Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Why not stop ?

  1. Oct 5, 2004 #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
    }
     
  2. jcsd
  3. Oct 5, 2004 #2
    It works!
    Check whether there is some other error!

    -- AI
     
  4. Oct 5, 2004 #3

    chroot

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

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

    - Warren
     
  5. Oct 5, 2004 #4
    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() wich returns an int.
    Code (Text):
    int ch;
    while( ( ch = fgetc(fp) ) != EOF )
    This is perfectly valid.

    This is probably a bit better:
    Code (Text):

    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 */
    }
     
  6. Oct 6, 2004 #5
    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 ?
     
  7. Oct 6, 2004 #6
    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: Oct 6, 2004
  8. Oct 7, 2004 #7

    chroot

    User Avatar
    Staff Emeritus
    Science Advisor
    Gold Member

    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
     
  9. Oct 8, 2004 #8
    Thanks a lot for your help, but anyone has any other ideas ? Please tell me..
     
  10. Oct 8, 2004 #9
    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 (Text):
    #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.
     
  11. Oct 9, 2004 #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.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?



Similar Discussions: Why not stop ?
  1. Stop The Keyblogger! (Replies: 6)

Loading...