1
2 
1 3 
2 4 8 13
3 5 6 13
4
4
8
3 7 9 10 13 
8 10 11 
8 9 11 12 
9 10 
10 15 
3 4 8 14 
13 
12 16 
15 17 18 
16 
18 16 

I want to read this these values from file into two dimensional STL vector. Note that the size of inner vector is not uniform and not known in adance so I need to detect '\n'. So far I have been unnsuccessful. My code is as follows. Please help. What is wrong?

int main()
{
    ifstream Lin("A.txt");
    double d;
    vector<vector<double> > A;
    vector<double> dummy;

    if (Lin.is_open()){
    while (Lin >> d) {
            if (Lin.peek() == '\n'){
                A.push_back(dummy);
                dummy.clear();
            }else{
                dummy.push_back(d);
            } 
        }
        Lin.close();
    }

...

return 0;

}

When I iterate over the vector using the following code , it reveals what is stored:

for(int i = 0; i< A.size(); i++){
       for(int j = 0; j< A[i].size() ; j++){
           cout << A[i][j] << " ";
       }
       cout << endl;
   }


1
2 4 8
3 5 6



3 7 9 10
8 10
8 9 11
9
10
3 4 8

12
15 17

18

The intended output is same as the way it is stored in the file

Utkrist Adhikari
  • 1,002
  • 2
  • 12
  • 30

4 Answers4

4

Make sure that there is no empty space after the last integer in each line in the data file. In the code currently you are not adding the last integer to the dummy vector. Modify it like this:

while (Lin >> d) 
{
       dummy.push_back(d);   // Add the number first
       if (Lin.peek() == '\n')  // Then check if it is end of line
       {
             A.push_back(dummy);
             dummy.clear();
       }
}
PermanentGuest
  • 5,029
  • 2
  • 24
  • 36
2

Consider using getline.

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

int main() {
    std::string line;
    std::vector<std::vector<double> > v;
    while(std::getline(cin, line)) {
        std::stringstream ss(line);
        double value;
        std::vector<double> numbers;
        while(ss >> value) {
            numbers.push_back(value);
            std::cout << value << std::endl;
        }
        v.push_back(numbers);
    }
    return 0;
}
andre
  • 6,611
  • 4
  • 36
  • 70
2

Less is more. This replaces your entire loop. Note: You don't need to check is_open or call close for this to work safely.

for(std::string s; std::getline(Lin, s);)
{
    A.emplace_back(std::istream_iterator<double>(std::istringstream(s)), 
                   std::istream_iterator<double>());
}
David
  • 25,830
  • 16
  • 80
  • 130
  • needs extra set of parentheses http://stackoverflow.com/questions/195323/what-is-the-most-elegant-way-to-read-a-text-file-with-c – kirill_igum Aug 07 '13 at 04:05
  • for me this doesn't work. I have to convert `string` to `stringstream` in a separate line. gcc 4.8.0 – kirill_igum Aug 07 '13 at 04:06
0

There could be other whitespace characters after the number at the end of line, other than \n. Like spaces:

1234  445  445    \n
              ^^^^

So your approach is not safe. Better would be to read entire line (getline) to some string, then construct istringstream on this string containing line, then just parse this istringstream to your vector for one line.

Like this:

   for (string line; getline(filein, line); ) {
        vector<double> dd;
        istringstream is(line);
        for (double d; is >> d; )
            dd.push_back(d);
        if (not dd.empty())
           A.push_back(dd);
    }
PiotrNycz
  • 20,687
  • 7
  • 55
  • 102