0

My program is supposed to run in the following way:

CProgram < file.txt

file.txt can has as many rows of data as it wants. For instance,

2 3 G 5 6
5 6 7 
6 9 3 6 H
<<Blank line>>

Is there a way to know that that there is no more input rows? Every file has a blank line at the end.

I am able to read the rows but my program never comes to know if there is no more data to be read and keeps waiting for more data as it would normally expect from stdin.

This is how I am reading it

 while( fgets(line, sizeof(line), stdin) != NULL) {
   ... do something
}
Aakash
  • 17
  • 4
  • @chux posted in the question – Aakash Jun 07 '18 at 04:44
  • 1
    It is more likely there is a bug inside that loop that is causing your program to behave like it is paused. Can you try an experiment where the `... do something` is actually all commented out? – jxh Jun 07 '18 at 04:49
  • 1
    You are thinking of stdin incorrectly. Perhaps you are assuming it is always a fifo, or always associated with a keyboard. Stop thinking this way. In fact, perform the experiment in which you call `fseek(stdin, ...)` (checking the return value, or course) and run the program with stdin redirected from a regular file. You may be surprised to find that `fseek` does not fail in that case. If you find it surprising, then you're not thinking about stdin correctly. It's standard, not an edge case. – William Pursell Jun 07 '18 at 04:55

3 Answers3

4

All of the input functions will give you an end of file indication when the file is finished. For example:

#include <stdio.h>

int main(void) {
    int count = 0;
    while (getchar() != EOF)
        ++count;
    printf("There were %d characters.\n", count);
    return 0;
}

will count the characters in the input stream:

pax> ./testprog <testprog.c
There were 169 characters.

pax> echo -n hello | ./testprog
There were 5 characters.

If you're using fgets (as seems clear from your update), that also allows easy detection:

#include <stdio.h>

static char buff[1000];

int main(void) {
    int count = 0;
    while (fgets(buff, sizeof(buff), stdin) != NULL)
        ++count;
    printf("There were %d lines.\n", count);
    return 0;
}

Running that will count the lines:

pax> ./testprog <testprog.c
There were 12 lines.

You can see in both cases that the end of file is detected correctly using the input redirection or pipe methods. If you're running your code reading from the terminal, you just have to indicate end of file using the facilities your environment provides.

That's usually CTRL-D at the start of the line in UNIX-like operating systems, or CTRL-Z at the start of the line for Windows:

pax> ./testprog
this has
two lines
<Ctrl-D pressed (I run Linux)>
There were 2 lines.
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 2
    @Aakash, see the update. If you're using input redirection or piping, it *will* work. If you reading from an actual *interactive* device, you'll need to ensure you indicate end of file explicitly. – paxdiablo Jun 07 '18 at 04:50
3

EOF represents the end of file, so you can read file till you hit EOF

int c = 0;
while ((c = getchar ()) != EOF) { ... }

EDIT:

while ( fgets(line, sizeof(line), stdin) != NULL ) {
    ... do something
}

should work fine since fgets() returns NULL if it hits end of file. At least in Unix like OS (Unix/Linux/BSD/Mac OS) everything is a file, so is standard input. So you can check for EOF on standard input.

  • @Aakash it does not matter, what OS are you using? –  Jun 07 '18 at 04:46
  • mac operating system – Aakash Jun 07 '18 at 04:48
  • @Aakash "Its reading from stdin so no EOF" makes no sense at all. If stdin is a regular file (which it is when you redirect from a regular file), getchar/fread/read etc. will reach the end of file. (getchar will return EOF, fread and read will return 0) – William Pursell Jun 07 '18 at 04:50
  • 2
    Don't use `feof` like this: https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – William Pursell Jun 07 '18 at 04:51
  • thank you guys for help I know `feof()` is not necessary but it was way to see what is going on with OPs code. –  Jun 07 '18 at 04:58
  • 1
    @chux you are right that is why OP is saying that my code is not working. :( Well all of that you said plus the fact that *The return type is int to accommodate for the special value EOF, which indicates failure:* –  Jun 07 '18 at 05:09
0

Since you are reading from stdin and using fgets() , to terminate the loop or there is no more rows to take from user, check the return value of fgets() like below.

char *ptr = NULL;
while( (ptr= fgets(line, sizeof(line), stdin)) != NULL) {
    if( *ptr == '\n')
        break;
    else { /* do something */  }
}

At last when you press ENTER key if condition will be true and it terminates.

Achal
  • 11,821
  • 2
  • 15
  • 37