【问题标题】:reading and parsing a file, assigning each piece of the parsed string to its own variable读取和解析文件,将解析后的字符串的每一部分分配给它自己的变量
【发布时间】:2014-02-23 00:14:02
【问题描述】:
 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 时,输出为:

约翰·多伊

马特·史密斯

在我添加第二个 getline(iss,name,',') 之前,cout 什么也没做。

谁能解释为什么它与重复的行一起工作以及为什么相同的代码对状态和电子邮件不起作用?

文件中的示例行:

1,john doe,freshman,jd@email.com

编辑:

我在第一个 getline(iss,name,',') 之前使用了 std::ignore(1,',') 并收到错误 'ignore' is undeclared in this namespace 'std'。

【问题讨论】:

  • 如果您还包括文件格式/布局会更容易。

标签: c++ parsing


【解决方案1】:

谁能解释为什么它与重复的行一起工作以及为什么相同的代码不能用于状态和电子邮件?

因为您对isa 的第一个操作是iss&gt;&gt;id

大概您的输入文件的格式为id,name,status,email。第一个操作最多读取但不包括第一个逗号。第一个逗号仍在输入流中。这意味着您的第一个 std::getline(iss,name,',') 会读取第一个逗号和第一个逗号之前剩余的所有内容。在第一个逗号之前剩下的所有东西——那是一个空字符串。

最好不要混合解析概念。沿逗号拆分行,然后解析每个拆分元素。


编辑
处理此问题的另一种方法:调用std::ignore 而不是第一次调用std::getline。下一个要读取的字符应该是逗号,所以忽略它。如果您可以假设格式正确的输入文件,这没关系。如果您必须处理人类创建的输入文件的变幻莫测,那就不行了。

另一个问题:假设某人的名字是“John Doe, PhD”或电子邮件地址是“John Doe, PhD”?


编辑 2
澄清一下,假设该行包含“1234,John Doe,freshman,jdoe@college_name.edu”。

iss&gt;&gt;id之前的输入指针:
1234,John Doe,freshman,jdoe@college_name.edu
^
iss&gt;&gt;id 的调用将id 设置为1234,并将输入指针前进到第一个非数字字符——第一个逗号。

iss&gt;&gt;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
______________^

【讨论】:

  • 这意味着您的第一个 std::getline(iss,name,',') 会读取第一个逗号和第一个逗号之前剩余的所有内容。 实际上,假设id 字段有效(因此全部读入 id 变量),第一个 getline 将不返回任何内容。逗号被丢弃。
  • 在第一个逗号之前剩下的所有东西——没有这样的东西。另一种看待它的方式:第一个逗号之前剩余的所有内容都是空字符串,这正是我在回答中所说的。
  • 读取第一个逗号和第一个逗号之前剩余的所有内容这就是我所指的。
  • @computerfreaker - 我想我们说的是同一件事。第一个 std::getline 没有名字。假设一个格式正确的输入文件,它会推进流指针,以便下一个要读取的字符是名称中的第一个字符。
  • 对。我想我误解了你的部分答案,我的错。
猜你喜欢
  • 2021-03-11
  • 2014-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-04
相关资源
最近更新 更多