user1661781
user1661781

Reputation: 327

Reading fixed amount of bytes in C?

I have to write an algorithm that can read three bytes of data at a time, as such:

For example, imagine the user inputs: Uof

Uof in binary would be presented as 01010101 01101111 01100110

I need help splitting this into four equal parts of six bits each, as such:

010101 (21)

010110 (22)

111101 (61)

100110 (38)

I'm only allowed to use ints. I can read the first character, shift it two to the right and get the result 21 no problem.

Getting the 22 makes no sense to me. Any pointers will help, don't need the exact solution, but what's something that can get me thinking?

Upvotes: 0

Views: 178

Answers (2)

Toribio
Toribio

Reputation: 4078

OK, first, we'll try to put the 3 bytes into a single integer. We'll use shift and OR logic. Suppose we have a, b and c input variables. (Uof would split into a, b and c respectively).

We first, add space for 1 more byte for the b variable:

(b << 8)

So 01101111 transforms to 0110111100000000.

Now we OR c into b, so the zeroes are actually c:

((b << 8) | c))

Now, we do the same logic with a. We reserve more 16 bits onto the right of a, so we can OR the last expression we obtained.

((a << 16) | ((b << 8) | c))

That far, we have all the bits merged into one single 4-byte integer.

We only need to split it now, into 4 parts of 6 bit each. We'll use the mask logic for this.

First, when we use the "mask" logic, we have to make the mask itself. Our mask is 0x3F (from the binary number 111111, i.e. six bits), so when we AND the number, with this mask, we can extract the first 6 bits on the right side:

r1 = (merged & 0x00003F);

Where r1 stands for result 1.

Now, the same thing, but with the merged number 6 bits to the right, so we can take the next 6-bit number, and so on with rest:

r1 = ((merged >> 0)  & 0x3F);
r2 = ((merged >> 6)  & 0x3F);
r3 = ((merged >> 12) & 0x3F);
r4 = ((merged >> 18) & 0x3F);

So, the final code would be:

char /*or int*/ a, b, c;
int merged, r1, r2, r3, r4;

scanf(" %c %c %c", &a, &b, &c);

merged = ((a << 16) | ((b << 8) | c));

r1 = ((merged >> 0)  & 0x3F);
r2 = ((merged >> 6)  & 0x3F);
r3 = ((merged >> 12) & 0x3F);
r4 = ((merged >> 18) & 0x3F);

printf("%d %d %d %d\n", r1, r2, r3, r4);

EDIT: I have corrected the mask part.

Upvotes: 0

Analog File
Analog File

Reputation: 5316

Ask yourself:

  • where do the 6 bits of each part come from?

  • how can I move bits to a different position in a value?

  • how can I combine two values so that only the interesting bits of each are taken?

To help you answer the third question you may also ask yourself:

  • how can I mask a value so that interesting bits stay what they are and non interesting bits all become 0s (or all become 1s)?

Upvotes: 1

Related Questions