Estcc
Estcc

Reputation: 128

Read from file line by line and parse to vector a lot of ints in c++

I have seen a lot of similar posts regarding very similar cases but my case is a bit different. I'm a newbie to c++, so any help would be appreciated.

I have a large file full of lines full of integers. Each number is separated by blank spaces. I need diferent lines to stay seperate, i don't want to read all the file on one go. I want to read line by line and parse each line in to a vector of integers. The code I've got is this:

int main () {
  string line;
  ifstream myfile;
  myfile.open ("numbers.txt");
  vector<int> vec1;
  int const2=0;
  int a;
  while ( getline (myfile,line) ){ // I understand that this reads line 
                                   // by line and stores the string to "line"
    while (line >> a){  // this part is the one i can't get right, i 
                        // want to push_back every int from
                        // the string to vec1 but doesn't work
      vec1.push_back(a); 
      // More stuff
    }
    // more stuff
  }
  myfile.close();   
  return 0;
}

Upvotes: 1

Views: 298

Answers (2)

Jonathan H
Jonathan H

Reputation: 7933

Here is the C++11 way (use -std=c++0x with g++ or clang++), you can google each function that you don't know. Using back_inserter and istream_iterator is much cleaner than any while/for loop you would come up with on your own. Using deque in this context is also more efficient. Obviously you can also take the file name from the main input.

#include <algorithm>
#include <iterator>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <deque>

int main()
{
    const std::string filename = "/path/to/file.txt";

    std::string    line_buf;
    std::ifstream  file( filename );

    std::deque< std::deque<int> > parsed_data;
    if (file) while ( std::getline(file,line_buf) )
    {
        std::deque<int>    parsed_line;
        std::stringstream  ss( line_buf );

        std::copy( std::istream_iterator<int>(ss), std::istream_iterator<int>(), std::back_inserter(parsed_line) );

        parsed_data.emplace_back();
        parsed_data.back().swap( parsed_line );
    }
}

To check the result in your console, you can use this function

#include <cstdio>
void show_result( const std::deque< std::deque<int> >& data )
{
    size_t line_count = 0;
    for ( auto& line: data )
    {
        printf( "Line %02ld: ", ++line_count );
        for ( auto& num: line )
            printf( "%d ", num );
            printf( "\n" );
    }
}

Upvotes: 0

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

You need a std::istringstream:

std::istringstream iss(line);
while(iss >> a) {
     vec1.push_back(a);
     // ....
}

But in fact if you only have numbers in that file, it would be enough to leave out the while ( getline (myfile,line) ){ loop completely and just write

while(myfile >> a) {
     vec1.push_back(a);
     // ....
}

Upvotes: 3

Related Questions