Reputation: 43
I'm having a bit of a problem with extracting data from a simple .txt file with the getline command.
The txt file is very simple: a column of 400 numbers. I use a vector to store them with the following code:
int i = 0;
string line;
vector <double> vec;
while (getline(input, line))
{
vec.push_back(i);
N++;
input >> vec[i];
i++;
}
It correctly creates a vector of 400 elements but first line of txt file is ignored (I end up with vec[0] = 2nd line of txt file instead of 1st) and 399th element is 399 instead of the 400th line of txt file.
I tried several other ways to extract this data but it was unsuccessful.
Thank you for your help!
EDIT:
I have edited the code according to some of the remarks:
vector <double> vec;
string line;
double num;
while (getline(input, line))
{
input >> num;
vec.push_back(num);
}
Unfortunately, it still skips the first line of my text file.
EDIT 2 --> SOLUTION:
Thanks to all of your remarks, I realized that I was doing something wrong when using both getline and input >> num;
Here is how the problem was solved:
double num;
vector <double> vec;
while (input >> num)
{
vec.push_back(num);
}
Upvotes: 0
Views: 1921
Reputation: 136515
You can read the entire file into a vector just by passing std::istream_iterator
to std::vector
constructor, without loops:
std::vector<int> v{
std::istream_iterator<int>{input},
std::istream_iterator<int>{}
};
E.g.:
#include <iostream>
#include <iterator>
#include <vector>
#include <exception>
template<class T>
std::vector<T> parse_words_into_vector(std::istream& s) {
std::vector<T> result{
std::istream_iterator<T>{s},
std::istream_iterator<T>{}
};
if(!s.eof())
throw std::runtime_error("Failed to parse the entire file.");
return result;
}
int main() {
auto v = parse_words_into_vector<int>(std::cin);
std::cout << v.size() << '\n';
}
Upvotes: 2
Reputation: 44368
You loose the first line due to reading from the file once more - here:
while (getline(input, line))
// ^^^^^^^ Here you read the first line
{
input >> num;
// ^^^^^^^^ Here you will read the second line
You told you want a vector of doubles - like:
std::vector<double> vec;
So you should use std::stod
to convert the line read by getline
into a double. Like:
while (std::getline(input, line))
{
// Convert the text line (i.e. string) to a floating point number (i.e. double)
double tmp;
try
{
tmp = stod(line);
}
catch(std::invalid_argument)
{
// Illegal input
break;
}
catch(std::out_of_range)
{
// Illegal input
break;
}
vec.push_back(tmp);
}
Don't do input >> num;
inside the loop.
If you really want to use input >> num;
then you shall not use getline
. That is - you can use either but not both.
Upvotes: 1
Reputation: 1631
You are starting by putting 0 in vector in first iteration:
vec.push_back(i);
then after you read first line you read next string, but stream get pointer from file is already in different place, so you override this 0 and skip first value from stream. What is worse that is oddly converted to double:
input >> vec[i];
This way you will get wrong. Try this:
while (std::getline(file, line)) {
//In c++11
vec.emplace_back(std::stod(line));
//In c++ 98, #include <stdlib.h> needed
//vec.push_back(atof(line.c_str()));
}
This assumes you will always have proper file.
Upvotes: 0
Reputation: 5601
Change your while loop like below:-
while (getline(input, line))
{
vec.push_back(line);
//N++;
//input >> vec[i];
//i++;
}
Also try with below option
do{
vec.push_back(i);
//N++;
//i++;
}while (input >> vec[i++]);
Upvotes: 0