0

I am working on the infamous book "Prentice Hall Software Series" and trying out the Code they write and modifying it to learn more about C.

I am working with VIM on Fedora 25 in the console. The following code is a quote from the book, I know "int" is missing as well as argc and argv etc.

Kernighan and Ritchie - The C Programming Language: Page 20

#include <stdio.h>
/* copy input to output; 1st version  */   
main(){       
    int c;
    c = getchar();       
    while (c != EOF) {           
        putchar(c);           
        c = getchar();       
    }   
}

With this code I couldn't manage to get the "EOF" to work. I am not sure if "ctr + z" really is the real thing to do, since it quits any console program in console.

Well since I was unsure i changed the condition to

...
while (c != 'a') {
...

So normally if I enter 'a' the while condition should break and the programm should terminate. Well it does not when I try to run it and enter 'a'. What is the problem here?

Thank you guys!

HDJEMAI
  • 9,436
  • 46
  • 67
  • 93
  • 1
    ctrl+z is EOF on windows. For a Unix it's ctrl+d – StoryTeller - Unslander Monica Mar 14 '17 at 10:05
  • 2
    First thing to learn about C: **int main**. – n. m. could be an AI Mar 14 '17 at 10:05
  • 2
    i know it is actually "int main(int argc, char *argv[]) I quote the book, it is written that way, so please bare with me. –  Mar 14 '17 at 10:06
  • 2
    Get a better book. It's better to learn things properly the first time, then needing to unlearn them later. – StoryTeller - Unslander Monica Mar 14 '17 at 10:07
  • 3
    @n.m. Sir, to nitpick, `int main(void)`.. :) – Sourav Ghosh Mar 14 '17 at 10:07
  • 1
    Please answer the actual question, and I don't see how Kernigan and Ritchie's book on C should be a bad book, Ritchie was one of the inventors of C –  Mar 14 '17 at 10:08
  • @ThomasChristopherDavies This does not mean that someone should start Learning now `C` using that OLD book. – Michi Mar 14 '17 at 10:09
  • 2
    C changed a great deal since K&R wrote their book. Even their book on ANSI C contains code samples that will break in modern compilers that adhere to the current revision of the C standard. – StoryTeller - Unslander Monica Mar 14 '17 at 10:09
  • i think you should use `char c` .. – Ankur Jyoti Phukan Mar 14 '17 at 10:11
  • 2
    @AnkurJyotiPhukan - That will be wrong. – StoryTeller - Unslander Monica Mar 14 '17 at 10:11
  • In K&R C, the default return type for a function is int so `main()` is the same as `int main()`. We don't do that anymore. – JeremyP Mar 14 '17 at 10:11
  • @AnkurJyotiPhukan You should read about getchar – Michi Mar 14 '17 at 10:11
  • 2
    It is not the first book, and I really just want to understand the problem with getchar(). I don't want to have a discussion about the book, since I know that it is old and has its flaws. It is additional lecture for me. I am reading 4 books right now about C. A very recent one "Learn C The Hard Way", two german books and this one. Please answer my question –  Mar 14 '17 at 10:11
  • @SouravGhosh what you can put inside the parentheses is a matter of debate. Some people say the standard doesn't sanction `()`. I don't think so. – n. m. could be an AI Mar 14 '17 at 10:12
  • Did you try ctrl+d instead of ctrl+z or not? – StoryTeller - Unslander Monica Mar 14 '17 at 10:12
  • Well what about the character 'a' from the modified code? Why does it not terminate when I enter 'a' when I have it conditioned to break the loop when entered? –  Mar 14 '17 at 10:13
  • 1
    @n.m. The only valid signature for `main` are `int main(void){}` and/or `int main(int argc, char *argv[]){}` and that is what should be used – Michi Mar 14 '17 at 10:14
  • 1
    @ThomasChristopherDavies the input is line buffered so won't start processing your characters until you hit enter – Chris Turner Mar 14 '17 at 10:15
  • Your problem is non-reproducible http://ideone.com/oWiUNy – StoryTeller - Unslander Monica Mar 14 '17 at 10:15
  • Okay, with enter it terminates, i didn't really get why enter is actually needed –  Mar 14 '17 at 10:17
  • 2
    @ThomasChristopherDavies, read about [Canonical vs. non-canonical terminal input](http://stackoverflow.com/q/358342/1606345) – David Ranieri Mar 14 '17 at 10:18
  • @Michi the standard says a function *definition* with `(void)` is equivalent to that with `()`. It doesn't say "... except when defining `main`" anywhere as far as I know. The *signature* of such function remains `int (void)` regardless of the way you spell the definition. – n. m. could be an AI Mar 14 '17 at 10:26
  • 2
    See my expanded explanation for why enter is needed. – JeremyP Mar 14 '17 at 10:31
  • @Michi It looks like the standard doesn't actually say so (to my utter disappointment). – n. m. could be an AI Mar 14 '17 at 10:47
  • 1
    @n.m. The difference between `int foo()` and `int foo(void)` is that you can call the former with any arguments you like (they will be ignored) but it is an error to call the latter with any arguments. – JeremyP Mar 14 '17 at 11:49
  • @JeremyP *they will be ignored* There doesn't seem to be wording in the standard to this effect I believe the result would be undefined behaviour. Most implementation will let you supply extra arguments to an old style function but I don't think this was ever codified. – n. m. could be an AI Mar 14 '17 at 12:21
  • @n.m. the standard actually says an empty parameter list means "no information about the number or types of parameters is supplied" (6.7.6.3). In practice on my version of clang, it is the difference between a warning and an error. – JeremyP Mar 14 '17 at 12:27
  • @JeremyP "If the expression that denotes the called function has a type that does not include a prototype ... If the number of arguments does not equal the number of parameters, the behavior is undefined". "No information" doesn't mean "anything goes". – n. m. could be an AI Mar 14 '17 at 12:27
  • @n.m. Yes but undefined behaviour is different to error. If the function declaration says `int foo(void)` and you call it like this `int bar = foo(5);` it is not undefined behaviour, it is an error. – JeremyP Mar 14 '17 at 12:30
  • @JeremyP no argument about that. The only issue is with a **definition** (not just any declaration) that has an empty parameter list. – n. m. could be an AI Mar 14 '17 at 12:31

1 Answers1

2

There's nothing wrong with the code (except the archaic declaration of main).

Usually, on Unixes end of file is signalled to the program by ctrl-D. If you hit ctrl-D either straight away or after hitting new-line, your program will read EOF.

However, the above short explanation hides a lot of subtleties.

In Unix, terminal input can operate in one of two modes (called IIRC raw and cooked). In cooked mode - the default - the OS will buffer input from the terminal until it either reads a new line or a ctrl-D character. It then sends the buffered input to your program.

Ultimately, your program will use the read system call to read the input. read will return the number of characters read but normally will block until it has some characters to read. getchar then passes them one by one to its caller. So getchar will block until a whole line of text has been received before it processes any of the characters in that line. (This is why it still didn't work when you used a).

By convention, the read system call returns 0 when it gets end of file. This is how getchar knows to return EOF to the caller. ctrl-D has the effect of forcing read to read and empty buffer (if it is sent immediately after a new line) which makes it look to getchar like it's reached EOF even though nobody has closed the input stream. This is why ctrl-D works if it is pressed straight after new line but not if it is pressed after entering some characters.

JeremyP
  • 84,577
  • 15
  • 123
  • 161
  • thank you for this very insightful explenation, this makes now perfectly sense! –  Mar 14 '17 at 10:34