For this assignment, you will write a C++ program called hw1
that reads integers from standard input, translates them to a serialized
format, and writes the two-digit hexadecimal form of the serialized
numbers to standard output, one per line.
We define a vnum, or variable-length number, as a two’s complement, variable number of bits (but always of the length 8n+4, where n≥0), prefixed by a four-bit length. The output will always be a whole number of bytes, or a multiple of eight bits.
You can consider the length nibble to be either:
For example, the number five, in binary, is 101_{2}. We need to pad that to a length of 8n+4. Since it’s three bits long, we pad it on the left to four bits: 0101_{2}. This requires no additional bytes, so the four-bit length is zero, or 0000_{2}. Put those together: 0000 0101_{2}, or 05_{16}.
The number three hundred, in binary, is 1 0010 1100_{2}. Padded to length 8n+4, that is 0001 0010 1100_{2}. This requires two bytes, or one additional byte, so the four-bit length is one, or 0001_{2}. Put those together: 0001 0001 0010 1100_{2}, or 112c_{16}.
The number negative one, in two’s complement binary, is 1111_{2}. This requires no additional bytes, so the four-bit length is zero, or 0000_{2}. Put those together: 0000 1111_{2}, or 0f_{16}.
A vnum must always be the represented using the minimum number of bytes. For example, seven must serialize as 07_{16}, not as 30 00 00 07_{16}.
A one-byte vnum (-8 ≤ n < 8) | |||||||
---|---|---|---|---|---|---|---|
byte #1 | |||||||
length | bits | ||||||
0 | 0 | 0 | 0 | b_{3} | b_{2} | b_{1} | b_{0} |
A two-byte vnum | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
byte #1 | byte #2 | ||||||||||||||
length | bits | ||||||||||||||
0 | 0 | 0 | 1 | b_{11} | b_{10} | b_{9} | b_{8} | b_{7} | b_{7} | b_{5} | b_{4} | b_{3} | b_{2} | b_{1} | b_{0} |
A three-byte vnum | |||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
byte #1 | byte #2 | byte #3 | |||||||||||||||||||||
length | bits | ||||||||||||||||||||||
0 | 0 | 1 | 0 | b_{19} | b_{18} | b_{17} | b_{16} | b_{15} | b_{14} | b_{13} | b_{12} | b_{11} | b_{10} | b_{9} | b_{8} | b_{7} | b_{6} | b_{5} | b_{4} | b_{3} | b_{2} | b_{1} | b_{0} |
In these examples, b_{0} is the least significant bit (LSB), b_{1} is next most significant bit, etc.
The four-bit length field has a maximum value of 15, so this scheme can only store a 16-byte, or 124-bit number.
Here are several sample runs, where %
is my prompt.
What you type looks like this.
Your output must match exactly. Ignore the indentation.
% make make output appears here % echo '5 300 -1 1 2 -3 40 500' | ./hw1 5: 05 300: 11 2c -1: 0f 1: 01 2: 02 -3: 0d 40: 10 28 500: 11 f4 % ./hw1 -6000 -6000: 2f e8 90 70000 70000: 21 11 70 1000000000 1000000000: 40 3b 9a ca 00 control-D %
// Emit two-digit hexadecimal. int n = 200; cout << "decimal: " << dec << n << '\n' << "hex: " << hex << setw(2) << setfill('0') << (n & 0xff) << '\n';
decimal: 200 hex: c8
<stdio.h>
or <cstdio>
facilities,
such as printf
, scanf
, fopen
, and getchar
.
cout
, and ifstream
.
int
.
If you have any questions about the requirements, ask. In the real world, your programming tasks will almost always be vague and incompletely specified. Same here.
hw1.tar
*.cc
)
*.h
) (if any)
Makefile
, with a capital M
)
Makefile
’s default target must create the executable file
hw1
.
Makefile
must use at least -Wall
when compiling.
~cs253/bin/checkin HW1 hw1.tar
Turn in someone else’s work.