Thread: Opening files.

  1. #1
    Novice.
    Join Date
    Oct 2005
    Posts
    88

    Opening files.

    I've got the following code:
    Code:
    #include <stdio.h>
    FILE * fptr;
    int main()
    {
      char fileLine[81];
      fptr = fopen("C:\\aap.txt", "r");
      if (fptr != 0)
         {
          while (!feof(fptr))
                {
                 fgets(fileLine, 81, fptr);
                 if (!feof(fptr))
                    {puts(fileLine);}
                 }
          }
       else
           {printf("\nError opening file.\n");}
       fclose(fptr);
       getchar();
       getchar();
      return 0;
    }
    Let's start with the first bit.

    I'm not sure about
    Code:
    while (!feof(fptr))
                {
                 fgets(fileLine, 81, fptr);
                 if (!feof(fptr))
                    {puts(fileLine);}
    What does while (!feof(fptr)) do exactly? I can see that it checks whether the end of the file as been reached.

    Would (feof(fptr)) return 1 if the end of the file had been reached and 0 if the end of the file hadn't been reached?

    If so how can it do that,
    Code:
     FILE * fptr;
    (I thought) means, store the adress of FILE in fptr. It doesn't say much about the lengt of the file does it? (or does it store the end adress of the file too, so that it knows how long it is, as this is a special FILE-pointer?)


    Thank You.

  2. #2

  3. #3
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Indeed, it returns 0 if end of file is not reached and 1 otherwise.
    How can it do that? It's true that you receive a FILE* pointer, but have you thought about what it points to?
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  4. #4
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I can see that it checks whether the end of the file as been reached.
    It does indeed.

    >Would (feof(fptr)) return 1 if the end of the file had been
    >reached and 0 if the end of the file hadn't been reached?
    Close, it returns a non-zero value if the end of file has been reached. Or rather, true if the end of file has been reached and false otherwise, as C treats a non-zero value as true and a zero value as false.

    > FILE * fptr;
    >(I thought) means, store the adress of FILE in fptr.
    FILE is an opaque type. Typically it's a structure that contains all kinds of information about a file so that the standard I/O functions can properly work with it and still tell you how things went. For example, here's one implementation for FILE:
    Code:
    struct _buffer {
      HANDLE         _fd;    /* Character source for the buffer */
      struct _deque  _buf;   /* Queue of buffered characters */
      struct _deque  _unget; /* Stack of pushed back characters */
      char           _peek;  /* Unread but not yet buffered character */
      unsigned long  _flag;  /* State of the buffer */
      char          *_tmp;   /* The name of the file (if it's temporary) */
    };
    
    typedef struct _buffer FILE;
    And feof might be implemented as such:
    Code:
    int feof ( FILE *stream )
    {
      return stream->_flag & _OPEN && stream->_flag & _EOF;
    }
    At the risk of confusing you with too much detail, the input functions will work with a buffer of characters. That buffer is filled up using system functions. For example, the rest of the library that works with the above FILE structure eventually gets down to this function for input:
    Code:
    /*
      Return the 0 on success, non-zero on error or EOF
    */
    int _intern_fill ( FILE *in )
    {
      const HANDLE fd = in->_fd;
      const size_t size = in->_buf._size;
    
      size_t  read_size = size;
      char   *temp = NULL;
    
      if ( ( temp = malloc ( read_size ) ) != NULL ) {
        char   *pread = temp;
        size_t  nread = 0;
    
        /* "Read" any peeked characters first */
        if ( in->_flag & _PEEK ) {
          in->_flag &= ~_PEEK;
          *temp = in->_peek;
          pread = temp + 1;
          --read_size;
        }
    
        /* Load the raw stream characters into our temporary buffer */
        if ( ReadFile ( fd, pread, read_size, (LPDWORD)&nread, NULL ) != 0 ) {
          if ( pread != temp ) {
            /* We "read" a peeked character, so bump the nread count */
            ++nread;
          }
    
          if ( nread != 0 ) {
            /* Prep the buffer for streaming */
            char   *buf = in->_buf._base;
            size_t  i = 0;
    
            if ( in->_flag & _TEXT )
              nread = _compact_newlines ( in, temp, nread );
    
            /* Set up a new owned buffer if necessary */
            if ( buf == NULL && in->_flag & _OWNED )
              buf = malloc ( size );
    
            if ( buf != NULL ) {
              /* Reset the buffer for fresh loading */
              _deque_init ( in->_buf, buf, size );
    
              /* Load characters into the buffer */
              while ( i < nread && i < size )
                _deque_pushf ( in->_buf, temp[i++] );
            }
            else {
              /* Allocation failed or a non-owned buffer was NULL */
              in->_flag |= _ERR;
            }
          }
          else {
            /* The stream is good, but we hit end-of-file immediately */
            in->_flag |= _EOF;
          }
        }
        else
          in->_flag |= _ERR;
      }
      else
        in->_flag |= _ERR;
    
      /* Don't forget to clean up the mess */
      free ( temp );
    
      return in->_flag & ( _ERR | _EOF );
    }
    Notice how it sets the flag field for errors and end-of-file. It's this flag that tells feof (and ferror) whether the stream is in an invalid state or not. The actual machinery is somewhat complicated by the buffering mechanism, but it all boils down to this: FILE is an opaque type that holds enough information necessary to work with streams. When you perform I/O on a stream, the C runtime makes calls to the system to do the actual work. The system functions give the C runtime enough information to pass back to you through the standard C interface, which completes the abstraction.
    My best code is written with the delete key.

  5. #5
    Novice.
    Join Date
    Oct 2005
    Posts
    88
    I thank you all for your explanations. Prelude, I think you must be really intelligent, but I'm sorry to say that your knowlege of C is a bit bigger than mine, and therefore I don't understand very much of your post. Thanks for your reply, it will probably be useful to somebody else.

    Elysia, yes I have thought about that. I think it would be the location on the harddisk. Is this true?

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    As I mentioned, it's FILE struct pointer. It points to a struct of information somewhere in memory.
    That's where it gets the information from.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I don't understand very much of your post
    That's okay, I didn't expect you to. If you understood everything in my post you wouldn't have asked your question in the first place. I covered the extra detail because even though you may not understand it now, it'll be there for you in the future.
    My best code is written with the delete key.

  8. #8
    Novice.
    Join Date
    Oct 2005
    Posts
    88
    Okay. I think I have a slight understanding of its working now. I was actually going to ask how
    Code:
    fgets(fileLine, 81, fptr);
    works too, but I think I'm just going to accept its working for now without knowing why or how.

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Fgets reads the information from the pointer to the FILE struct you passed and can thus read information from the file opened and store it in your buffer.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  10. #10
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I was actually going to ask how fgets(fileLine, 81, fptr); works too
    Okay, now I'm just being evil. You can ignore me, but this is how fgets and gets work:
    Code:
    char *gets ( char *s )
    {
      return _getline ( s, 0x80000000, stdin, 0 );
    }
    
    char *fgets ( char *s, int n, FILE *in )
    {
      return _getline ( s, n, in, 1 );
    }
    
    static char *_getline ( char *s, int n, FILE *in, int store_nl )
    {
      char *p = s;
      int ch;
    
      while ( --n > 0 ) {
        ch = fgetc ( in );
    
        if ( ch == EOF )
          break;
        else if ( ch == '\n' ) {
          if ( store_nl )
            *p++ = '\n';
          break;
        }
        else
          *p++ = (char)ch;
      }
    
      if ( p != s && !ferror ( in ) ) {
        *p = '\0';
        return s;
      }
      else
        return NULL;
    }
    My best code is written with the delete key.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Opening ASCII files in C?
    By Mavix in forum C Programming
    Replies: 6
    Last Post: 04-25-2007, 02:23 PM
  2. Need help opening a series of files
    By ramparts in forum C Programming
    Replies: 9
    Last Post: 11-14-2006, 05:49 PM
  3. Opening files with UNICODE file names
    By decohk in forum Linux Programming
    Replies: 2
    Last Post: 11-09-2006, 05:25 AM
  4. opening files
    By angelic79 in forum C Programming
    Replies: 3
    Last Post: 10-19-2004, 06:52 AM
  5. Opening files - Giving options?
    By wwwGazUKcom in forum C++ Programming
    Replies: 3
    Last Post: 09-18-2001, 07:06 AM