【问题标题】:Reading in a .txt file word by word to a struct in C++逐字读取 .txt 文件到 C++ 中的结构
【发布时间】:2011-10-30 21:13:23
【问题描述】:

我的 CMPT 课程的实验作业遇到了一些问题... 我正在尝试读取每行包含两个单词和一串数字的文本文件,并且该文件可以是任何人制作的长度。

一个例子是

Xiao Wang 135798642
Lucie Chan 122344566
Rich Morlan 123456789
Amir Khan 975312468
Pierre Guertin 533665789
Marie Tye 987654321

我必须让每一行都成为一个单独的“学生”,所以我正在考虑使用 struct 来做到这一点,但我不知道该怎么做,因为我需要将第一个、最后一个和 ID 号分开.

struct Student{
    string firstName;
    string secondName;
    string idNumber;
};

所有尝试分别阅读每个单词的尝试都失败了(最终改为阅读整行),我有点沮丧。

在@Sylence 的帮助下,我设法分别阅读了每一行。不过,我仍然对如何用空格分割行感到困惑。 ifstream中是否有拆分功能? Sylence,'parts' 会是一个数组吗?我看到你在 [] 中有索引。 students.add( stud ) 到底是做什么的? 到目前为止我的代码是:

int getFileInfo()
{
    Student stdnt;
    ifstream stdntFile;
    string fileName;
    char buffer[256];
    cout<<"Please enter the filename of the file";
    cin>>filename;
    stdntFile.open(fileName.c_str());
    while(!stdFile.eof())
    {
        stdFile.getLine(buffer,100);
    }
    return 0;
}

这是我修改后的最终版本的 getFileInfo(),感谢 Shahbaz,感谢 Shahbaz 提供了一种简单快捷的方式来读取数据。

void getFileInfo()
{
    int failed=0;
    ifstream fin;
    string fileName;
    vector<Student> students; // A place to store the list of students

Student s;                  // A place to store data of one student
cout<<"Please enter the filename of the student grades (ex. filename_1.txt)."<<endl;
do{
    if(failed>=1)
        cout<<"Please enter a correct filename."<<endl;
    cin>>fileName;
fin.open(fileName.c_str());// Open the file
failed++;
}while(!fin.good());
while (fin >> s.firstName >> s.lastName >> s.stdNumber)
    students.push_back(s);
fin.close();
cout<<students.max_size()<<endl<< students.size()<<endl<<students.capacity()<<endl;


return;
}

我现在很困惑的是如何访问输入的数据!我知道它被放入了一个向量中,但是如何访问向量中的各个空间,以及输入的数据到底是如何存储在向量中的?如果我尝试计算向量的一个点,我会收到一个错误,因为我猜 Visual Studio 不知道要输出什么..

【问题讨论】:

  • 抱歉,txt文件的链接失效了,
  • 那么您尝试过做什么?向我们展示您的努力,以便我们为您提供帮助。
  • 好的.. 感谢您的快速回复。我很乐意向您展示我目前所拥有的,但我无法弄清楚如何格式化此评论框中的代码。我只是在它周围加上撇号或[代码]或其他东西吗?对不起,我的能力不够。。
  • 修改您的问题。不要将代码放在 cmets 中。编辑窗口顶部有按钮。选择您的代码部分并单击代码按钮(引号)。

标签: c++ string file-io input vector


【解决方案1】:

其他答案都不错,但看起来有点复杂。您可以通过以下方式完成:

vector<Student> students;   // A place to store the list of students

Student s;                  // A place to store data of one student

ifstream fin("filename");   // Open the file

while (fin >> s.firstName >> s.secondName >> s.idNumber)
    students.push_back(s);

请注意,如果 istream 失败,例如文件完成时,istream 对象 (fin) 将评估为 false。因此while (fin &gt;&gt; ....) 将在文件完成时停止。

附:不要忘记检查文件是否打开。

【讨论】:

  • 那么我将如何对文件中的整个行列表重复此操作,以及如何告诉它为每次迭代创建新的学生结构??
  • 不错的解决方案 :) @b3orion 您不需要为每次迭代创建一个新对象,因为向量使用您提供的数据的副本。
  • 好的,所以我不需要每次都创建一个新学生,但是对于循环,我是否只使用一个while循环?我只是很困惑如何告诉它每次迭代使用哪一行。就目前而言,没有循环,它只读取文件的最后一行。
  • fin &gt;&gt; s.firstName &gt;&gt; s.secondName &gt;&gt; s.idNumber 从文件中读取一行数据并放入s,这是一个Student 类型的局部变量。 students.push_back(s) 复制s 并输入students。在while 循环中,您继续读取行,覆盖相同的局部变量s 并将其副本添加到students。因此,你得到了所有的学生。文件结束时循环停止。
  • 好的,我现在明白了。感谢您清除它!我将如何找到每个学生的存储位置。我的意思是,我如何访问每个学生?这是我第一次使用向量和结构,以及文件输入!所以这对我来说有点模糊!谢谢大家的帮助!!
【解决方案2】:

为学生定义一个流阅读器:

std::istream& operator>>(std::istream& stream, Student& data)
{
    std::string line;
    std::getline(stream, line);

    std::stringstream   linestream(line);
    linestream >> data.firstName >> data.secondName >> data.idNumber;

    return stream;
}

现在您应该能够从任何流(包括文件)流式传输对象:

int main()
{
    std::ifstream    file("data");
    Student          student1;

    file >> student1;   // Read 1 student;

    // Or Copy a file of students into a vector
    std::vector<Student>   studentVector;
    std::copy(std::istream_iterator<Student>(file),
              std::istream_iterator<Student>(),
              std::back_inserter(studentVector)
             );
}

【讨论】:

  • 这究竟是如何工作的?你能在代码中添加一些 cmets 吗?
  • 既然这是家庭作业,我想你最好自己弄清楚细节。如果您将此信息与@Shahbaz 答案结合起来,那么您应该拥有所需的所有详细信息。
  • 但是代码@Shahbaz 不是已经输入了读入Student 的文本吗?为什么需要流式阅读器?不过,我对如何访问 strcut 中的每个学生感到困惑。我如何选择每个学生,因为它把他们放在一个向量中......
【解决方案3】:

只需读取一整行,然后在空格处拆分字符串并将值分配给结构的对象。

伪代码:

while( !eof )
   line = readline()
   parts = line.split( ' ' )

   Student stud = new Student()
   stud.firstName = parts[0]
   stud.secondName = parts[1]
   stud.idNumber = parts[2]  

   students.add( stud )     
end while

【讨论】:

  • 这实际上都是错误的(在很多方面)。请修复,否则我将投反对票。
  • 我对伪代码没有任何问题。但是你违反了几条关键规则。 1)不要在一段时间内测试 eof (适用于所有语言(因为 EOF 不会发生,直到你读过 EOF,这会导致循环进入额外的时间) 2)不要使用 new 特别是当回答 C++ 问题。 3) 在很多语言中按空格分割是可以的,但实际上在 C++ 中会导致你走错路
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-25
相关资源
最近更新 更多