Earlier quoted context omitted.
Wikipedia supports this: > Character 26 was used to mark "End of file" even if the ASCII calls it Substitute, and has other characters for this. Number 28 which is called "File Separator" has also been used for similar purposes. [1] I think today we would think of character 4 (End of Transmission, Ctrl-D) as the end of file/input marker, but historically Character 26/Ctrl-Z was used, even on disk. 1: https://en.wikip…
See, this is why you should not believe Wikipedia. The DOS syscall interface has no concept of an EOF character. ^Z being considered EOF was a feature of the COPY command, later replicated by the runtimes of various languages targetting DOS. http://jdebp.info/FGA/dos-character-26-is-not-special.html
EOF is not a character
71–80 of 136 posts
Re: EOF is not a character
#72Seems like the confusion arises because getchar() (or its equivalent in langauges other than c) can produce an out-of-band result, EOF, which is not a character. Procedural programmers don't generally have a problem with this -- getchar() returns an int, after all, so of course it can return non-characters, and did you know that IEEE-754 floating point can represent a "negative zero" that you can use for an error cod…
What does "Procedural" vs "Functional" have to do with this? It's a choice in data type. If by procedural you mean, nonsense, then sure... I agree that a function named `getchar` returning an `int` is procedural. :P
(Though by the way: having functions that evaluate to a value when executed is itself a feature that belongs to the functional paradigm, although one so trivial and common that it’s not usually thought as such. But a purely imperative/procedural way of returning values would be via out parameters or global variables.)
Re: EOF is not a character
#73Seems like the confusion arises because getchar() (or its equivalent in langauges other than c) can produce an out-of-band result, EOF, which is not a character. Procedural programmers don't generally have a problem with this -- getchar() returns an int, after all, so of course it can return non-characters, and did you know that IEEE-754 floating point can represent a "negative zero" that you can use for an error cod…
ISO C says that char must be at least 8 bits, and that int must be at least 16. It is entirely legal to have an implementation that has 16-bit signed char and sizeof(int)==1. In which case -1 is a valid char, and there's no way to distinguish between reading it and getting EOF from getchar().
Re: EOF is not a character
#74CP/M and DOS use ^Z (0x1A) as an EOF indicator. More modern operating systems use the file length (if available). Unix/Linux will treat ^D (0x04) as EOF within a stream, but only if the source is "cooked" and not "raw". (^D is ASCII "End Of Transmission or EOT" so that seems appropriate, except in the world of unicode.)
That is a common misconception. http://jdebp.info/FGA/dos-character-26-is-not-special.html
It was sometimes used to have TYPE print something human readable and stop before the remaining (binary) file data would scroll everything away
Re: EOF is not a character
#75Earlier quoted context omitted.
Well then try explaining ctrl+c vs ctrl+d to someone who's never touched a terminal at all. Starts off so easily... "see one tells the program to stop" the other, well, if you're in a shell... or some programs... oh god. IDK anymore, just assume it works. What was the question?"
it all depends on your stty settings. since I am more used to Windows where ctrl-c is copy, I followed other people's suggestion and mapped ctrl-x to do what ctrl-c usually does, with: stty intr ^X -ixon This is because X and C are very close, and I couldn't sacrifice ctrl-v (paste) or ctrl-z (background) while I seldom use ctrl-c I'm sure you could do the same with ctrl-d if you really wanted to.
Re: EOF is not a character
#76Like NULL, confusion over EOF is a problem which can be eliminated via algebraic types. What if instead of a char, getchar() returned an Option ? Then you can pattern match, something like this Rust/C mashup: match getchar() { Some(c) => putchar(c), None => break, } Magical sentinels crammed into return values — like EOF returned by getchar() or -1 returned by ftell() or NULL returned by malloc() — are one of C's dra…
”What if instead of a char, getchar() returned an Option ?” Getchar doesn’t return a char ; it returns an int ( https://en.cppreference.com/w/c/io/getchar ). ⇒ if C didn’t do automatic conversions from int to char , we would have that (in a minimalistic sense) That wouldn’t work for ftell and malloc (and, in general, most of the calls that set errno ), though.
Dammit, I knew that. Thank you for flagging my blunder; being precise is really important in this case. The Linux manpage better explains the return value of getchar:
https://linux.die.net/man/3/getchar
"fgetc(), getc() and getchar() return the character read as an unsigned char cast to an int or EOF on end of file or error."
getchar() needs to return an object the width of an unsigned char, but all the values in that range are taken by possible character values. The return type had to be expanded to int in order to accommodate the sentinel.
The alternative of using an algebraic type is superior because the end-of-stream condition has a different type (so to speak), and furthermore, the programmer has no choice but to deal with it because the character value comes wrapped inside an Option which must be stripped away before the character value can be used.
Really, you also want the type system to express all possible error conditions as well, since getchar() returning EOF can mean either that end-of-file was reached or that some other error occurred!
As someone who has written lots of C code and worked hard to account for all possibilities manually, I really appreciate it when the type system and APIs can express all possibilities and back me up.
Re: EOF is not a character
#77Like NULL, confusion over EOF is a problem which can be eliminated via algebraic types. What if instead of a char, getchar() returned an Option ? Then you can pattern match, something like this Rust/C mashup: match getchar() { Some(c) => putchar(c), None => break, } Magical sentinels crammed into return values — like EOF returned by getchar() or -1 returned by ftell() or NULL returned by malloc() — are one of C's dra…
That would be the textbook case of stupid over-engineering.
Re: EOF is not a character
#78Banged my head against the wall once after trying to figure out why Ctrl+D generates some character in bash but I can't send that character in a pipe to simulate termination.
Yes, you can. You just end your stream by closing the pipe.
Re: EOF is not a character
#79Like NULL, confusion over EOF is a problem which can be eliminated via algebraic types. What if instead of a char, getchar() returned an Option ? Then you can pattern match, something like this Rust/C mashup: match getchar() { Some(c) => putchar(c), None => break, } Magical sentinels crammed into return values — like EOF returned by getchar() or -1 returned by ftell() or NULL returned by malloc() — are one of C's dra…
> What if instead of a int, getchar() returned an Option ? That would be the textbook case of stupid over-engineering.
Re: EOF is not a character
#80Earlier quoted context omitted.
> What if instead of a int, getchar() returned an Option ? That would be the textbook case of stupid over-engineering.
I strongly disagree. The existing getchar() API is not simple at all! All the possible error conditions are still there, they're just obscured by an overstreamlined API which fuses them inappropriately into a single return type. That makes it harder to handle all cases well, because you have to do all the work manually.