从文件中读取到一行的末尾,并为下一行重复该过程

时间:2019-01-25 22:50:54

标签: c++

我正在使用此.txt文件:

Anna 70 79 72 78 71 73 68 74 75 70
Jason 78 89 96 91 94 95 92 88 95 92
kim 83 81 93 85 84 79 78 90 88 79
Maria 93 100 86 99 98 97 96 95 94 92

我将名称存储在结构的向量中的每一行中,该向量包含字符串名称和一个int分数。在分数中,我存储了姓名后面所有数字的平均值(10个数字/ 10)。

我已经做完了所有工作,它以正确的名称和平均分数存储了第一行,但是我正在努力的是对以下数据重复此过程。 (詹森+他的号码,金...)

struct Student
{
    string name;
    int score;
};

void printInfo(vector<Student>);


int main() {

    string defaultPath = "lab2.txt";
    ifstream inFile(defaultPath);

    vector<Student> studentData;

    string name;
    int score = 0, totalScore = 0, averageScore = 0;

    while (inFile >> name)
    {
        while (inFile >> score)
        {
            totalScore += score;
        }
        averageScore = totalScore / 10;
        studentData.push_back({name, averageScore});
    }

    cout << studentData[0].name << '\t' << studentData[0].score << endl;

}

此代码的输出:

  

安娜73

(第一行中的名称+计算出的平均值)

studentData[1].name / .score上面有垃圾。

谢谢您的帮助!

4 个答案:

答案 0 :(得分:1)

当前代码的问题在于,当您阅读分数时,您实际上并不知道分数何时结束。仅当您读取下一行名称时,循环才会失败,这将使流进入错误状态,并且不再读取任何内容。

我建议您解决问题(并使代码更健壮)的方式是

  1. Read line by line into a string
  2. 将字符串放入input string stream
  3. 从输入字符串流中读取名称
  4. 从输入字符串流中循环读取“分数”(如您所知)。
  5. 完成,转到下一行(返回1)

其他可能的解决方案是在读取分数后清除所有错误状态。或使用for循环。这两项都要求您希望行没有格式错误,或者读取文件时没有 real 错误。

答案 1 :(得分:0)

问题在于内部循环。当它无法读取数字时,它将退出并使流保持错误状态。这会导致外循环也失败。

建议您使用嵌套的字符串流,这是缓解此问题的最简单方法:

while (inFile >> name)
{
    while (inFile >> score)
    {
        totalScore += score;
    }
    averageScore = totalScore / 10;
    studentData.push_back({name, averageScore});

    if (!inFile.eof()) {
        inFile.clear();
    }
}

这实际上清除了流可能处于的任何错误状态,但只有在未设置eof bit的情况下,才会这样做。


  • 运行代码后,我发现您在进行下一次计算之前不会将totalScore重置为零。

答案 2 :(得分:0)

@smac89's answer已指出问题。我想提出一个略有不同的答案。

  1. 阅读所有文本,直到没有内容可阅读为止。
  2. 使用std::istringstream分别处理每一行文本。

我还建议:

  1. 仅在需要的范围内声明变量。
  2. 不要假设有10个数字。计算成功读取的数字数,并使用该计数计算平均值。

std::string line;
while (inFile >> line)
{
   std::string name;
   std::istringstream str(line);
   if ( !(str >> name) )
   {
      // Deal with error.
   }

   int count = 0;
   int score = 0;
   int totalScore = 0;
   while (str >> score)
   {
      totalScore += score;
      ++count;
   }

   if ( count > 0 )
   {
      int averageScore = totalScore / count;
      studentData.push_back({name, averageScore});
   }
}

答案 3 :(得分:0)

这是将来方便您使用的简便方法:)

 #include <fstream>
 #include <sstream>

 struct Student
{
    string name;
    int score;
};

void printInfo(vector<Student>);

int main() {

    string defaultPath = "lab2.txt";
    ifstream inFile(defaultPath);

    vector<Student> studentData;
    string line;
    string name;
    string Sscore;
    int totalScore = 0, averageScore = 0;
    // first read the line
    while (getline(inFile,line))
    {
        totalScore = 0; averageScore = 0;
        stringstream temp(line);
        // read the first word which is delimited by a space

        getline(temp, name,' ');
        // read the rest words which are delimited by a space in the same line
        while (getline(temp, Sscore, ' '))
        {
            totalScore += atoi(Sscore.c_str());
        }
        averageScore = totalScore / 10;
        studentData.push_back({ name, averageScore });
    }

    cout << studentData[1].name << '\t' << studentData[1].score << endl;
    inFile.close();
}