CSV parser using STL

I'm wondering what would be the right way to parse CSV file with "numbers" using operator>> overload?

test.csv
1
2
Test,20,50.12
Other,31,46.12


code.cpp
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
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <vector>

struct test {
    std::string name;
    int rate;
    double avg;
};

std::ostream &operator<<(std::ostream &os, const test &t) {
    return os << t.name << ", " << t.rate << ", " << t.avg;
}

std::istream &operator>>(std::istream &is, test &t) {
    // here!!!
    return is >> t.name >> t.rate >> t.avg;
}

using cont = std::vector<test>;
using i_iter = std::istream_iterator<test>;
using o_iter = std::ostream_iterator<test>;

int main() {
    std::ifstream f("test.csv");
    i_iter beg(f), ends;
    o_iter iter(std::cout, "\n");
    cont c;
    std::copy(beg, ends, std::back_inserter(c));
    std::copy(c.begin(), c.end(), iter);
}
Last edited on
There isn't for all valid CSV. If you restrict it some, then you've got the right idea, just remember that a record is a single line, and you'll need to take care to read the individual fields correctly. Your test struct gives us the opportunity to look at a variety of input considerations:

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <limits>
#include <sstream>
#include <string>
#include <vector>

struct test {
    std::string name;
    int rate;
    double avg;
};

std::ostream &operator<<(std::ostream &os, const test &t) {
    return os << t.name << ", " << t.rate << ", " << t.avg;
}

std::istream &operator>>(std::istream &is, test &t) {

    // Read any string terminating with a comma
    getline( is >> std::ws, t.name, ',' );
    
    // Read formatted input; must terminate with a comma
    is >> t.rate;
    if ((is >> std::ws).get() != ',')
    {
      is.setstate( std::ios::failbit );
      return is;
    }
    
    // Read formatted input; ignore everything else to end of line
    is >> t.avg;
    is.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
    
    return is;
}

std::istream &operator>>(std::istream &is, std::vector<test> &data) {
    data.clear();
    test rec;
    while (is >> rec)
        data.emplace_back(rec);
    return is;
}

int main() {

    std::istringstream f(
      "Rain,      3   ,  2.7\n"
    "  Sunshine,  97  , 84.3  \n"
      "Happy Days,100 ,100.0\n"
    );
    
    std::vector<test> data;
    
    // Read
    f >> data;

    // Write
    for (auto rec : data)
      std::cout << rec << "\n";
}
Rain, 3, 2.7
Sunshine, 97, 84.3
Happy Days, 100, 100

Hope this helps.

Thank you Mr. @Duthomhas,
- this is just one of the tasks in process of better understanding of c++ and STL, not a real life CSV
Topic archived. No new replies allowed.