Troubleshooting Program that Won't Stop - Help Appreciated!

AI Thread Summary
The discussion focuses on troubleshooting a program that fails to stop due to improper handling of the `fgetc()` function. The main issue identified is the incorrect type casting of the return value, as `fgetc()` returns an integer (EOF is represented as -1) while the variable `ch` is a char, leading to potential errors. Participants suggest using an integer for `ch` or employing `fgets()` to read characters safely without casting. Additionally, the conversation touches on why `fgetc()` returns an integer instead of a char, emphasizing the need for explicit file status checks like `feof()` and `ferror()`. Overall, the thread provides insights into proper file reading techniques in C programming.
Nobody
Messages
18
Reaction score
1
I have a small code snip as included below, please have a look at it and please tell me why my program doesn't stop...I am really thankful for your answers...

char ch;
while((ch=fget(fp)!=EOF){
// print out values of ch
}
 
Computer science news on Phys.org
It works!
Check whether there is some other error!

-- AI
 
BTW, I would generally strongly caution against using loop conditions that have side-effects, like this one.

- Warren
 
The "error" is that 'ch' is of type char. It might not be what is causing your problems, but it is nevertheless an error.
When fgetc() returns EOF it is an int. You are casting an int to a char, then casting it back to an int to compare with EOF. This is not safe. The original int(the code for EOF) might not be the same after beeing casted from int to char and then back to int.

Here are two ways to deal with fgetc() which returns an int.
Code:
int ch;
while( ( ch = fgetc(fp) ) != EOF )
This is perfectly valid.

This is probably a bit better:
Code:
char ch;
while(1)
{
    ch = fgetc(fp); /* Casting from int to char is ok here */

    if ( feof(fp) )    /* Because we use feof() to check the stream */
      break;

    if ( ferror(fp) )  /* We can also check for read-errors */
        break; /* And handle them if we want */

    /* Work with 'ch' here */
}
 
Thank you for your answers, I am still a bit curious about why fgetc() reads only characters but returns an integer ? Do you know why ?
 
What I mean to ask is people who created fgets, might also think of making it return a char so that it would be more compatible and easier for programmers to remember, but they didn't do so ? why ?
And EOF is actually a -1 but why -1 exists at the end of tha file ?
 
Last edited:
The problem is that there is really no such thing as an "EOF char." All 256 possible values of char are perfectly valid anywhere in a file, and none of them actually mean "end of file." If they did, you would not be able to store the integer -1 in a binary file! Instead, the operating system stores the length of files in a file's metadata, and sets a flag when you attempt to read past the end of an open file. The various file I/O functions have to report to you when an flag (such as EOF) occurs, but they can't do so just by using a special char. Instead, fgetc() mucks about with ints. This is why it's much preferred to actually check the file's status explicitly by using something like ferror().

- Warren
 
Thanks a lot for your help, but anyone has any other ideas ? Please tell me..
 
1. fgets() returns a (char *), which it obviously must.

If you for some reason suddenly has become affraid of using fgetc() because it returns an integer, you can use fgets() to get that char directly without casting.
But, it's not dangerous to cast the initial integer to a char. It's when you start casting it back and forth that strange things might occur.

char foo;

foo = fgetc(fp);
/* perfectly valid, just feof() to check for eof on the stream */
It's the exact same as foo = (char) fgetc(fp);

Or, you could always do:
char *foo;

while ( (fgets(foo, 1, fp) ) != EOF )


But, that's just silly.

What you really should do is to create a buffer:
char buf[255];

Then read into that buffer:
while( ( fgets(buf, 255, fp) ) != EOF )
{
/* work with buf */
}


The point beeing that reading from a file stream requires a low-level call, and the more you do it, the more resources you use.

Here is some code I wrote to count the number of chars in a file stream using fgets() instead of fgetc():
Code:
#include <stdio.h>

int main(void)
{
  FILE *foo;
  int i = 0;
  char buf[512];

  foo = fopen("/Users/tor/Library/Mail/Mailboxes/Apple Lists/OS X Server.mbox/mbox", "r");

  if(!foo)
    exit(-1);

  while( fgets(buf, 255, foo) != 0 ) /* 0 means error or EOF, check man fgets */
      i += strlen(buf);

  printf("%d\n", ++i);

  return 0;
}
This code is not 100% safe, because there might occur errors after x bytes have been read from the stream. But, a simple call to ferror(fp) will fix that.
 
  • #10
Thank you, I'd like your explanation...
I looked at your code, I like apple, I will save money to buy one then. Thanks again.
 
Back
Top