0

因为文件中的数据如下所示:第 1 行是名称(第一个最后一个),下一行是分数(score1 score 2 ....score5)等等......所以我认为我需要 getline 作为 name 和 >> for分数

数据文件示例

David Beckham
80 90 100 20 50
Ronaldinho Gaucho
99 80 100 20 60
....

首先,我有结构

struct Player {
string name;
int score[5];
} player[size]

从文件中读取数据时

int i = 0;
while(!file.eof())
    {
        for (int j = 0; j < 2; j++) //read each 2 two lines
        {               
            if(j==0) // name
            {               
                getline(file, player[i].name);  
            }
                        else if(j==1) // score
            {
                for(int k=0; k<5; k++) file >> player[i].grade[k];
            }
                }
         i++; //move to next player
    }

问题是在阅读了所有分数(第一个玩家的)之后,似乎没有去下一行继续阅读下一个名字,那里有点乱。那么有什么建议可以纠正我的代码或新想法吗?

4

2 回答 2

4

读完最后一个分数后,换行符仍在输入缓冲区中。你需要跳过那个。该ignore功能对此很有用。

getline(file, player[i].name);
for (int k = 0; k < 5; ++k)
  file >> player[i].grade[k];
file.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

根据需要检查错误。>>运算符、和getlineignore返回流引用,您可以检查它是成功还是失败。


不需要那个j循环,因为每次迭代都会做完全不同的事情。只需在j=0case 之后立即编写j=1case,然后摆脱循环,就像我上面的代码一样。(请注意,j循环内永远不会等于 2,所以无论如何你的条件都是错误的。)

于 2012-06-14T18:40:42.737 回答
1

您的主要问题是您正在使用 >> 直接从流中读取整数。这与从流中读取字符串相结合是一个坏主意。读取字符串会删除新行,使用 >> 读取不会删除新行。

最好不要混合这两种形式。要么总是使用>>,要么总是使用getline()。注意:我不是说最好,我说的是最简单。当您了解权衡以及如何补偿它们的使用差异时,您可以一起使用它们。

因此,将数字行读入字符串然后解析字符串更容易。

std::string  lineOfNumbers;
std::getline(file, lineOfNumbers);

// Now you have read all the numbers and the new line.
std::stringstream streamOfNumbers(lineOfNumbers);
while(streamOfNumbers >> value)
{
    // Do something with number.
}

使用几乎总是错误的:

while(!file.eof())

这是因为在您阅读 eof 之后才设置 EOF 标志。请注意,最后一次读取将读取到但不会超过 eof。因此,即使没有可用数据,您也将进入循环。

标准模式是:

while(file >> object)
{
   // Action
}

考虑到这一点,我将定义一个代表您想要的所有信息的类(即两行)。一个简单的版本是

class TwoLineReader
{
   public:
     std::string line1;
     std::string line2;
};
std::istream& operator>>(std::istream& stream, TowLineReader& record)
{
    std::getline(stream, record.line1);
    std::getline(stream, record.line2);
    return stream;
}

TowLineReader   obj;
while(file >> obj)
{
     // Do stuff
}

如果您只想读取行,这很好。
但是数据看起来像是有结构的。所以我会构造一个代表数据的类,然后将数据直接读入该结构。所以这更多的是我会做的。我也会用算法替换 while() 循环。

标头

#include <algorithm>
#include <iterator>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

/*
 * Example Data

David Beckham
80 90 100 20 50
Ronaldinho Gaucho
99 80 100 20 60
 */

班上:

class Player
{
    std::string         name;
    std::vector<int>    goals;

    // Stream operator that reads a platers name and his goals.
    friend std::istream& operator>>(std::istream& stream, Player& record)
    {   
        // Read the name
        std::getline(stream, record.name);

        // Read the line of goals.
        // Copies the data into goals.
        std::string scores;
        std::getline(stream, scores);

        // std::copy replaces a while loop that pushes each number into the vector.
        std::stringstream scorestream(scores);
        std::copy( std::istream_iterator<int>(scorestream), 
                   std::istream_iterator<int>(), 
                   std::back_inserter(record.goals));

        return stream;
    }   
};

用法:

int main()
{

    std::ifstream   dataFile("data");
    std::vector<Player>   players;

    // Copy all players into a vetor
    std::copy( std::istream_iterator<Player>(dataFile), 
               std::istream_iterator<Player>(), 
               std::back_inserter(players));
}
于 2012-06-14T19:22:12.140 回答