用c ++读取CSV文件中的两列

Reading two columns in CSV file in c++

我有一个两列形式的csv文件:name,age

为了读取和存储信息,我这样做了

1
2
3
4
5
6
7
struct person
{
    string name;
    int age;
}
person record[10];
ifstream read("....file.csv");

但是,当我这样做的时候

1
2
3
read >> record[0].name;
read.get();
read >> record[0].age;

阅读>>名字给了我整行而不仅仅是名字。我怎么可能避免这个问题,这样我就可以把整数读到年龄中去?

谢谢您!


您可以先用std:getline读取整行,然后通过std::istringstream解析它(必须是#include ),比如

1
2
3
4
5
6
7
std::string line;
while (std::getline(read, line)) // read whole line into line
{
    std::istringstream iss(line); // string stream
    std::getline(iss, record[0].name, ','); // read first part up to comma, ignore the comma
    iss >> record[0].age; // read the second part
}

下面是一个完全正常工作的通用示例,它对IDeone上的csv文件live进行标记化。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

int main()
{
    // in your case you'll have a file
    // std::ifstream ifile("input.txt");
    std::stringstream ifile("User1, 21, 70
User2, 25,68"
);

    std::string line; // we read the full line here
    while (std::getline(ifile, line)) // read the current line
    {
        std::istringstream iss{line}; // construct a string stream from line

        // read the tokens from current line separated by comma
        std::vector<std::string> tokens; // here we store the tokens
        std::string token; // current token
        while (std::getline(iss, token, ','))
        {
            tokens.push_back(token); // add the token to the vector
        }

        // we can now process the tokens
        // first display them
        std::cout <<"Tokenized line:";
        for (const auto& elem : tokens)
            std::cout <<"[" << elem <<"]";
        std::cout << std::endl;

        // map the tokens into our variables, this applies to your scenario
        std::string name = tokens[0]; // first is a string, no need for further processing
        int age = std::stoi(tokens[1]); // second is an int, convert it
        int height = std::stoi(tokens[2]); // same for third
        std::cout <<"Processed tokens:" << std::endl;
        std::cout <<"\t Name:" << name << std::endl;
        std::cout <<"\t Age:" << age << std::endl;
        std::cout <<"\t Height:" << height << std::endl;
    }
}


你也许可以使用Stringstream,但如果我诚实的话,我不会相信这一点。如果我是你,我会写一个小函数,它将整行读入一个字符串,然后它应该在字符串中搜索分隔符。前面的一切都是第一列,后面的一切都是第二列。通过C++提供的字符串操作,您可以在变量中移动这些部分(如果需要的话,可以将它们转换成正确的类型)。我为CSV解析编写了一个小型C++库,也许看看它对你有帮助。你可以在Github上找到它。

编辑:在这里你可以找到解析函数


read>>name gave me the whole line instead of just the name. How could I possibly avoid this problem so that I can read the integer into age?

read >> name将把所有内容都读到name中,直到遇到空白。

如果您有一个逗号分隔的没有空格的行,那么将整行读入name是有意义的。

您可以使用std::getline将整行读取到一个字符串。然后使用各种方法对std::string进行标记化。

示例SO贴出标记化std::string的帖子:

如何在C++中标记字符串?C++标记STD字符串使用令牌分裂C++ STD::字符串,例如";";