Проблемы с чтением нескольких типов из стандартного ввода

Я новичок в С++, и у меня возникают проблемы с чтением нескольких типов из стандартного ввода. Я пытаюсь ввести такие данные, как:

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

и для каждой строки извлеките разные поля и сохраните их в структуре и векторе. После запуска main.cpp я получаю следующий вывод:

Smith
rpenter

Полная строка «Карпентер» не считывается полностью в Student_info.name. Он обрезается как «renter». Не уверен, в чем моя проблема. Может ли кто-нибудь помочь прояснить это?

#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;
}

person Bailey    schedule 08.10.2019    source источник
comment
Просканировав некоторое время глазами, я изо всех сил пытался объяснить, что происходит, но не мог. Поэтому я попытался воспроизвести, но не смог: MCVE на coliru. :-(   -  person Scheff's Cat    schedule 08.10.2019
comment
Я почему-то подозреваю, что double x; while(in >> x) потребляет Ca и не может вернуть их во входной поток в случае сбоя. (У меня нет лучшего оправдания под рукой.) Вы пытались проверить это с помощью файла вместо std::cin?   -  person Scheff's Cat    schedule 08.10.2019
comment
Тоже не может воспроизвести. Возможно, это может быть плохо написанное включение другого объявления. Вы должны показать полный исходный файл, включая объявления (#include и using). Единственная (незначительная) проблема здесь - это while (read...), который попытается дважды прочитать конец файла.   -  person Serge Ballesta    schedule 08.10.2019
comment
@Scheff: отлично работает даже при чтении с консоли...   -  person Serge Ballesta    schedule 08.10.2019
comment
Я оказался на странице std::num_get<>::get() и нашел следующее: Если соответствует одному из 0123456789abcdefxABCDEFX+-. Не то, чтобы operator>>(std::istream&, double&) пытался прочитать шестнадцатеричное значение. Вы можете попробовать с именами, не начинающимися с abcdefABCDEFX, чтобы доказать это правильно или неправильно... Может быть, компилятор (и ОС) были бы полезны. (Проводник компилятора?)   -  person Scheff's Cat    schedule 08.10.2019
comment
Однако решением может быть чтение строк с std::getline() сразу и их разбор в std::istringstream. Соответствующие изменения будут фактически ограничены main(). (Хорошая работа с std::istream&.) ;-)   -  person Scheff's Cat    schedule 08.10.2019
comment
Я отредактировал приведенный выше вопрос, чтобы включить полный источник. Меня больше интересует, почему я испытываю то поведение, которое испытываю. Этот связанный пост имеет ту же проблему, что и я (stackoverflow.com/questions/26580400/).   -  person Bailey    schedule 08.10.2019
comment
Кроме того, при запуске этого на Ubuntu с использованием компилятора gcc (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4 он работает нормально, как и ожидалось. Когда я запускаю это через CLion IDE с помощью компилятора C++ инструментов командной строки xcode, я сталкиваюсь с проблемой, описанной выше.   -  person Bailey    schedule 08.10.2019


Ответы (1)


Замените цикл while внутри функции read_hw() на это:

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

Но будьте осторожны, вы должны вводить каждую студенческую запись в отдельной строке. Кроме того, пользователь не должен вводить никаких других символов, кроме '\n' после прочтения последней оценки за домашнее задание для этой конкретной студенческой записи.

person srt1104    schedule 08.10.2019