Reading two columns in a CSV file in C ++

I have a CSV file as two columns: name, age

To read and save the information, I did this

struct person
{
    string name;
    int age;
}
person record[10];
ifstream read("....file.csv");

      

However, when I did

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

      

read -> name gave me a whole string instead of a name. How could I avoid this problem so that I can read the integer age?

Thank!

+3


source to share


3 answers


You can read the whole line from first std:getline

, then parse it with std::istringstream

(required #include <sstream>

) like

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
}

      



Below is a complete working example that symbolizes the CSV file Live on Ideone

#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\nUser2, 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;
    }
}

      

+2


source


read>>name

gave me a whole string instead of a name. How could I avoid this problem so that I can read the integer age?

read >> name

will read everything in name

until empty space is encountered.

If you have a comma-delimited string with no spaces, it makes sense that the entire string is read into name

.



You can use std::getline

to read the entire line down to one line. Then use various methods of tokenizing a std::string

.

An example of SO posts that address tokenization std::string

:

How to tokenize a string in C ++? C ++ tokenize std string
Splitting a C ++ std :: string using tokens, e.g. ""

0


source


Perhaps you could use stringstream for this, but I wouldn't trust it to be honest. If I were you, I would write a little function that reads the entire string into a string, and after that it should look for the delimiter character in the string. This is preceded by the first column and everything behind the second. With the string operations provided by C ++, you can move these parts around in your variables (you can convert them to the correct type if you need to). I wrote a small C ++ library for CSV parsing, maybe this will help you. You can find it on GitHub .

EDIT: In this Gist you can find the function

0


source







All Articles