"inFile" object cannot read EOF

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • waltbrad

    "inFile" object cannot read EOF

    Hello. I'm studying the book "C++ Primer Plus" by Stephan Prata. In
    chapter 6 he gives an exercise that reads from a file. The list is
    thus:

    4
    Sam Stone
    2000
    Freida Flass
    100500
    Tammy Tubbs
    5000
    Rich Raptor
    55000

    So I create a istream object, inFile, and associate the file with
    it. I know it reads the file because I've placed cout directives
    after every read instruction. (since taken out). But I can't get the
    program to read EOF.

    After the following code there are conditions that test for
    inFile.eof() and inFile.fail() but these get skipped over, to a
    default "else" condition.

    Can anyone see why EOF is not being recognized?


    inFile >size;
    donor *pd = new donor[size];
    while(inFile.ge t() != '\n')
    ;

    for(int i = 0; i < size; i++){
    getline(inFile, pd[i].name); //a cout stmt here and
    inFile >pd[i].cash; //here lets me know the data was
    read
    while(inFile.ge t() != '\n')
    ;
    }

  • Victor Bazarov

    #2
    Re: &quot;inFile&qu ot; object cannot read EOF

    waltbrad wrote:
    Hello. I'm studying the book "C++ Primer Plus" by Stephan Prata. In
    chapter 6 he gives an exercise that reads from a file. The list is
    thus:
    >
    4
    Sam Stone
    2000
    Freida Flass
    100500
    Tammy Tubbs
    5000
    Rich Raptor
    55000
    >
    So I create a istream object, inFile, and associate the file with
    it. I know it reads the file because I've placed cout directives
    after every read instruction. (since taken out). But I can't get the
    program to read EOF.
    What do you mean by "to read EOF"? What's "EOF" in your statement?
    After the following code there are conditions that test for
    inFile.eof() and inFile.fail() but these get skipped over, to a
    default "else" condition.
    This is covered in the FAQ 5.8.
    Can anyone see why EOF is not being recognized?
    Every read operation ends with some kind of terminator. For example,
    reading a number ('pd[i].cash') terminates at a symbol that cannot
    be part of a number (like a newline). Most likely you never attempt
    to read when the file cursor is _at_ the end of the file, to force the
    'eof' bit to be set. Since you tell your program exactly how many
    times to read, it doesn't fail to read, and that's why 'fail' bit is
    not getting set either. Try removing the newline after the last
    number in your file - make the third '0' in '55000' the _last_ symbol
    in the file. You should see the difference.
    >
    >
    inFile >size;
    donor *pd = new donor[size];
    while(inFile.ge t() != '\n')
    ;
    >
    for(int i = 0; i < size; i++){
    getline(inFile, pd[i].name); //a cout stmt here and
    inFile >pd[i].cash; //here lets me know the data was
    read
    while(inFile.ge t() != '\n')
    ;
    }
    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask


    Comment

    • waltbrad

      #3
      Re: &quot;inFile&qu ot; object cannot read EOF

      On Jun 7, 2:58 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
      >
      This is covered in the FAQ 5.8.
      >
      Hello again. Thanks for the response. Actually I was getting around to
      your answer. But, you confirmed my suspicions, and I didn't know a way
      to test them.

      I waasn't aware that there was a faq for this newsgroup. Where can I
      find it?

      Thanks again.

      Comment

      • Devon Null

        #4
        Re: &quot;inFile&qu ot; object cannot read EOF

        waltbrad wrote:
        >
        I waasn't aware that there was a faq for this newsgroup. Where can I
        find it?


        DN
        --
        [there are no x's in my email]

        I have the right to remain silent
        (and should probably use it as much as possible)
        Anything I type can and will be used against me
        in a court of idiocy
        I have the right to be wrong
        (and probably am)
        If I can not furnish my own wrongness
        I'm sure someone will provide it for me.

        Comment

        • Victor Bazarov

          #5
          Re: &quot;inFile&qu ot; object cannot read EOF

          waltbrad wrote:
          On Jun 7, 2:58 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
          >>
          >This is covered in the FAQ 5.8.
          >>
          >
          Hello again. Thanks for the response. Actually I was getting around to
          your answer. But, you confirmed my suspicions, and I didn't know a way
          to test them.
          >
          I waasn't aware that there was a faq for this newsgroup. Where can I
          find it?


          Also, check out "Welcome to comp.lang.c++" message posted here every
          now and then. If your server doesn't have it, search the archives.

          V
          --
          Please remove capital 'A's when replying by e-mail
          I do not respond to top-posted replies, please don't ask


          Comment

          • Devon Null

            #6
            Re: &quot;inFile&qu ot; object cannot read EOF

            waltbrad wrote:
            >
            I waasn't aware that there was a faq for this newsgroup. Where can I
            find it?


            Mostly a great reference for a lot of concepts in C++, but has a section
            devoted entirely to posting in this NG.

            DN
            --
            [there are no x's in my email]

            I have the right to remain silent
            (and should probably use it as much as possible)
            Anything I type can and will be used against me
            in a court of idiocy
            I have the right to be wrong
            (and probably am)
            If I can not furnish my own wrongness
            I'm sure someone will provide it for me.

            Comment

            • James Kanze

              #7
              Re: &quot;inFile&qu ot; object cannot read EOF

              On Jun 7, 8:52 pm, waltbrad <waltb...@hotma il.comwrote:
              Hello. I'm studying the book "C++ Primer Plus" by Stephan Prata. In
              chapter 6 he gives an exercise that reads from a file. The list is
              thus:
              4
              Sam Stone
              2000
              Freida Flass
              100500
              Tammy Tubbs
              5000
              Rich Raptor
              55000
              So I create a istream object, inFile, and associate the file with
              it. I know it reads the file because I've placed cout directives
              after every read instruction. (since taken out). But I can't get the
              program to read EOF.
              You can't "read" EOF, since by definition, a read fails if the
              file is at EOF. You have to try to read something, and then
              check whether it failed. After failure, you can check whether
              it was due to EOF, or some other reason.
              After the following code there are conditions that test for
              inFile.eof() and inFile.fail() but these get skipped over, to a
              default "else" condition.
              I would help if you'd show them, however...
              Can anyone see why EOF is not being recognized?
              inFile >size;
              donor *pd = new donor[size];
              while(inFile.ge t() != '\n')
              ;
              Why not simply: inFile.ignore( INT_MAX, '\n' ) ?

              More generally, your file is line oriented, so it is probably
              better to read it line by line, using an istringstream to
              convert the numeric values (and verifying that the format is
              correct). So the above would read:

              std::string line ;
              if ( ! std::getline( inFile, line ) ) {
              // Error, file was empty...
              }
              std::istringstr eam sLine( line ) ;
              if ( ! (sLine >size >std::ws) || sLine.get() != EOF ) {
              // Error, first line didn't contain a number, or
              // had extra junk at the end...
              }

              Given that your format includes lines with just a single number,
              I'd probably wrap this into a separate function.

              Finally, there's no reason in C++ to have to specify the count
              at the start. Just use std::vector, and push_back until you
              encounter end of file.
              for(int i = 0; i < size; i++){
              getline(inFile, pd[i].name); //a cout stmt here and
              inFile >pd[i].cash; //here lets me know the data was
              read
              while(inFile.ge t() != '\n')
              ;
              }
              I'd write this loop something like:

              std::vector< donor donors ;
              std::string line1 ;
              std::string line2 ;
              while ( getline( inFile, line1 ) && getline( inFile, line2 ) ) {
              double cash ;
              std::istringstr eam sCash( line2 ) ;
              sCash >cash ;
              donors.push_bac k( donor( line1, cash ) ) ;
              }

              Except, of course, that it requires more error handling; the
              above only works if the file has the correct format.

              --
              James Kanze (GABI Software) email:james.kan ze@gmail.com
              Conseils en informatique orientée objet/
              Beratung in objektorientier ter Datenverarbeitu ng
              9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

              Comment

              • James Kanze

                #8
                Re: &quot;inFile&qu ot; object cannot read EOF

                On Jun 7, 10:51 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
                waltbrad wrote:
                On Jun 7, 2:58 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
                This is covered in the FAQ 5.8.
                Hello again. Thanks for the response. Actually I was getting around to
                your answer. But, you confirmed my suspicions, and I didn't know a way
                to test them.
                I waasn't aware that there was a faq for this newsgroup. Where can I
                find it?
                Also, check out "Welcome to comp.lang.c++" message posted here every
                now and then. If your server doesn't have it, search the archives.
                Note that all of the FAQ's, to all groups, are available at
                www.faqs.org. Back in the old days, this was pointed out to
                people when they got their connection, but any sort of
                responsability on the part of providers today seems to have gone
                out the window.

                --
                James Kanze (GABI Software) email:james.kan ze@gmail.com
                Conseils en informatique orientée objet/
                Beratung in objektorientier ter Datenverarbeitu ng
                9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                Comment

                • BobR

                  #9
                  Re: &quot;inFile&qu ot; object cannot read EOF


                  James Kanze wrote in message...
                  >** You can't "read" EOF **, since by definition, a read fails if the
                  >file is at EOF.
                  So, my docs are wrong?
                  " Method: int istream::get ()
                  Read a single character ** (or EOF) ** from the input stream, returning it
                  (coerced to an unsigned char) as the result. "
                  You have to try to read something, and then
                  >check whether it failed. After failure, you can check whether
                  >it was due to EOF, or some other reason.
                  I once did this in some 'test' code:

                  // std::vector<uns igned charImage;
                  while( SomeInFile.peek () != EOF ){
                  // .... do stuff ....
                  // Image.push_back ( SomeInFile.get( ) );
                  // if not reading single chars, need to check stream state.
                  }

                  Maybe it will help the OP to see the light. <G>

                  --
                  Bob R
                  POVrookie


                  Comment

                  • Victor Bazarov

                    #10
                    Re: &quot;inFile&qu ot; object cannot read EOF

                    BobR wrote:
                    James Kanze wrote in message...
                    >
                    >** You can't "read" EOF **, since by definition, a read fails if the
                    >file is at EOF.
                    >
                    So, my docs are wrong?
                    " Method: int istream::get ()
                    Read a single character ** (or EOF) ** from the input stream,
                    returning it (coerced to an unsigned char) as the result. "
                    Whoever wrote that decided to shorten it a bit. What it should say
                    is "Read a single character from the input stream returning it, or
                    return a special value if the stream is in 'end-of-file' state".

                    In fact, istream::get() returns either the character it read or
                    'traits::eof()' , according to the Standard. It doesn't "read" any
                    "EOF" from the stream.
                    > You have to try to read something, and then
                    >check whether it failed. After failure, you can check whether
                    >it was due to EOF, or some other reason.
                    >
                    I once did this in some 'test' code:
                    >
                    // std::vector<uns igned charImage;
                    while( SomeInFile.peek () != EOF ){
                    // .... do stuff ....
                    // Image.push_back ( SomeInFile.get( ) );
                    // if not reading single chars, need to check stream state.
                    }
                    >
                    Maybe it will help the OP to see the light. <G>
                    Maybe...

                    V
                    --
                    Please remove capital 'A's when replying by e-mail
                    I do not respond to top-posted replies, please don't ask


                    Comment

                    • BobR

                      #11
                      Re: &quot;inFile&qu ot; object cannot read EOF


                      Victor Bazarov wrote in message...
                      BobR wrote:
                      James Kanze wrote in message...
                      ** You can't "read" EOF **, since by definition, a read fails if the
                      file is at EOF.
                      So, my docs are wrong?
                      " Method: int istream::get ()
                      Read a single character ** (or EOF) ** from the input stream,
                      returning it (coerced to an unsigned char) as the result. "
                      >
                      Whoever wrote that decided to shorten it a bit. What it should say
                      is "Read a single character from the input stream returning it, or
                      return a special value if the stream is in 'end-of-file' state".
                      Ok, I'll buy that. Thanks.
                      >
                      In fact, istream::get() returns either the character it read or
                      'traits::eof()' , according to the Standard. It doesn't "read" any
                      "EOF" from the stream.
                      No "implementa tion defined" escape clause there? I'll check it out (for my
                      systems(win,GNU )) to satisfy my curiosity <G>.

                      --
                      Bob R
                      POVrookie


                      Comment

                      • James Kanze

                        #12
                        Re: &quot;inFile&qu ot; object cannot read EOF

                        On Jun 8, 8:20 pm, "BobR" <removeBadB...@ worldnet.att.ne twrote:
                        James Kanze wrote in message...
                        ** You can't "read" EOF **, since by definition, a read fails if the
                        file is at EOF.
                        So, my docs are wrong?
                        " Method: int istream::get ()
                        Read a single character ** (or EOF) ** from the input stream, returning it
                        (coerced to an unsigned char) as the result. "
                        Pourly worded. It "tries" to read a single character, returning
                        the character read, or EOF if it cannot read a character. EOF
                        is not a character, but a special out of band value. (That's
                        why get() returns int, and not char.)
                        You have to try to read something, and then
                        check whether it failed. After failure, you can check whether
                        it was due to EOF, or some other reason.
                        I once did this in some 'test' code:
                        // std::vector<uns igned charImage;
                        while( SomeInFile.peek () != EOF ){
                        // .... do stuff ....
                        // Image.push_back ( SomeInFile.get( ) );
                        // if not reading single chars, need to check stream state.
                        }
                        Maybe it will help the OP to see the light. <G>
                        Yes. That's basically what I recommended at the filebuf level:
                        peek() simply returns rdbuf()->sgetc() (or EOF, if the rdbuf()
                        returns a null pointer).

                        --
                        James Kanze (Gabi Software) email: james.kanze@gma il.com
                        Conseils en informatique orientée objet/
                        Beratung in objektorientier ter Datenverarbeitu ng
                        9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                        Comment

                        • James Kanze

                          #13
                          Re: &quot;inFile&qu ot; object cannot read EOF

                          On Jun 8, 10:42 pm, "BobR" <removeBadB...@ worldnet.att.ne twrote:
                          Victor Bazarov wrote in message...
                          BobR wrote:
                          James Kanze wrote in message...
                          >** You can't "read" EOF **, since by definition, a read fails if the
                          >file is at EOF.
                          So, my docs are wrong?
                          " Method: int istream::get ()
                          Read a single character ** (or EOF) ** from the input stream,
                          returning it (coerced to an unsigned char) as the result. "
                          Whoever wrote that decided to shorten it a bit. What it should say
                          is "Read a single character from the input stream returning it, or
                          return a special value if the stream is in 'end-of-file' state".
                          Ok, I'll buy that. Thanks.
                          The important point is that at this level, EOF is an out of band
                          value, and not a character. At this level, because...
                          In fact, istream::get() returns either the character it read or
                          'traits::eof()' , according to the Standard. It doesn't "read" any
                          "EOF" from the stream.
                          No "implementa tion defined" escape clause there? I'll check it
                          out (for my systems(win,GNU )) to satisfy my curiosity <G>.
                          Most of what takes place in IO is more or less "implementa tion
                          defined". When it's not flattly unspecified In particular, how
                          an implementation represents line breaks and end of file is
                          unspecified, and may (and does under most systems) differ
                          between text files and binary. (For Unix, everything is pretty
                          much transparent, and there is no EOF character, either in text
                          or in binary files. I think that most Windows compilers,
                          however, still recognize the traditional CP/M end of file
                          character, 0x1A, in text files.)

                          Note that historically, a common error was writing the result of
                          istream::get() or istream::peek() (or earlier, getc() or
                          getchar()) to a char, and testing that for EOF (typically -1,
                          although any negative value is legal). This worked if (and only
                          if) plain char was signed, and the file never contained a 0xFF.
                          In ISO 8859-1, 0xFF is the 'ÿ' character (small Latin letter y
                          with diarese, if it doesn't show up right here). Not the most
                          common character, so the error often went unobserved.

                          --
                          James Kanze (Gabi Software) email: james.kanze@gma il.com
                          Conseils en informatique orientée objet/
                          Beratung in objektorientier ter Datenverarbeitu ng
                          9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                          Comment

                          • Jerry Coffin

                            #14
                            Re: &quot;inFile&qu ot; object cannot read EOF

                            In article <1181292953.700 106.187630@q66g 2000hsg.googleg roups.com>,
                            james.kanze@gma il.com says...

                            [ ... ]
                            I'd write this loop something like:
                            >
                            std::vector< donor donors ;
                            std::string line1 ;
                            std::string line2 ;
                            while ( getline( inFile, line1 ) && getline( inFile, line2 ) ) {
                            double cash ;
                            std::istringstr eam sCash( line2 ) ;
                            sCash >cash ;
                            donors.push_bac k( donor( line1, cash ) ) ;
                            }
                            Personally, I think I'd do it a bit differently:

                            struct donor {
                            std::string name;
                            double cash;

                            // read a single donor's data:
                            friend std::istream &operator>>(std ::istream &i, donor &d) {
                            std::getline(i, d.name);

                            std::string line2;
                            std::getline(li ne2);
                            std::istringstr eam temp(line2);
                            line2 >d.cash;
                            return i;
                            }
                            };

                            std::vector<don ordonors;

                            std::copy(std:: istream_iterato r<donor>(infile ),
                            std::istream_it erator<donor>() ,
                            std::back_inser ter(donors));

                            This does not require (or allow) the count at the beginning of the file
                            though...

                            --
                            Later,
                            Jerry.

                            The universe is a figment of its own imagination.

                            Comment

                            • James Kanze

                              #15
                              Re: &quot;inFile&qu ot; object cannot read EOF

                              On Jun 10, 2:23 am, Jerry Coffin <jcof...@taeus. comwrote:
                              In article <1181292953.700 106.187...@q66g 2000hsg.googleg roups.com>,
                              james.ka...@gma il.com says...
                              [ ... ]
                              I'd write this loop something like:
                              std::vector< donor donors ;
                              std::string line1 ;
                              std::string line2 ;
                              while ( getline( inFile, line1 ) && getline( inFile, line2 ) ) {
                              double cash ;
                              std::istringstr eam sCash( line2 ) ;
                              sCash >cash ;
                              donors.push_bac k( donor( line1, cash ) ) ;
                              }
                              Personally, I think I'd do it a bit differently:
                              I'd do it a lot differently in production code as well:-).
                              Starting with a lot more error handling.
                              struct donor {
                              std::string name;
                              double cash;
                              // read a single donor's data:
                              friend std::istream &operator>>(std ::istream &i, donor &d) {
                              std::getline(i, d.name);
                              >
                              std::string line2;
                              std::getline(li ne2);
                              std::istringstr eam temp(line2);
                              line2 >d.cash;
                              return i;
                              }
                              };
                              Good point. Using a >operator is definitely the way to go.
                              std::vector<don ordonors;
                              std::copy(std:: istream_iterato r<donor>(infile ),
                              std::istream_it erator<donor>() ,
                              std::back_inser ter(donors));
                              This does not require (or allow) the count at the beginning of the file
                              though...
                              Neither did my version:-). In fact, as soon as you use
                              std::vector, you're freed from this constraint.

                              --
                              James Kanze (Gabi Software) email: james.kanze@gma il.com
                              Conseils en informatique orientée objet/
                              Beratung in objektorientier ter Datenverarbeitu ng
                              9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                              Comment

                              Working...