C/C++ Arena

Step 2 of 8

Reading lines with fgets

Text files are usually processed line by line. The safe way to read a line is fgets:

char line[256];
fgets(line, sizeof line, f);

It reads characters until the end of the line (and keeps the '\n'), or until the buffer is full, or until the end of the file. It never writes more than sizeof line bytes, so a very long line can't overflow the array; it just arrives in pieces. It returns NULL when there's nothing left, which makes it a natural loop condition.

#include <stdio.h>
#include <string.h>

int main(void) {
    FILE *f = fopen("words.txt", "w");
    if (!f) return 1;
    fputs("alpha\nbe\ngamma ray\n", f);
    fclose(f);

    f = fopen("words.txt", "r");
    if (!f) return 1;
    char line[64], shortest[64] = "";
    int count = 0;
    while (fgets(line, sizeof line, f) != NULL) {
        line[strcspn(line, "\n")] = '\0';
        count++;
        if (count == 1 || strlen(line) < strlen(shortest)) {
            strcpy(shortest, line);
        }
    }
    fclose(f);
    printf("%d lines, shortest: %s\n", count, shortest);
    return 0;
}
3 lines, shortest: be

Removing the newline

Because fgets keeps the '\n', you usually want to cut it off before using the line. strcspn(line, "\n") returns the position of the first '\n', or the string's length if there isn't one (for example, a last line without a newline), so line[strcspn(line, "\n")] = '\0'; removes it safely in every case.

Keeping a copy

line is overwritten by every fgets call, so to remember a line (like the longest so far), copy it into a separate array with strcpy. Storing a pointer to line would just point at whatever was read last.

Your turn: the folder contains maps.txt. Print how many lines it has and the longest line (the first one, if there's a tie).

Previous: Write a file, read it back Next: When fopen fails