0

I'm doing homework for my C programming class. The question states "Write a program which reads input as a stream of characters until encountering EOF". I'm using Xcode on my macbook and the only way I know to make the program encounter EOF is using ctrl + D or ctrl + Z. But it will exit my program completely.

For example I have this code:

int main()
{
    int ch;
    while ((ch = getchar()) != EOF)
    {
        putchar(ch);

    }
    printf("%d",ch);
    return 0;
}

Is there away for the code to execute the printf("%d",ch) after the loop (after i hit ctrl + D on my keyboard)?

skaffman
  • 398,947
  • 96
  • 818
  • 769
Dat Tran
  • 159
  • 3
  • 12
  • 1
    You'll have to press Enter at least once before hitting Ctrl-D. – Crowman Mar 16 '15 at 11:27
  • @PaulGriffiths is it really so? – Sourav Ghosh Mar 16 '15 at 11:32
  • @dattran it should print -1 or something. are you sure you're not missing the o/p because of lack of a `\n` in the print statement? – Sourav Ghosh Mar 16 '15 at 11:33
  • i tried and it doesn't work. everytime i use ctrl + D to input the EOF there's a -1 and it exits my program – Dat Tran Mar 16 '15 at 11:34
  • `EOF` **is** `-1`. So what would expect `printf("%d",ch);` to print out? – alk Mar 16 '15 at 11:37
  • The ascii number of the inputs – Dat Tran Mar 16 '15 at 11:40
  • 4
    It's outputting the code of the **last** input character, which happens to be EOF, hence -1. – undur_gongor Mar 16 '15 at 11:41
  • 1
    To print the ascii number of the inputs change `putchar(ch);` to `printf("%d," ch);` – David Ranieri Mar 16 '15 at 11:45
  • yes i'm running from a command line. – Dat Tran Mar 16 '15 at 12:01
  • @DatTran Your program does what your homework says to do. It reads input from the stdin stream until an EOF is encountered. When you don't redirect the input from a file or something, then it is up to you to type in the input at the terminal and to indicate when you are done with a ctrl-D. :) – jschultz410 Mar 16 '15 at 12:05
  • Your program is executing the `printf("%d", ch);` If your IDE is popping up a window to run your program and then quickly closing it when the program exits, then you could change your printf to be `printf("\n%d\n", ch);` (which will always print -1, btw) and then put a call to `pause();` (you'll need to #include ) at the end of your program just before you return from main. That will cause it to pause until you send it a signal (e.g. - ctrl-C). If you are running from the command line of a shell, then you shouldn't need this. – jschultz410 Mar 16 '15 at 12:18

4 Answers4

2

You can test your program using (with a POSIX shell) here documents.

First compile your source code mycode.c into a binary mybin with

 gcc -std=c99 -Wall -Wextra -g mycode.c -o mybin

(it could be clang or cc instead of gcc)

then run mybin with a "here document" like

 ./mybin << EOF
    here is my 
    input
 EOF

You could also use input redirection. Make some file myfile.txt and run ./mybin < myfile.txt

You could even run your program on its own source code: ./mybin < mycode.c

And the input could even come from some pipe, e.g. ls * | ./mybin

BTW, what you are observing is that stdin, when it is a terminal, is line-buffered. See this answer (most of it should apply to MacOSX).

Notice that your code is incorrect: you are missing an #include <stdio.h> near the top of the file, and your main should really be int main(int argc, char**argv) (BTW you could improve your program so that when arguments are given, they are file names to be read). At last the ending printf would surely show -1 which is generally the value of EOF

Also, it is much better to end your printf format control string with \n or else use appropriately fflush(3)

Notice that end-of-file is not an input (or a valid char), it is a condition on some input file stream like stdin, and the getchar(3) function is specified to return EOF which is an int outside of the range of char (on my Linux system EOF is -1 because char-s are between 0 and 255 included). You might test end-of-file condition after some input operation (never before!) using feof(3)

A terminal in usual cooked mode is handled by the kernel so that when you press Ctrl D an end-of-file condition is triggered on the file descriptor (often STDIN_FILENO i.e. 0) related to that terminal.

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
2

I'm using Xcode on my macbook and the only way I know to make the program encounter EOF is using ctrl + D or ctrl + Z. But it will exit my program completely.

No it won't. If you run your program in the Xcode debugger, provided the console pane has the focus, all input you type will go to your program (note that, by default, stdin is line buffered, so you'll only see output when you press the return key). If you hit control-d (not control-z), you're program will exit the loop and print -1 in the console window (which is what you expect because that is the value of EOF in OS X).

Here is the result when I ran your program without change in the Xcode debugger (I typed command-r in Xcode)

bgbgdfsfd
bgbgdfsfd
hgfdgf
hgfdgf
-1

Regular font was typed by me, bold font was from your program. At the end of each of the lines typed by me, I pressed carriage return. After your program printed hgfdgf I typed control-D. Your program then printed the value of the last thing it got from getchar() which was EOF which is -1 in the OS X C library.


Edit

If you are unsure that your program is printing the EOF, change your printf format string to (for example)

printf("Last character is [%d]\n", ch);

Then instead of -1 your program will output Last character is [-1] on the last line.

JeremyP
  • 84,577
  • 15
  • 123
  • 161
0

First of all ctrl+z does not input EOF to your program. If you hit ctrl+Z your shell will put your program to sleep.

Second, if you want to handle these ctrl+Z in your program you need to learn about signal handling in C.

And I think because you were hitting ctrl+Z you were not seeing any output on the screen.

Sumit Mahamuni
  • 302
  • 1
  • 6
0

Make sure you are sending the EOF signal, not a signal that actually terminates your program.

For example, for c program running in windows the EOF is represent by typing ctrl+z and pressing enter. Doing this will exit your while loop but still runs the rest of your program.

However, ctrl+c, which some people may have mistakenly tried for EOF, actually kills your program and will prevent the code behind your while loop from executing.

For mac you will need to find what is the input that corresponds to EOF, and make sure that is what you are sending through rather than the kill signal, which I suspect is what you are doing here.