David David - 1 month ago 15
C++ Question

C++ - Filling multidimensional vector with data from file with delimiters

I need to fill my multidimensional vector with data from file with delimiter, so I do somethink like this:

ifstream file;
vector < vector<string> > stockVector;
vector<string> rowVector;

file.open( fileLocation(), std::ios::in | std::ios::out );

if ( !file.good() )
return false;

string data;
while ( getline( file, data, ';' ) ) {
for( int i = 0; i < 20; i++ ) {
rowVector.push_back(data);
}

stockVector.push_back( rowVector );
}


But I'm getting
1
everywhere. What is bad?

Here is my file:

1;Guerra;36;0.95;
2;Rivas;14;3.20;
3;Petty;30;7.81;
4;Gallagher;65;8.00;
5;Nguyen;76;1.99;
6;Wooten;57;0.97;
7;Guerra;53;7.25;
8;Norman;6;5.82;
9;Dyer;72;8.69;
10;Martin;67;4.73;
11;Delgado;73;4.60;
12;Velasquez;87;1.76;
13;Crawford;95;0.66;
14;Houston;9;7.78;
15;Shaffer;85;4.40;
16;Hoover;99;0.81;
17;Webb;97;8.02;
18;Gonzales;22;1.78;
19;Gross;17;4.00;
20;Bridges;93;8.08;

Answer

There are a few mistakes here, including a subtle one.

1) You need two getline's here: one to read a (surprise) line from a file until \n, and another one to extract tokens out of the line read.

2) The second getline needs to have a delimiter of ;.

3) Your two loops contradict each other. The while loop reads (incorrectly!) token by token from the file, and the other loop adds the very same token 20 times.

4) (The subtle error) You don't reset rowVector for every line in a file.

5) Hardcoding 20 is a bad idea, better let getline find the end of the file and string for you.

#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
#include <iterator>

int main(int argc, char **argv) {
    std::ifstream file;
    std::vector < std::vector<std::string> > stockVector;

    file.open( argv[1], std::ios::in | std::ios::out );

    if ( !file.good() )
        return false;

    for ( std::string data; getline(file, data); ) {
        std::istringstream linestr(data);
        std::vector<std::string> rowVector;
        for( std::string token; std::getline(linestr, token, ';'); ) {
            rowVector.push_back(token);
        }
        stockVector.push_back( rowVector );
    }

    for (const auto& v: stockVector ) {
        std::copy(v.cbegin(), v.cend(), std::ostream_iterator<std::string>(std::cout, " "));
        std::cout << "\n";
    }
}

See for reference:

http://en.cppreference.com/w/cpp/string/basic_string/getline http://en.cppreference.com/w/cpp/io/basic_stringstream http://en.cppreference.com/w/cpp/iterator/ostream_iterator