Wojtek Wojtek - 21 days ago 4
C Question

Trailing newline character

I have a text file with 32 binary numbers, each one is in separate line and each number is 8 characters long. I want to store them in the

mem
array as strings.

Right now, this code looks like this:

char mem[32][9];
char line[9];

FILE *file_pointer;
file_pointer = fopen(filename, "r");

if (file_pointer == NULL) {
printf("Failed to open file \"%s\"!", filename);
} else {
int i = 0;
while (fgets(line, sizeof line, file_pointer)) {
memcpy(mem[i], line, 8);
mem[i][8] = '\0';
i++;
}
}
fclose(file_pointer);


Unfortunately I still get newline characters in
line
, so my array is not displaying properly.

This is my console when I am printing the array:

00 00110100
01

02 01111100
03

04 10011100
05

06 10010101
etc...


My code for printing the array:

for (i = 0; i < 32; i++) {
if (i >= 10) {
printf("%d", i);
} else {
printf("%c%d", '0', i);
}
printf("\t%s\n", mem[i]);
}


I tried also using:

strtok(line, "\n");

line[strcspn(line, "\r\n")] = '\0';

Answer

Some notes about your code:

  • You must make line longer so fgets() can read the '\n' into line. Currently it breaks each line into an 8 byte chunk and an empty line with the newline character.

  • You should prevent the while loop from reading beyond the end of the array.

Here is an improved version

    char mem[32][9] = { 0 };
    char line[80];

    FILE *file_pointer = fopen(filename, "r");

    if (file_pointer == NULL) {
        fprintf(stderr, "Failed to open file \"%s\"!\n", filename);
    } else {
        int i = 0;
        while (i < 32 && fgets(line, sizeof line, file_pointer)) {
            strncat(mem[i], line, 8);
            i++;
        }
        if (i < 32) {
            fprintf(stderr, "Missing values in file \"%s\": found %d lines\n",
                    filename, i);
        }
        fclose(file_pointer);
    }

You could also simplify the printing code this way:

    for (int i = 0; i < 32; i++) {
        printf("%02d\t%s\n", i, mem[i]);
    }

Note that if you are certain about the file format, you can simplify the reading code this way:

    char mem[32][9];
    char line[80];

    FILE *file_pointer = fopen(filename, "r");

    if (file_pointer == NULL) {
        fprintf(stderr, "Failed to open file \"%s\"!\n", filename);
    } else {
        if (fread(mem, 9, 32, fp) != 32) {
            fprintf(stderr, "Missing bytes in file %s\n", filename);
        } else {
            for (int i = 0; i < 32; i++) {
                mem[i][8] = '\0';
            }
        }
        fclose(file_pointer);
    }

You might also want to verify that the strings in mem[] contain exactly 8 hexadecimal digits with a simple loop and using the isxdigit() function from <ctype.h>:

            for (int i = 0; i < 32; i++) {
                int j;
                for (j = 0; j < 8; i++) {
                    if (!isxdigit((unsigned char)mem[i][j])
                        break;
                }
                if (j != 8 || mem[i][8] != \n') {
                    fprintf("invalid data on line %d\n", i + 1);
                }
                mem[i][8] = '\0';
            }