0

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);
}
Einsiedler
  • 33
  • 6

4 Answers4

2

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';
}
Maxim Egorushkin
  • 119,842
  • 14
  • 147
  • 239
1

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.

4386427
  • 33,845
  • 4
  • 32
  • 53
  • Actually, it's a vector of double. – Einsiedler May 22 '18 at 16:02
  • I edited the original post with a code that makes more sense so I don't need to convert. It's still skipping the first line :( – Einsiedler May 22 '18 at 16:19
  • @Einsiedler: Sorry but the new code doesn't make "more sense". **Don't** do `input >> num;` you have **already** read the first line of the file with `getline`. So you loose the first line. Try what I have proposed. – 4386427 May 22 '18 at 16:23
  • @Einsiedler I added some extra explanation of the problem with your approach. Hope it helps. – 4386427 May 22 '18 at 16:26
  • Thank you very much for your remarks. I understand more clearly but unfortunately, stod is not defined (despite including all libraries) so it does not work here. – Einsiedler May 22 '18 at 16:32
  • @Einsiedler `stod` is from C++11 - use `#include `. Are you compiling for pre C++11? If you use gcc compiler add `-std=c++11` or `-std=c++0x` – 4386427 May 22 '18 at 16:33
  • Actually, thanks to your remarks regarding the fact that we shouldn't use both inside the loop, I found the solution (see edit). Thank you very much for your greatly appreciated help :) – Einsiedler May 22 '18 at 16:38
  • @Einsiedler - Glad to help :-) – 4386427 May 22 '18 at 16:41
0

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++]);
Abhijit Pritam Dutta
  • 5,010
  • 2
  • 6
  • 16
0

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.

Mateusz Wojtczak
  • 1,503
  • 9
  • 25
  • Thanks for your remark, I have edited my post. Can you tell me if that actually changes anything to your remark? – Einsiedler May 22 '18 at 16:18