views:

385

answers:

6

Does fgets on a mac read until a carriage return '\r' or does it also depend on the new line '\n'?

Reason is I am using fgets to read a file a line at a time. However if it is run on a mac file with only '\r' for the line ending it fails to do what I want. (run in linux)

I don't want to be writing library type functions to deal with cross compatibility issues. Is there another standard function that I could use instead?

A: 

The C library on the Mac should 'do the right thing'.

BTW Linux and Mac both use \n as line terminator, not \r

pm100
Program is not running on a Mac, and the file apparently has CRs, regardless of where it came from.
Carl Smotricz
ha! i didn't realise mac switched from CR to LF, but they did.
Matt Joiner
@Anacrolix - Mac switched to LF as of OS X (the version based on Darwin).
R Samuel Klatchko
+1  A: 

Are you talking about MacOS X or MacOS 9 (or earlier)?

  • On MacOS 9 or earlier, the library would stop at the '\r'.
  • On MacOS X, the line terminator is '\n', just as in any other Unix system.
Jonathan Leffler
Irrelevant, as his program is running under Linux. Trick question ;)
Carl Smotricz
Yes - so I see...oh well... :( Well, actually, the first paragraph or question is about fgets() on a Mac. There is then a change of tack to ask about reading Mac files on Linux. If it came off a MacOS X Mac, then it will contain newlines and not carriage returns. Since it then mentions that fgets() on Linux doesn't behave as expected - and asks whether there is some function other than fgets() that could be used instead. There isn't a truly standard alternative - the GNU C Library alternative of getdelim() is reasonable for Linux, but is not cross-platform.
Jonathan Leffler
+3  A: 

Oh wait, I missed the "run on linux" with "a mac file having CR".

OK, the answer is: The fgets() documentation explicitly refers to "newline" as the line terminator. Especially Unix/Linux implementations cannot be expected to have heard about the old Mac's notion of CR as a line terminator; so it's not surprising fgets doesn't see those CRs as line ends.

Update:

My strong recommendation to avoid most of the issue is to use a command line utility such as tr to just translate the file before you throw your program at it.

Carl Smotricz
+2  A: 

If you're strictly adhering to C, you could try using getdelim() if it's available on your system.

Matt Joiner
best option I think, if the mac guy doesn't have GnuC then that is just too bad, or he can come up with a better patch.
Tanj
+1  A: 

Are you willing to change your code just to deal with Mac-style line endings? Will you never deal with normal Unix line endings? Or do you want a function that accepts either style? That isn't reasonable.

Why not just pipe all questionable files through TR to change the CR to LF, and then read the pipe. No need to create additional files. Whether the original file had CRs or not, the code will work with standard fgets.

gary
+1, I second the suggestion.
Carl Smotricz
+1  A: 

When the Mac moved from Mac OS 9 to Mac OS X, the line ending convention changed from lines terminated with \r to \n, as Mac OS X is built on top of BSD, in which \n is the conventional newline. Thus, even on a Mac, fgets will parse lines delimited by \n, not \r.

I believe that if you want to parse lines delimited by \r, you will have to do so yourself, or convert the files to \n line endings in advance.

Brian Campbell
I think you'd win that bet, +1.
Carl Smotricz