Stripping newline character causes problems reading batchfile in c

Viewed 32
FILE *in_file  = fopen("batchfile", "r"); // read only
while( fgets (buf, MAX_BUFFER, in_file)!=NULL )
{
    buf[strcspn(buf, "\n")] = 0;
    printf("%s ", buf);
}

When I try to run this code without the buf[strcspn(buf, "\n")] = 0;, line, it runs properly and prints out the 3 lines of text in my batchfile. When I add this line to strip the newline character it only prints the last line of my file. Anyone know why this is happening?

1 Answers

Windows represents line breaks as the two-character sequence CR, LF (carriage return, line feed). Most other systems represent line breaks as a simple LF. In C, a CR is '\r' and a LF is '\n'.

When you open a text file on Windows (fopen without the b flag), the CR-LF sequence is converted into a simple '\n'. When you open a text file on Unix-like systems (including Linux, macOS, and some ports of Unix development tools to Windows), a CR is just an ordinary character. So if you read a Windows text file on Unix and you want to remove the line breaks, you need to remove both the '\n and the preceding '\r'.

Many terminals interpret LF as “go to the beginning of the next line” and CR as “go to the beginning of the current line”. So if you read and print a Windows text file, the CR characters are effectively invisible. If you read and print a Unix text file but remove the LF characters, the lines come out concatenated together without breaks. If you read and print a Windows text file, and you remove the LF characters but you keep the CR characters, each line overwrites the previous line. You can watch that happening stepping through your program in a debugger, or by adding fflush(stdout); sleep(1); after each printf call.

To support both Unix and Windows line endings, check if there's a '\r' before the '\n' and remove it.

size_t len = strlen(buf);
if (len > 0 && buf[len-1] == '\n') buf[--len] = 0;
if (len > 0 && buf[len-1] == '\r') buf[--len] = 0;
Related