Reading an std::ifstream to a vector of lines
Asked Answered
M

3

5

How would I go about reading in a file where each line is a single number, then outputing that number into a vector of lines?

eg: file.txt contains:

314
159
265
123
456

I have tried this implementation:

vector<int> ifstream_lines(ifstream& fs) {
    vector<int> out;
    int temp;
    getline(fs,temp);
    while (!fs.eof()) {
        out.push_back(temp);
        getline(fs,temp);
    }
    fs.seekg(0,ios::beg);
    fs.clear();
    return out;
}

but when I attempt to compile, I get errors such as:

error C2784: 'std::basic_istream<_Elem,_Traits> &std::getline
(std::basic_istream<_Elem,_Traits> &,std::basic_string<_Elem,_Traits,_Alloc> &)' : 
could not deduce template argument for 'std::basic_istream<_Elem,_Traits> &' from 'std::ifstream'

so, obviously, something is wrong. Is there a more elegant solution than what I am trying? (Assuming 3rd party libraries like Boost are unavailable)

Thanks!

Muttonhead answered 4/11, 2009 at 17:46 Comment(0)
P
23

I suspect you want something like this:

#include <vector>
#include <fstream>
#include <iterator>

std::vector<int> out;

std::ifstream fs("file.txt");

std::copy(
    std::istream_iterator<int>(fs), 
    std::istream_iterator<int>(), 
    std::back_inserter(out));
Parsimony answered 4/11, 2009 at 17:50 Comment(2)
You should note that it will not detect errors in the input file (ie two numbers on the same line).Peba
A stream iterator will read multiple values from a single line, separated by whitespace, but it will stop if something other than a digit or whitespace is encountered, leaving the stream with fs.eof() == false and fs.fail() == true.Parsimony
P
6

The standard iterators as describe by 'Tim Sylvester' is the best answer.

But if you want a manual loop then,
Just to provide a counter example too: 'jamuraa'

vector<int> ifstream_lines(ifstream& fs)
{
    vector<int> out;
    int temp;

    while(fs >> temp)
    {
        // Loop only entered if the fs >> temp succeeded.
        // That means when you hit eof the loop is not entered.
        //
        // Why this works:
        // The result of the >> is an 'ifstream'. When an 'ifstream'
        // is used in a boolean context it is converted into a type
        // that is usable in a bool context by calling good() and returning
        // somthing that is equivalent to true if it works or somthing that 
        // is equivalent to false if it fails.
        //
        out.push_back(temp);
    }
    return out;
}
Peba answered 4/11, 2009 at 18:17 Comment(0)
P
1

std::getline(stream, var) reads into a std::string for var. I suggest using the stream operators to read into the int instead, and check for errors if needed:

vector<int> ifstream_lines(ifstream& fs) {
  vector<int> out;
  int temp;
  while (!(fs >> temp).fail()) {
    out.push_back(temp);
  }
  fs.seekg(0,ios::beg);
  fs.clear();
  return out;
}
Pimento answered 4/11, 2009 at 17:53 Comment(1)
That's horrible. Never test for eof() in the condition. It is ALWAYS better to test the action in the condition.Peba

© 2022 - 2024 — McMap. All rights reserved.