简体   繁体   English

读取文件C ++时使用getline和>>

[英]Use getline and >> when read file C++

Because data from file look like this: line 1 is name (first last), next line is score (score1 score 2 ....score5) and so on... So I think that I need getline for name and >> for score 因为来自文件的数据如下所示:第1行是名称(第一名),下一行是score(分数1分数2 .... score5),依此类推...因此,我认为我需要getline作为名称和>>得分

Example of data file 数据文件示例

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

First of all, I have structure 首先,我有结构

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

When read data from file 从文件读取数据时

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
    }

Problem is after read all scores (of first player), it seems like doesn't go to next line to continue read next name, kind of mess up there. 问题是看完(第一名球员)的所有分数后,似乎不去下一行继续读取下一个名字,那儿有点混乱。 So any suggestions to correct my code or new idea to do this? 因此,有什么建议可以纠正我的代码或执行此操作的新想法?

After reading the last score, the line break is still sitting on the input buffer. 读取最后一个分数后,换行符仍位于输入缓冲区上。 You need to skip that. 您需要跳过。 The ignore function is useful for that. 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');

Check for errors as appropriate. 检查适当的错误。 The >> operator, getline , and ignore all return the stream reference, which you can check for success or failure. >>运算符getlineignore所有返回流引用,您可以检查流引用是否成功。


There's no need for that j loop since each iteration does a completely different thing. 不需要j循环,因为每次迭代都做完全不同的事情。 Just write the j=0 case immediately followed by the j=1 case, and then get rid of the loop, like my code above. 只需立即编写j=0情况,然后紧跟j=1情况,然后摆脱循环,就像上面的代码一样。 (And note that j will never equal 2 inside the loop, so your condition was wrong anyway.) (请注意,循环内j永远不会等于2,因此无论如何您的条件都是错误的。)

Your main problem is that you are reading the integers with >> directly from the stream. 您的主要问题是直接从流中读取带有>>的整数。 This combined with reading a string from the stream is a bad idea. 这与从流中读取字符串相结合是一个坏主意。 Reading the strings removes the new line will reading with >> will not remove the new lines. 读取字符串将删除新行,将显示>>,不会删除新行。

It is best not to mix the two forms. 最好不要混合使用两种形式。 Either always use >> or always use getline(). 始终使用>>或始终使用getline()。 Note: I am not saying best I am saying easiest. 注意:我说的不是最好的,我说的是最简单的。 You can use them together when you understand the tradeoffs and how to compensate for the differences in their usage. 当您了解权衡因素以及如何补偿其用法差异时,可以将它们一起使用。

Thus it is easier to read the line of numbers into a string then parse the string. 因此,将数字行读入字符串然后解析该字符串比较容易。

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.
}

It is nearly always wrong to use: 使用几乎总是错误的:

while(!file.eof())

This is because the EOF flag is not set until you read past the eof. 这是因为直到您读取了eof之后才设置EOF标志。 Note the last read will read upto but not past the eof. 请注意,最后一次读取将读取直到但不会超过eof。 Thus you will enter the loop even though there is not data available. 因此,即使没有可用数据,您也将进入循环。

The standard pattern is: 标准模式是:

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

With this in mind I would define a class that represents all the information you want (ie two lines). 考虑到这一点,我将定义一个代表您想要的所有信息的类(即两行)。 A simple version would be 一个简单的版本是

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
}

This is fine if all you want to do is read lines. 如果您只想读取行,这很好。
But the data looks like it has a structure. 但是数据看起来好像具有结构。 So I would construct a class that represents the data and then read the data directly into that structure. 因此,我将构造一个表示数据的类,然后将数据直接读取到该结构中。 So this is more what I would do. 所以这是我会做的更多的事情。 I would also replace the while() loops with algorithms. 我还将用算法替换while()循环。

Headers

#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
 */

The Class: 班级:

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;
    }   
};

Usage: 用法:

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));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM