Search code examples
cansi-c

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';

Solution

  • 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';
                }