1

The storage representation of the string or equivalently text from a file, is the ASCII code for each character of the string or text from a file, I have been told that I/O functions like fread and fgets will read a string from disk into memory without conversion. The C compiler always works with the storage representation, so when we "retrieve" a string in C, it's always in binary form.

I need to access this binary form to use in my code (without saving this as a binary file, also not asking to print in binary format).

For example, the text string "AA" is saved in memory as "0100000101000001", I need to access directly, without any conversion (like we do when we print, integer using %s, %d) this binary form "0100000101000001" of "AA" using an integer array, say, D[16] which has elements 0,1,0,0,0,0,0,1,0,1,0,0,0,0,0,1. So if I use an index int i, I will get 0 from D[4] for i=0.

Array-index operations like buffer[i] (for example, in the sample code in the below) will extract one character from a string:

FILE *fp = fopen("a.txt", "r");
if (fp == NULL)
    return 1;

char buffer[100];
int r = fread(buf, 1, sizeof(buffer), fp);
if (r <= 0)
    return 1;

printf("As string: %.*s", r, buffer);

printf("As integers:");
for (i = 0; i < r; i++)
    printf(" %d", buffer[i]);

But I would like to have the complete text as an array of 0 and 1, whereas here, buffer[i] contains 8 bits which I cannot access individually each bit, how can I do that?

4
  • Two loops, one nested inside the other: Outer loop per byte, inner loop per bit. How to print the bits of a byte I leave as an exercise to the reader. Commented Jul 15, 2022 at 12:04
  • @Someprogrammerdude how do I access each bit of buffer[i], I am new, what is the syntax? Commented Jul 15, 2022 at 12:42
  • the short answer is that you can't directly access bits using array notation like buffer[i]. that being said, the following code will have the value of bit n of the array, assuming buffer is an array of 1-byte values: (buffer[n/8] >> (n%8)) & 1. look up "C bit operations" if you want to understand this statement better. also, this wont give you '0' and '1' as characters, it will just give you the value of the bit. Commented Jul 15, 2022 at 13:31
  • Now seems the time to invest in a beginners C book or two. There are also plenty of tutorials online about how to handle bits in C, but try to avoid general "learn C the easy way" kind of tutorials, try to search for narrow tutorials discussing only a specific subject (they tend to be better). Commented Jul 15, 2022 at 13:46

2 Answers 2

1

I have been told that I/O functions like fread and fgets will read a string from disk into memory without conversion.

This is true if the file has been open as binary, ie: with "rb". Such streams do not undergo any translation when read into memory, and all stream functions will read the contents as it is stored on disk, getc() included. If your system is unix based, there is no difference with "r", but on legacy systems, there can be substantial differences: text mode, which is the default, may imply end of line conversion, code page translation, end of file mitigation... If you want the actual file contents, always use binary mode ("rb").

You should also avoid the char type when dealing with binary representation, because char is signed by default on many architectures, hence inappropriate for byte values which are usually considered positive. Use unsigned char to prevent this issue.(*)

The most common way to display binary contents is using hexadecimal representation, where each byte is output as exactly 2 hex digits.

If you want to output binary representation, there is no standard printf conversion to output base-2 numbers, but you can write a loop to convert the byte to its bit values.


(*) among other historical issues such as non two's complement signed value representations

Here is a modified version:

#include <stdio.h>

int main() {
    FILE *fp = fopen("a.txt", "r");
    if (fp == NULL) {
        perror("a.txt");
        return 1;
    }
    unsigned char buffer[100];
    unsigned char bits[100 * 8];
    int r = fread(buffer, 1, sizeof(buffer), fp);
    if (r <= 0) {
        fprintf(stderr, "empty file\n");
        fclose(fp);
        return 1;
    }
    
    printf("As a string: %.*s\n\n", r, (char *)buffer);
    int pos;
    pos = printf("As 8-bit integers:");
    for (int i = 0; i < r; i++) {
        if (pos > 72) {
            printf("\n");
            pos = 0;
        }
        pos += printf(" %d", buffer[i]);
    }
    printf("\n\n");
    
    pos = printf("As hex bytes:");
    for (int i = 0; i < r; i++) {
        if (pos > 72) {
            printf("\n");
            pos = 0;
        }
        pos += printf(" %02X", buffer[i]);
    }
    printf("\n\n");
    
    pos = printf("Converting to a bit array:");
    for (int i = 0; i < r; i++) {
        for (int j = 8; j-- > 0;) {
            bits[i * 8 + 7 - j] = (buffer[i] >> j) & 1;
        }
    }
    /* output the bit array */
    for (int i = 0; i < r * 8; i++) {
        if (pos > 72) {
            printf("\n    ");
            pos = 4;
        }
        pos += printf("%d", bits[i]);
    }
    printf("\n");
    fclose(fp);
    return 0;
}
Sign up to request clarification or add additional context in comments.

3 Comments

Hello again! I have a trivial question if you can answer: is it possible to use fread function directly without storing it to an array like you did in fread(buffer, 1, sizeof(buffer), fp);? Thanks.
@Michael: no, fread must be given a valid pointer to an array at least long enough to receive the data read from the stream. You can read data from the stream without storing it with getc, but it is usually less efficient than fread for large numbers of bytes. There is a contorted alternative using fscanf(): fscanf(fp, "%*10000c") will read and discard 10000 bytes from the stream.
The number of bytes must be explicit so you must construct the string with snprintf() if you want to read a discard a variable number of bytes: void skip(FILE *fp, int count) { char buf[20]; snprintf(buf, sizeof buf, "%%*%dc", count); fscanf(fp, buf); }
0

Use bit masking to check the value of individual bits. Checkout a brief description here https://www.learn-c.org/en/Bitmasks

Then you can write the result to your array for the corresponding bit.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.