Checking stdin and stdout using external function

129 views Asked by At

Does scope impact, checking for errors while obtaining input from stdin or outputting to stdout? For example if I have a code body built in the following way:

void streamCheck(){
   if (ferror(stdin)){
      fprintf(stderr, "stdin err");
      exit(1);
   }
   if (ferror(stdout)){
      fprintf(stderr, "stdout err");
      exit(2);
   }
}

int main(){
   int c = getchar();
   streamCheck();
   ...
   putchar(c) 
   streamCheck();
}

are the return values of ferror(stdin) / ferror(stdout) impacted by the fact that I am checking them in a function rather than in the main? If there is a better way to do this also let me know I am quite new to C.

3

There are 3 answers

2
John Bollinger On

are the return values of ferror(stdin) / ferror(stdout) impacted by the fact that I am checking them in a function rather than in the main?

The return value of ferror() is characteristic of the current state of the stream that you provide as an argument. At any given time, the stdin provided by stdio.h refers to the same stream, with the same state, in every function, including main(). Therefore, you will obtain the same result by calling the ferror() function indirectly, via an intermediary function, as you would by calling it directly.

NEVERTHELESS, the approach you present in your example is poor. For the most part, C standard library functions indicate whether an error has occurred via their return values. In particular, getchar() returns a special value, represented by the macro EOF, if either the end of the file is encountered or an error occurs. This is typical of the stdio functions. You should consistently test functions' return values to recognize when exceptional conditions have occurred. For stream functions, you should call ferror() and / or feof() only after detecting such a condition, and only if you want to distinguish between the end-of-file case and the I/O error case (and the "neither" case for some functions). See also "Why is 'while ( !feof (file) )' always wrong?"

Personally, I probably would not write a generic function such as your streamCheck() at all, as error handling is generally situation specific. But if I did write one, then I'd certainly have it test just one stream that I specify to it. Something like this, for example:

void streamCheck(FILE *stream, const char *message, int exit_code) {
   if (ferror(stream)) {
      fputs(message, stderr);
      exit(exit_code);
   }
}

int main(void) {
   int c = getchar();

   if (c == EOF) {
       streamCheck(stdin, "stdin err\n", 1);
   }

   // ...

   if (putchar(c) == EOF) {
       streamCheck("stdout err\n", 2);
   }
}
2
dbush On

As long as you call ferror on a particular stream before calling any other function on that stream you should be fine.

It doesn't matter that ferror is being called from a different function that getchar or putchar was called from.

0
Marco Bonelli On

There is no problem in your function. ferror() checks the error indicator of the FILE * that is passed as argument. In other words, the error indicator is a property of the file object and is directly obtainable from the FILE * pointer. Therefore, no matter where you call ferror() from, it will be able to determine if an error happened with the FILE * that is passed as argument (that is, of course, if the argument is valid).