C++ 使用getline和>&燃气轮机;读取文件C++;

C++ 使用getline和>&燃气轮机;读取文件C++;,c++,getline,C++,Getline,因为文件中的数据如下所示:第1行是名称(最后一行),下一行是分数(score1分数2…score5),依此类推。。。所以我想我需要getline作为name,而>>作为score 数据文件示例 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

因为文件中的数据如下所示:第1行是名称(最后一行),下一行是分数(score1分数2…score5),依此类推。。。所以我想我需要getline作为name,而>>作为score

数据文件示例

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
    }
inti=0;
而(!file.eof())
{
对于(int j=0;j<2;j++)//每2行读取两行
{               
如果(j==0)//名称
{               
getline(文件,player[i].name);
}
如果(j==1)//得分,则为else
{
对于(int k=0;k>player[i]。等级[k];
}
}
i++;//移动到下一个玩家
}

问题是在读取(第一名球员的)所有分数后,似乎没有转到下一行继续读取下一个名称,这有点混乱。因此,有没有任何建议来更正我的代码或执行此操作的新想法?

在读取最后一个分数后,换行符仍然位于输入缓冲区上。您需要跳过它。该函数对此很有用

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(文件,播放器[i].name);
对于(int k=0;k<5;++k)
文件>>玩家[i].等级[k];
ignore(std::numeric_limits::max(),'\n');
根据需要检查错误。
>
运算符、
getline
ignore
都返回流引用,您可以检查流引用是否成功



没有必要使用
j
循环,因为每次迭代都会做完全不同的事情。只需在
j=0
案例后面紧跟
j=1
案例,然后摆脱循环,就像我上面的代码一样。(注意
j
在循环中永远不会等于2,所以你的条件无论如何都是错误的。)

读取最后一个分数后,换行符仍位于输入缓冲区上。您需要跳过它。该函数对此很有用

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(文件,播放器[i].name);
对于(int k=0;k<5;++k)
文件>>玩家[i].等级[k];
ignore(std::numeric_limits::max(),'\n');
根据需要检查错误。
>
运算符、
getline
ignore
都返回流引用,您可以检查流引用是否成功



没有必要使用
j
循环,因为每次迭代都会做完全不同的事情。只需在
j=0
案例后面紧跟
j=1
案例,然后摆脱循环,就像我上面的代码一样。(注意
j
在循环中永远不会等于2,所以你的条件无论如何都是错误的。)您的主要问题是直接从流中读取带有>>的整数。这与从流中读取字符串相结合是个坏主意。读取字符串会删除新行,而使用>>读取不会删除新行

最好不要将这两种形式混合使用。请始终使用>>或始终使用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,但不会超过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
 */
#包括
#包括
#包括
#包括
#包括
#包括
/*
*示例数据
贝克汉姆
80 90 100 20 50
罗纳尔迪尼奥-高乔
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;
    }   
};
职业玩家
{
std::字符串名;
病媒目标;
//流运算符,用于读取板材名称及其目标。
friend std::istream&operator>>(std::istream&stream,播放器&唱片)
{   
//读名字
std::getline(流、记录、名称);
//读一行目标。
//将数据复制到目标中。
std::字符串分数;
std::getline(流、分数);
//复制替换一个while循环,该循环将每个数字推送到向量中。
std::stringstream scorestream(分数);
std::copy(std::istream_迭代器(scorestream),
std::istream_迭代器(),
std::back_插入器(record.goals));
回流;
}   
};
用法:

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));
}
intmain()
{
std::ifstream数据文件(“数据”);
向量机;
//将所有玩家复制到vetor中
std::copy(std::istream_迭代器(数据文件),
std::istream_迭代器(),
标准:背向插入器(球员);
}

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

最好不要将这两种形式混合使用。请始终使用>>或始终使用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,但不会超过EOF。