1
int n = NMAXVAL;
char line[MAXLINE];
int rowCount = 0;
char* token = NULL;

while (rowCount < n && fgets(line, MAXLINE, stdin))
{
    token = strtok(line, " ");
    checkToken(token, n);
    // do something
    rowCount++;
}

My function reads from stdin line by line and performs some tasks. It works fine for me on Visual Studio. However, it acts differently on xcode. It took a while for me to realize that this is caused by the difference between \n, \r, and \n\r. How do I make my code support these newline chars?

update: consider this input:

1
10
3 4
5 6 7

On visual studio, the function reads line by line. However, on Xcode it reads the first line just fine then it reads \n instead 10\n.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 4
    You can add `\r` and `\n` to the token separator in `strtok` : `token = strtok(line, " \r\n");` to ignore them. – rochard4u Aug 22 '22 at 10:14
  • This may help https://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input . – Askold Ilvento Aug 22 '22 at 10:30
  • 1
    I'm not aware a system that uses the `\n\r` sequence. Windows uses `\r\n` natively (and so do many internet protocols), and the standard I/O library on Windows maps `\r\n` to just newline when the file is processed as a text file. Old Macs (essentially those from the last millennium, not those running any version of macOS X) used just `\r`. There is no universal line ending; there is no standard C function that handles all line endings. – Jonathan Leffler Aug 22 '22 at 14:05
  • If you are tokenizing on whitespace, why do you care about line boundaries at all? Surely you aren't parsing a language in which `\t`, `\n`, and `\r` are not treated the same as a space. The only languages that do that are intentionally designed to be pathological. – William Pursell Aug 22 '22 at 14:06
  • @user3121023 stdin – Tiehan Jiang Aug 22 '22 at 17:30
  • The full classic whitespace characters are " \r\n\f\t\v" as [isspace](https://en.cppreference.com/w/c/string/byte/isspace). – Neil Aug 22 '22 at 18:02

1 Answers1

0

On visual studio, the function reads line by line. However, on xcode it reads the first line just fine then it reads \n instead 10\n.

The problem is not fgets(). This problem is the same exact file is treated as different text files on different platforms.

A simply solution is to create each text file, separately, on each platform using that platform's end-of-line convention.

Alternatively and harder, to read the same exact file on different platforms, create your own line read function that ID's an end-of-line in the various ways. Depending on goals, code may need to (re-)open the file in binary.

Alternatively and meets many cases, open the file in text mode (as stdin does), use fgets() and strip various line endings off.

if (fgets(line, sizeof line, stdin)) {
  line[strcspn(line, "\n\r")] = '\0'; // truncate after first of \n, \r or \0
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256