1
votes

I am new to c++ and I am running into issues reading multiple types from standard input. I am trying to take input such as:

Smith 93 91 47 90 92 73 100 87
Carpenter 75 90 87 92 93 60 0 98

and for each line extract the different fields and store them into a struct and a vector. After running main.cpp the output I get is:

Smith
rpenter

The full string 'Carpenter' is not being read fully into Student_info.name. It is being cut off as 'rpenter'. Not sure what my issue is here. Could anyone help clear this up?

#include <iostream>
#include <vector>

using std::istream;
using std::vector;
using std::string;
using std::endl;
using std::cout;
using std::max;
using std::cin;

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

// read homework grades from an input stream into a vector<double>
istream &read_hw(istream &in, vector<double> &hw) {
    if (in) {
        // get rid of previous contents
        hw.clear();

        // read homework grades
        double x;
        while (in >> x) {
            hw.push_back(x);
        }
        // clear the stream so that input will work for the next student
        in.clear();
    }
    return in;
}

istream &read(istream &is, Student_info &s) {
    // read and store the student's name and midterm and final exam grades
    is >> s.name >> s.midterm >> s.final;

    read_hw(is, s.homework); // read and store all the student's homework grades
    return is;
}

int main() {
    vector<Student_info> students;
    Student_info record;
    string::size_type maxlen = 0;

    //read and store all the records, and find the length of the longest name
    while (read(cin, record)) {
        maxlen = max(maxlen, record.name.size());
        students.push_back(record);
    }

    for (vector<Student_info>::size_type i = 0; i != students.size(); ++i) {

        // write the name, padded on the right to maxlen + 1 characters
        cout << students[i].name << endl;

    }

    return 0;
}
1
After scanning a while with eyes, I struggled to explain what happens but I couldn't. Hence, I tried to reproduce but I cannot: MCVE on coliru. :-( - Scheff's Cat
I somehow suspect that double x; while(in >> x) consumes Ca and cannot push them back to input stream on failure. (I have no better excuse at hand.) Have you tried to test this with a file instead of std::cin? - Scheff's Cat
Cannot reproduce either. Maybe it could be a badly written include of other declaration. You should show the full source file including the declarations (#include and using). The only (minor) problem here is the while (read...) which will try to read twice the end of file. - Serge Ballesta
@Scheff: works fine even when reading from the console... - Serge Ballesta
I ended up in std::num_get<>::get() and found this: If the character matches one of "0123456789abcdefxABCDEFX+-". Not that operator>>(std::istream&, double&) tries to read a hex value. You could try with names not starting with abcdefABCDEFX to prove this right or wrong... May be, compiler (and OS) would be helpful. (Compiler Explorer?) - Scheff's Cat

1 Answers

0
votes

Replace your while loop inside read_hw() function with this:

while (in.peek() != '\n' && in >> x) {
    hw.push_back(x);
}

But be careful, you must enter every student record in separate line. Also, the user should input no other character but '\n' after the reading the last homework grade for that particular student record.