Troubleshooting Program that Won't Stop - Help Appreciated!

Click For Summary

Discussion Overview

The discussion revolves around troubleshooting a programming issue related to the use of the `fgetc()` function in C, specifically why a program does not terminate as expected when reading from a file. Participants explore various aspects of file reading, including data types, error handling, and alternative functions.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Exploratory

Main Points Raised

  • One participant shares a code snippet and requests help for a program that does not stop, indicating a potential issue with the loop condition.
  • Another participant asserts that the code works and suggests checking for other errors.
  • A participant cautions against using loop conditions that have side effects, implying potential risks in the current approach.
  • Concerns are raised about the type of variable used for `fgetc()`, noting that it returns an `int` and that casting it to `char` may lead to unsafe comparisons with `EOF`.
  • Alternative approaches to reading from a file are proposed, including using `feof()` and `ferror()` for better error handling.
  • Questions are posed about why `fgetc()` returns an integer instead of a character, with speculation about design choices in the function's implementation.
  • A participant explains that there is no "EOF char" and discusses how file metadata is used to manage end-of-file conditions, emphasizing the need for explicit status checks.
  • Suggestions are made to use `fgets()` as an alternative to `fgetc()`, with discussions on the implications of casting and resource management when reading from files.

Areas of Agreement / Disagreement

Participants express differing views on the best practices for using `fgetc()` and `fgets()`, with no consensus reached on the optimal approach to handle file reading and EOF conditions.

Contextual Notes

There are unresolved questions regarding the design rationale behind the return types of file reading functions and the implications of casting between types. Additionally, some participants highlight potential limitations in the provided code examples regarding error handling.

Who May Find This Useful

This discussion may be useful for programmers dealing with file I/O in C, particularly those interested in understanding the nuances of reading characters from files and managing EOF conditions.

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.
 

Similar threads

  • · Replies 38 ·
2
Replies
38
Views
7K
  • · Replies 66 ·
3
Replies
66
Views
6K
Replies
5
Views
7K
  • · Replies 14 ·
Replies
14
Views
5K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 15 ·
Replies
15
Views
3K
  • · Replies 1 ·
Replies
1
Views
2K
Replies
73
Views
7K
  • · Replies 30 ·
2
Replies
30
Views
5K
Replies
2
Views
2K