HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Reading from a CSV file in C++

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
fromreadingfilecsv

Problem

I wrote this code to read from a CSV text file (containing data such as 12,3,568,48,3,8 with no more than 3 digits to each number). It stores the numbers as char arrays in the vector values. However, this does seem like a clumsy way of doing this with resizing the vector and copying the chars. Is there a neater/more succinct way of doing this?

#include 
#include 
#include 
#include 

int main() {
    using namespace std;
    ifstream in;
    in.open("Data.txt");
    assert(in.is_open());
    vector values;
    const int MAXSIZE = 4;
    char thisVal[MAXSIZE];
    while(in.getline(thisVal,MAXSIZE,',')) {
        values.resize(values.size() + 1);
        values.back() = new char[MAXSIZE];
        strcpy(values.back(), thisVal);
    }
    in.close();
    for (char* cp: values) cout<<*cp<<endl;
    return 0;
}

Solution

Storing char* in a vector leads to leaks. instead use std::string, which will manage its own buffer and delete it as needed.

vector values;


inserting to the back of a vector can be done with push_back or you can construct in place with emplace_back in C++11:

while(in.getline(thisVal,MAXSIZE,',')) {
    string str(thisVal);
    values.push_back(std::move(str));
    //std::move signals that I won't be using str anymore and that the underlying buffer can just be passed through to the new element. 
    // After this str will not be valid. You can still assign to it normally but until you do any result of calling a method on it will be implementation defined.
}


or

while(in.getline(thisVal,MAXSIZE,',')) {
    values.emplace_back(thisVal);
}


Failing to open a file is common enough to use an explicit if and print an error message instead of asserting (which won't do anything when compiled as a release version):

if(!in.is_open()){
    cerr << "failed to open file.";
    return 1; 
}


I return 1 here to signal to the OS that the program didn't finish successfully and a script using it can then react to it.

Code Snippets

vector<string> values;
while(in.getline(thisVal,MAXSIZE,',')) {
    string str(thisVal);
    values.push_back(std::move(str));
    //std::move signals that I won't be using str anymore and that the underlying buffer can just be passed through to the new element. 
    // After this str will not be valid. You can still assign to it normally but until you do any result of calling a method on it will be implementation defined.
}
while(in.getline(thisVal,MAXSIZE,',')) {
    values.emplace_back(thisVal);
}
if(!in.is_open()){
    cerr << "failed to open file.";
    return 1; 
}

Context

StackExchange Code Review Q#81928, answer score: 6

Revisions (0)

No revisions yet.