чтение и анализ файла, присвоение каждой части анализируемой строки своей переменной

0
 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".

  • 1
    Было бы проще, если бы вы также включили формат файла / макет.
Теги:
parsing

1 ответ

3

Может ли кто-нибудь объяснить, почему он работает с повторяющейся линией и почему тот же код не будет работать для статуса и электронной почты?

Потому что ваша первая операция на 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
______________^

  • 0
    Это означает, что ваш первый std :: getline (iss, name, ',') читает весь материал, оставшийся до первой запятой и первой запятой. На самом деле, предполагая, что поле id является действительным (и, следовательно, все считывается в переменную id), первая getline ничего не будет возвращать. Запятая отбрасывается.
  • 1
    Все, что осталось до первой запятой, - такого нет. Еще один способ взглянуть на это: все, что осталось до первой запятой, - это пустая строка, о чем я и говорил в своем ответе.
Показать ещё 7 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню