89 int Student::loadStudents() {
90 Student newStudent;
91 string comma;
92 string line;
93 ifstream myfile("student.dat");
94 string name,email="";
95 string status="";
96 int id;
97 if (myfile.is_open()){
98 while ( getline (myfile,line) ) {
99 //parse line
100 string myText(line);
101 istringstream iss(myText);
102 if(!(iss>>id)) id=0;
103
104 std::ignore(1,',');
105 std::getline(iss,name,',');
106 std::getline(iss,status,',');
107 std::getline(iss,email,',');
108 cout<<name<<endl;
109 Student newStudent(id,name,status,email);
110 Student::studentList.insert(std::pair<int,Student>(id,newStudent));
Выше - метод, который я определяю. Когда cout выполняется, выход:
Джон Доу
Matt Smith
Прежде чем я добавил во второй getline (iss, name, ','), cout ничего не сделал.
Может ли кто-нибудь объяснить, почему он работает с повторяющейся линией и почему тот же код не будет работать для статуса и электронной почты?
пример строки из файла:
1, john doe, первокурсник, jd @email.com
РЕДАКТИРОВАТЬ:
Я использовал std :: ignore (1, ',') перед первой getline (iss, name, ',') и получил ошибку "ignore", которая не объявлена в этом пространстве имен "std".
Может ли кто-нибудь объяснить, почему он работает с повторяющейся линией и почему тот же код не будет работать для статуса и электронной почты?
Потому что ваша первая операция на isa
is is iss>>id
.
Предположительно, ваш входной файл имеет форму id,name,status,email
. Эта первая операция считывает, но не включает первую запятую. Эта первая запятая все еще находится во входном потоке. Это означает, что ваш первый std::getline(iss,name,',')
читает все остальное до первой запятой и первой запятой. Все остальное до первой запятой - пустая строка.
Лучше не смешивать понятия синтаксического анализа. Разделите линию вдоль запятых, затем проанализируйте каждый из этих разделенных элементов.
редактировать
Другой способ справиться с этой проблемой: вызвать std::ignore
вместо этого первого вызова std::getline
. Следующий символ, который нужно читать, должен быть запятой, поэтому просто игнорируйте его. Это нормально, если вы можете принять правильно отформатированный входной файл. Это не нормально, если вам приходится иметь дело с капризами входных файлов, созданных людьми.
Другая проблема: предположим, что имя кого-то "John Doe, PhD" или адрес электронной почты "John Doe, PhD"?
Изменить 2
Чтобы уточнить, предположим, что строка содержит "1234, John Doe, первокурсник, jdoe @college_name.edu".
Указатель ввода до вывода iss>>id
: 1234,John Doe,freshman,jdoe@college_name.edu
^
При вызове iss>>id
задает id
до 1234 и продвигает указатель на первый нечисловой символ - первую запятую.
Указатель ввода после iss>>id
(до первого вызова std::getline
): 1234,John Doe,freshman,jdoe@college_name.edu
____^
Первый std::getline(iss,name,',')
видит, что указатель ввода находится в запятой. Он задает name
пустой строке и продвигает указатель ввода сразу после запятой.
Введите указатель после первого вызова std::getline
(до второго вызова std::getline
): 1234,John Doe,freshman,jdoe@college_name.edu
_____^
Второй std::getline(iss,name,',')
читается до второй запятой. Он задает name
пустой строке "John Doe" и продвигает указатель ввода сразу после второй запятой.
Введите указатель после второго вызова std::getline
(до третьего вызова std::getline
): 1234,John Doe,freshman,jdoe@college_name.edu
______________^