因为来自文件的数据看起来像这样:第1行是名字(第一个最后一个),下一行是得分(得分1得分2 ......得分5)等等......所以我认为我需要获取名称和>>得分
数据文件示例
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
}
问题是在读完所有分数(第一个玩家)之后,似乎没有进入下一行继续阅读下一个名字,那里有点乱。那么任何纠正我的代码或新想法的建议都可以吗?
答案 0 :(得分: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');
视情况检查错误。 >>
运算符getline
和ignore
都返回流引用,您可以检查是否成功。
不需要j
循环,因为每次迭代都会完全不同。只需编写j=0
案例后紧跟j=1
案例,然后摆脱循环,就像上面的代码一样。 (并注意j
在循环内永远不会等于2,所以无论如何你的情况都是错的。)
答案 1 :(得分:1)
您的主要问题是您正在使用&gt;&gt;读取整数直接来自流。这与从流中读取字符串相结合是一个坏主意。阅读字符串将删除新行将使用&gt;&gt;不会删除新行。
最好不要混合两种形式。要么总是使用&gt;&gt;或者总是使用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));
}