Краткая версия вопроса
Если я читаю данные, например, так:
while (in >> x) {
hw.push_back(x);
}
// clear the stream so that input will work for the next student
in.clear();
, где in
- это std::istream
, x
- это double
, а hw
- это vector<double>
. Разве мне не нужно было откладывать обратно любую попытку чтения, которая вызвала у меня всплеск, пока я oop? Иначе, не будет ли мое следующее чтение из in
пропустить некоторые данные?
Полный вопрос
Я пытаюсь прочитать из текстового файла, который содержит строку и ряд чисел. Я обрабатываю эти данные в структуре, которая содержит атрибуты членов для этих данных.
Входные данные выглядят следующим образом: Moore 75 85 77 59 0 85 75 89
Эти данные представляют собой имя студента, его итоговую оценку на экзамене их промежуточный экзамен и некоторая домашняя работа.
И чтобы прочитать такие данные, у меня есть следующее:
#include <boost/format.hpp>
#include <iostream>
#include <string>
using std::istream;
using std::vector;
using std::cout;
using std::string;
using std::cin;
struct Student_info {
std::string name;
double midterm, final;
std::vector<double> homework;
};
istream& read(istream&, Student_info&);
istream& read_hw(istream&, vector<double>&);
istream& read(istream& is, Student_info& s) {
// Read and store th studen'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;
}
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;
}
Короче говоря, и если мое понимание верно, я сначала читаю имя, затем два двойных (итоговый и промежуточный экзамен), а также много домашних заданий.
Я знаю, когда прекратить чтение в vector<double>
оценок за домашнее задание со следующим:
while (in >> x) {
hw.push_back(x);
}
// clear the stream so that input will work for the next student
in.clear();
Все это выглядит совершенно разумным для меня, но когда я читаю серию строк данных, данные не читаются должным образом.
Например, со следующим вводом:
Moo 100 100 100 100 100 100 100 100
Moore 75 85 77 59 0 85 75 89
Norman 57 78 73 66 78 70 88 89
Я получаю следующий вывод:
Name: Moo, Midterm: 100, Final: 100, Num HW: 6
Name: Moore, Midterm: 75, Final: 85, Num HW: 6
Name: orman, Midterm: 57, Final: 78, Num HW: 6
Обратите внимание, что имя orman , НЕ Норман. N отсутствует. Это не опечатка, это проблема, которую я пытаюсь понять.
Мне кажется, что мне нужно "забыть", хотя, когда я пытаюсь буквально вызвать in.unget()
, это не улучшает ситуацию.
Ниже приведены некоторые полные входные данные и полный источник для программы драйвера, если кто-то захочет попробовать это в своих руках:
Полные входные данные
Moo 100 100 100 100 100 100 100 100
Moore 75 85 77 59 0 85 75 89
Norman 57 78 73 66 78 70 88 89
Olson 89 86 70 90 55 73 80 84
Peerson 47 70 82 73 50 87 73 71
Russel 72 87 88 54 55 82 69 87
Thomas 90 96 99 99 100 81 97 97
Vaughn 81 97 99 67 40 90 70 96
Westerly 43 98 96 79 100 82 97 96
Baker 67 72 73 40 0 78 55 70
Davis 77 70 82 65 70 77 83 81
Edwards 77 72 73 80 90 93 75 90
Franklin 47 70 82 73 50 87 73 71
Jones 77 82 83 50 10 88 65 80
Harris 97 90 92 95 100 87 93 91
Smith 87 92 93 60 0 98 75 90
Carpenter 47 90 92 73 100 87 93 91
Fail1 45 55 65 80 90 70 65 60
Fail2 55 55 65 50 55 60 65 60
Полный источник программы драйвера
#include <boost/format.hpp>
#include <iostream>
#include <string>
using std::istream;
using std::vector;
using std::cout;
using std::string;
using std::cin;
struct Student_info {
std::string name;
double midterm, final;
std::vector<double> homework;
};
istream& read(istream&, Student_info&);
istream& read_hw(istream&, vector<double>&);
istream& read(istream& is, Student_info& s) {
// Read and store th studen'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;
}
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;
}
int main() {
vector<Student_info> students;
Student_info record;
string::size_type maxlen = 0;
while (read(cin, record)) {
// find length of longest name
cout << boost::format("Name: %1%, Midterm: %2%, Final: %3%, Num HW: %4%\n") % record.name % record.midterm % record.final % record.homework.size();
students.push_back(record);
}
return 0;
}
При использовании полных входных данных вывод выглядит следующим образом (обратите внимание, что многие имена были неверны):
Name: Moo, Midterm: 100, Final: 100, Num HW: 6
Name: Moore, Midterm: 75, Final: 85, Num HW: 6
Name: orman, Midterm: 57, Final: 78, Num HW: 6
Name: Olson, Midterm: 89, Final: 86, Num HW: 6
Name: rson, Midterm: 47, Final: 70, Num HW: 6
Name: Russel, Midterm: 72, Final: 87, Num HW: 6
Name: Thomas, Midterm: 90, Final: 96, Num HW: 6
Name: Vaughn, Midterm: 81, Final: 97, Num HW: 6
Name: Westerly, Midterm: 43, Final: 98, Num HW: 6
Name: ker, Midterm: 67, Final: 72, Num HW: 6
Name: vis, Midterm: 77, Final: 70, Num HW: 6
Name: wards, Midterm: 77, Final: 72, Num HW: 6
Name: ranklin, Midterm: 47, Final: 70, Num HW: 6
Name: Jones, Midterm: 77, Final: 82, Num HW: 6
Name: Harris, Midterm: 97, Final: 90, Num HW: 6
Name: Smith, Midterm: 87, Final: 92, Num HW: 6
Name: rpenter, Midterm: 47, Final: 90, Num HW: 6
Name: l1, Midterm: 45, Final: 55, Num HW: 6
Name: l2, Midterm: 55, Final: 55, Num HW: 6
Обновление 1
Я пытался добавить in.seekg(-1, in.cur);
после выхода из следующего, пока l oop:
double x;
while (in >> x) {
hw.push_back(x);
}
// Going to try and get the istream back to where it was when I broke out of the while loop.
in.seekg(-1, in.cur);
// clear the stream so that input will work for the next student
in.clear();
Думая, что это займет у меня вернуться к тому, что заставило меня вспыхнуть в то время как я oop. Но все же имена учеников по-прежнему не читаются правильно
Обновление 2
Я вижу, что здесь почти идентичный вопрос:
Почему istream.clear () удаляет часть моих строк при чтении парных и строковых значений?
Однако принятое решение не объясняет , почему то, что здесь делается, неправильно - он просто предлагает обходной путь.
Обновление 3
Я ценю все обходные пути, но рассмотрим этот более сфокусированный вопрос, почему не в каждой последующей строке отсутствует буква здесь или там? Только некоторые строки.