3

In the following simple code snippet, the end-of-file can be easily indicated by pressing ctrl-z.

double x;

while ( cin >> x )
{
    ++count;
    sum += x;
}

But when I try a more complicated program, such as reading in student records to do some processing, I fail to indicate the end-of-file to the program.

For example, I have a struct object called Student_info

struct Student_info
{
    string name;
    double midterm, final;
    vector<double> homework;
};

I have written several functions to read in and store several student records, as follows:

while ( read( cin, record ) )
{
    students.push_back( record );
}

But after inputting a few student records, when I do ctrl-z and hit the Enter to see the results, the command prompt is still waiting for me.

What am I doing wrong?

p.s.1. I separate names and grades with a blank space, and I separate students' details by jumping to the next line, which should be pretty much the same; i.e. some space separator. Right?

p.s.2. This code is adopted from the Accelerated C++ Book, and my knowledge of it is just up until Chapter 5 at the moment...

Thank you in advance,

EDIT

Below are two more functions that I use:

istream& read( istream& is, Student_info& s )
{
    is >> s.name >> s.midterm >> s.final;

    read_hw( is, s.homework );

    return is;
}


istream& read_hw( istream& in, vector<double>& hw )
{
    if ( in )
    {
        hw.clear();

        double x;
        while ( in >> x )
            hw.push_back( x );

        in.clear();
    }

    return in;
}
  • 4
    You should post the content of the `read()` function. – Synxis Dec 30 '13 at 14:04
  • 1
    I assume you are using windows. (on *nix systems, ctrl-Z will cause a SIGTSTP to be sent the foreground process, causing the program to go to sleep rather that closing the input stream) If not, then what you are doing wrong is using ctrl-Z instead of ctrl-D. – William Pursell Dec 30 '13 at 14:12
  • 1
    You must be on Windows, because everywhere else, ^Z is the SUB control character (and Ctrl-Z is overridden to send a suspend signal). Anyway, it's up to your program to handle the character. The first one only works because it puts your stream in a fail state and the `while` loop ends. It isn't automatically handling it for you. – Joseph Mansfield Dec 30 '13 at 14:20
  • Please see the added EDIT. –  Dec 31 '13 at 15:57

2 Answers2

2

The easiest solution would be to write an std::istream& operator>> ( std::istream& in, Student_info&) which behaves similarly to the existing operator>>. You can then use exactly the same loop:

Student_info record;
while ( cin >> record )
{
    ++count;
    students.push_back( record );
}

Inside your operator>>, you should just call operator>> for all members, and then return the istream& in argument.

MSalters
  • 173,980
  • 10
  • 155
  • 350
  • 2
    I think you want `operator>>`, not `operator<<`... Anyway, this does not really answers the OP's question. – Synxis Dec 30 '13 at 14:15
  • 1
    @Synxis: Fixed >>. And actually this will answer the OP's question. The reason why his simple loop worked is because the result tests `std::cin`, which checks for EOF and other problems. His code apparently doesn't notice EOF, so he's not testing `std::cin`. my code keeps the check on `std::cin` by returning it from `operator>>`. It therefore spots EOF just like the original code did. – MSalters Dec 30 '13 at 14:27
  • 1
    You probably meant to write `std::cin >> record` instead of `std::cin >> x` – Dietmar Kühl Dec 30 '13 at 15:11
  • 1
    I really need to stop coding in two windows at the same time :| – MSalters Dec 30 '13 at 15:21
1

when the cin read the EOF, it only set the instream flag eofbit and failbit. When you use

while(cin>>x)

,it implicit indicate a operator bool (std::cin),it return false when read EOF(the cin >> x return cin). Thus the while loop end.

But when you use

while ( read( cin, record ) )

the cin also return false when it read EOF,but your function read didn't recognize it.And when the while loop continue, the loop occur a new cin. And the important is the failbit flag will save in you stream until you use cin.clear().Thus your code is not good as overload operator >> for your student struct. I am sorry for my English,and hope you can clear.

Tu Xiaomi
  • 61
  • 8