CSCI 241 - Homework 4: Bits are bits

Due by 11:59.59pm Tuesday, October 25

Introduction

In this lab you will get experience dealing with data on the binary level. You will also have to deal with static local variables and using global variables. In addition, you’ll be expected to use conditional compilation via a Makefile, creating header files, etc.

You will work with a partner on this assignment.
It is expected that you work together and equally contribute to the development of your solution. Also, you are both responsible for understanding how your solution works. You need only submit one assignment per group, but clearly indicate your partnership in the README and comments for files. You should play with collaborating on github as you are doing this.

The URL for the github repository for this account is https://classroom.github.com/a/LD7tDRBS

Part 1 - converting data to binary and back

In this part, you will be creating 2 programs. encode_bits which will generate the “binary” representation of a file and decode_bits which will take that representation and convert it back to the original format.

encode_bits

Create a program called encode_bits. This program should use getchar() to read in characters one at a time and then call print_bits() (see below) to output that character as a sequence of ‘1’ and ‘0’ characters. It should stop on EOF.

decode_bits

Create a program called decode_bits. This program should use getchar() to read in characters one at a time and then call decode_bits() (see below) to output that sequence of ‘1’ and ‘0’ characters as actual characters. It should stop on EOF.

bits.c & bits.h

Create a file called bits.c that contains the following two functions and a header file bits.h that contains a guard against multiple inclusion, other needed includes, and function prototypes.

void print_bits(int ch)

Takes the character ch and outputs its value in binary format with all leading zeros and with the MSB first. For example, the letter ‘A’ has a value of 0x41, and should be output as 01000001. A newline character has a value of 0x0a and should be output as 00001010.

You should not assume the number of bits that are in a char, instead use the constant CHAR_BIT from limits.h.

void decode_bits(int ch)

If the character is whitespace, skip it. (You might want to use isspace() in ctype.h.)

If the character is a ‘1’ or a ‘0’, you should add it into an output buffer (numerically, shifting the current contents appropriately). Once you’ve seen CHAR_BIT bits, you should print the corresponding character out.

If the character is neither white space, nor a binary digit, you should print a message to the screen, and then use exit() to quit your program with a non-zero value.

Programming hints for part 1

You’ll probably need to use static local variables to handle decode_bits since it only prints out a character every CHAR_BIT calls to it.

Don’t forget to make rules in your Makefile include the correct compilation. bits.o should be the dependency for the two other programs, and you should have a separate rule for its compilation.

Part 2 - Number Transformation

For the second part, you will be creating a function to read in a positive integer value and storing the result in a long integer variable. You will also be creating 4 short programs that will use that function to read in integers and output them in one of 4 different formats – binary, decimal, octal, or hexadecimal.

reading in a number

Create a file called getnum.c and another called getnum.h. In getnum.c you will create the function getnum() that is used by your other programs.

long getnum(void) Read in a positive integer in one of 4 formats described below and then return the value.

Skip leading whitespace and stop reading in a number on the next occurrence of whitespace.

If the integer read is invalid, somehow signal the caller that the value returned is not valid. I’d suggest you consider a global variable.

If the input is invalid, skip to the next whitespace in the input or EOF.

You might find it useful to “unread” a character. You can do so using ungetc(ch, stdin); where “ch” is the character you just read. Note that you can only un-read one character at a time until you read in a new character.

Building a state diagram like the one below might be useful in visualizing the behavior of this function. Note: The image includes the case for negative numbers, which are not part of the main assignment.

state machine

Printing out a number

You will then create 4 short programs that will read in a sequence of number and then output them one per line in a specified format. All 4 will be using sign-magnitude format. (If negative, print out the sign and then the rest as if it were positive – important for binary.)

In the event that the integer being read is invalid, simply print “ERROR” to the screen.

Loop until no more integers remain.

Programming hints for part 3

Don’t forget to add these targets into your Makefile.


The rest of the info

Sample program

I’ve included my sample solution in ~rhoyle/pub/cs241/hw4/ with binaries that should work on the lab machines.

decode_bits should exactly undo encode_bits. For example, you should get no output from the following:

% ./encode_bits < ./encode_bits | ./decode_bits > output 
% diff -q encode_bits output 

You can also chain together the base transformation if you like

% echo 32767 0xffff 071 0b101 cat | ./tobinary | ./tohex | ./tooctal | ./todecimal 
32767
65535
57
5
ERROR

Extra Credit

Read in a flag on the command line that specifies the base for the output. It should be one of:

Note, your output, if octal, should be the regular number without the leading 0. The number, if hex, should be the regular number without the leading 0x. You will need to modify both encode_bits and decode_bits for full credit, as you’ll need to be able to decode each type of encoding. Handle negative numbers

README

As with the first project, I want you to create a file called README

Submission

Now you should make clean to get rid of your executables and commit your folder containing your source files, README, and Makefile through git, as you did in last week’s assignment. For a refresher, refer to those instructions.

Grading

Here is what I am looking for in this assignment:


Last Modified: October 07, 2022 - Roberto Hoyle, with material from Ben Kuperman