Thread: what is wrong with eof?

  1. #1
    Registered User
    Join Date
    May 2007
    Posts
    67

    Question what is wrong with eof?

    Write a program to compute numeric grades for a course.Read in a data file which contains the first name of the student and then ten quiz scores in each line.Then compute the ave score for the ten scores and write the result in to another file.

    This my code and my out put.
    Code:
    
    #include <iostream>
     #include <fstream>
     #include <stdlib.h>
     #include <iomanip>
     using namespace std;
    
     void welcome()
     {
          cout<<"This program will compute numeric grades for a course.\n";
          cout<<"After reading in a input file,I will compute the average score\n"
              <<"for each student and write them to a new file.\n";
    
     }
    
     void InputAndOutput(ifstream& in,char name[],int score[],ofstream& out)
     {
          in.open("E:\\fall 2007\\CS 3A\\6.9\\list.txt");
          if(in.fail())
          {
            cout<<"list.txt doesn't exist.Program terminates!\n";
            system("pause");
            exit(1);
          }
    
          out.open("E:\\fall 2007\\CS 3A\\6.9\\score.txt");
          if(out.fail())
          {
            cout<<"score.txt doesn't exist.Program terminates!\n";
            system("pause");
            exit(1);
          }
    
    
          int count=0;
          double sum[100];
    
    
          while(!in.eof())
          {
    
             in>>name>>score[0]>>score[1]>>score[2]>>score[3]>>score[4]>>score[5]
               >>score[6]>>score[7]>>score[8]>>score[9];
    
              cout<<name<<score[0]<<score[1]<<score[2]<<score[3]<<score[4]<<score[5]
               <<score[6]<<score[7]<<score[8]<<score[9];
    
             for(int i=0;i<10;i++)
             sum[count]+=score[i];
    
    
             out<<setw(10)<<name<<setw(5)<<score[0]<<setw(5)<<score[1]<<setw(5)
                <<score[2]<<setw(5)<<score[3]<<setw(5)<<score[4]<<setw(5)<<score[5]
                <<setw(5)<<score[6]<<setw(5)<<score[7]<<setw(5)<<score[8]<<setw(5)
                <<score[9]<<setw(5)<<sum[count]/10.0<<endl;
    
             count++;
    
           }
    
           cout<<"End of the program!\n";
    
     }
    
    
    
    
    
    
     int main()
     {
    
         ifstream in;
         ofstream out;
         char name[10];
         int score[10];
    
    
         welcome();
         InputAndOutput(in,name,score,out);
         in.close();
         out.close();
    
         system("pause");
    
      }

    output


    Tian 98 99 100 99 97 96 99 99 100 99 98.6
    Paul 88 89 90 91 94 93 88 78 99 100 91
    Zerg 99 91 92 78 99 95 94 96 99 100 94.3
    Mengle 99 93 94 92 94 95 99 100 99 100 96.5
    Mengle 99 93 94 92 94 95 99 100 99 100 96.5





    look, the last person do 2 times.So why it happened?I think there is must be something wrong in eof!And another question how do the system know the end of a file?how did the system detect it?

    And also maybe there is some way to simplify my code,so please help!
    Last,I want to enhance my program like:
    If there is more than 10 quiz score,how to make it possible to make my program to handle it?(use a array?)



    thanks!
    Last edited by tx1988; 09-10-2007 at 01:34 PM.

  2. #2
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    eof is not set until you reach the end of file therefore resulting in the double parsing you noticed.

    The prefered method is:
    Code:
    while(file>>value){
    //Do something

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Have you read the FAQ ?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    May 2007
    Posts
    67
    Quote Originally Posted by prog-bman View Post
    eof is not set until you reach the end of file therefore resulting in the double parsing you noticed.

    The prefered method is:
    Code:
    while(file>>value){
    //Do something
    Yes,I know your way,but for this case there is a mixed type--char and int.how could I define the value?

  5. #5
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Code:
          while( in>>name>>score[0]>>score[1]>>score[2]>>score[3]>>score[4]>>score[5]
               >>score[6]>>score[7]>>score[8]>>score[9] ) {
               ....
         }
    should do the trick.
    Kurt

  6. #6
    Registered User
    Join Date
    May 2007
    Posts
    67
    My teacher help me for solving this silly question.This is my list file:

    Tian 98 99 100 99 97 96 99 99 100 99
    Paul 88 89 90 91 94 93 88 78 99 100
    Zerg 99 91 92 78 99 95 94 96 99 100
    Mengle 99 93 94 92 94 95 99 100 99 100

    He pressed some keys at the end of my file,then this time everything is ok.He told me that I have a space in the end of list.txt .So the question is how do I always make the system to know the real end of the input?(like put a . in the end )

  7. #7
    Sweet
    Join Date
    Aug 2002
    Location
    Tucson, Arizona
    Posts
    1,820
    The way kurt just told you? Or read the file line by line and ignore blank lines

  8. #8
    Registered User
    Join Date
    May 2007
    Posts
    67
    I am sorry,what is "kurt" ?and what do you mean by "read the file line by line and ignore blank lines"?

  9. #9
    Registered User
    Join Date
    May 2007
    Posts
    67
    and also can someone tell me what is the key to modify the input file to make the system know the real end?

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    If you use ZuK's example, you don't have to worry about any spaces or newlines at the end of the file. It will work no matter what.

    If your teacher is teaching you to use while(!in.eof()), then perhaps your teacher should come to this board and we can explain why it is a bad idea and why ZuK's solution is preferred.

  11. #11
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Quote Originally Posted by tx1988
    what do you mean by "read the file line by line and ignore blank
    lines"?
    Something like this
    Code:
        string input;
        while ( getline( in, input ) ) {
            if ( input.length() ) {  // ignore empty lines
                stringstream str( input );
                if ( str >>name>score[0]>>score[1]>>score[2]>>score[3]>>score[4]>>score[5]
                          >>score[6]>>score[7]>>score[8]>>score[9] ) {
                
                }
                else {
                    cout << "illegal line in inputfile '" << input << "'." << endl;
                }
            }
        }
    Quote Originally Posted by tx1988
    and also can someone tell me what is the key to modify the input file to make the system know the real end?
    On some systems ctrl-A is the magic key. It inserts eof into a text file.

    Kurt

  12. #12
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    There's no need to explicitly ignore blank lines in the file. They will be ignored automatically using ZuK's original solution. If you want to error out on blank lines, then the above code would work, but I don't see why that would be necessary.

  13. #13
    Registered User
    Join Date
    May 2007
    Posts
    67
    On some systems ctrl-A is the magic key. It inserts eof into a text file.
    are you sure I can use this?I think it means select the whole contents.And I tried and failed.This is not the magic key!

    Code:
     while( in>>name>>score[0]>>score[1]>>score[2]>>score[3]>>score[4]>>score[5]
               >>score[6]>>score[7]>>score[8]>>score[9] ) {
               ....
         }
    I know it is a good way,but how about there are 20 quiz scores?This way will be too complicated!So I want to make sure how to tell the system the real end that I want in order to use !in.eof() theeasy way!
    So can someone tell me how to make system know the right end of the file?

  14. #14
    Registered User
    Join Date
    May 2007
    Posts
    67
    And also I still can't understand why the last person do 2 times.
    I know eof will read one more value character to determine whether it is true or false.So in my case,after read the last score[9] 100 for mengle,there is nothing after that score(unless blank).So the program should terminate,but why not?

  15. #15
    Registered User
    Join Date
    Jan 2005
    Posts
    7,366
    The only way while (!in.eof()) will work is if there are absolutely no characters after the last 100 in the file. Most files end with a newline, which is the character '\n'.

    So if your code looks like this:
    Code:
          while(!in.eof())
          {
    
             in>>name>>score[0]>>score[1]>>score[2]>>score[3]>>score[4]>>score[5]
               >>score[6]>>score[7]>>score[8]>>score[9];
    Then what will happen is that the 100 will be read in with the ifstream input file. The input file will then read the newline after the 100 and see that it is whitespace. This will tell it not to read any more and to store the 100 in score[9]. At that point, eof() is false because the end of the file has not been reached. That means your loop will run another time.

    So then the file will attempt to read into name. But that read will fail because there are no more non whitespace characters in your file. Once a read fails, the other reads will fail also, so nothing will be read into name, or score[0] or score[1], etc. Those values will be left unchanged from the previous time through the loop. Because you use those values without checking to see if the read succeeded or not, you print them out again. That is why the last line is printed twice.

    If you change your code to do this:
    Code:
          while(in>>name>>score[0]>>score[1]>>score[2]>>score[3]>>score[4]>>score[5]
               >>score[6]>>score[7]>>score[8]>>score[9])
          {
    then what you are doing is checking to see if all those reads succeeded. It works the same when the reads succeed. But at the end, when there is a newline at the end of the file but no more actual data, the reads will fail. This will cause that big long read to evaluate to false, which will break the loop. The code inside the loop that prints out the values won't be run, so the last line won't get output twice.

    Another similar solution that is slightly less safe but looks cleaner and will work for what you are doing is this:
    Code:
          while(in>>name)
          {
    
             in>>score[0]>>score[1]>>score[2]>>score[3]>>score[4]>>score[5]
               >>score[6]>>score[7]>>score[8]>>score[9];
    In this case, you are only checking to make sure the read worked for name, not the other values. This means it is less safe, but you don't seem to be too concerned about checking for other errors.

    Does that make more sense?


    Now, if your input file has no newline and no other characters after the last value, then the while (!in.eof()) will probably work. That is because it will read in the 100, then check to see if there are any other characters (incase it is 1000 or 1001 or something). At that point it will find that there are no more characters at all, and the end of file will be reached setting the eof flag. If you insist on using while(!in.eof()) then you have to delete all characters after the 100 in the input file. Just remember that it is better to fix the code to handle any input file than to change the input file to work with the code.
    Last edited by Daved; 09-10-2007 at 03:33 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Program exiting
    By sql.scripter in forum C Programming
    Replies: 9
    Last Post: 01-28-2006, 08:51 PM
  2. Anything wrong with this(char to short and int)
    By hckr83 in forum C Programming
    Replies: 3
    Last Post: 12-22-2005, 06:27 PM
  3. EOF messing up my input stream?
    By Decrypt in forum C++ Programming
    Replies: 4
    Last Post: 09-30-2005, 03:00 PM
  4. Dividing and EOF
    By Tride in forum C Programming
    Replies: 7
    Last Post: 09-27-2003, 05:26 PM
  5. Strange EOF happenings
    By fatinez in forum C Programming
    Replies: 6
    Last Post: 09-23-2003, 08:37 PM