0

I need to read some lines from an input file into vector (of integers) and c++ is new to me so I'm having trouble understanding huge codes with lots of functions. Can you tell me how to do this the most basic way?

In my file I have something like this:

5 6 11 3 4
2 3 1
1 
9

I wrote the input file with another program so I can present in it the number of vectors (4 in this case) and their size (5, 3, 1, 1) if I makes the reading easier.

I means I can present the information in any form... just need to know which one is better and how to use it.

Jason Aller
  • 3,541
  • 28
  • 38
  • 38
Laura Pinguicha
  • 189
  • 2
  • 6
  • 2
    [Option 2 in Kerrek SB's answer here](https://stackoverflow.com/a/7868998/4581301) gets you most of the way. Replace the `if (!(iss >> a >> b))` with a while loop somehting like `while (iss >> a) { vec.push_back(a); }` – user4581301 May 03 '19 at 22:16
  • Do you know how to read one number into an `int` variable? If not, I suggest you start there. – Code-Apprentice May 03 '19 at 22:24

2 Answers2

3

It's not really 'a basic way', but it's short and it works:

#include <fstream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>

int main()
{
    std::vector<std::vector<int>> vec;

    std::ifstream file_in("my_file.txt");
    if (!file_in) {/*error*/}

    std::string line;
    while (std::getline(file_in, line))
    {
        std::istringstream ss(line);
        vec.emplace_back(std::istream_iterator<int>(ss), std::istream_iterator<int>());
    }
}

Slightly simplified version that does the same thing:

#include <fstream>
#include <sstream>
#include <string>
#include <vector>

int main()
{
    std::vector<std::vector<int>> vec;

    std::ifstream file_in("my_file.txt");
    if (!file_in) {/*error*/}

    std::string line;
    while (std::getline(file_in, line)) // Read next line to `line`, stop if no more lines.
    {
        // Construct so called 'string stream' from `line`, see while loop below for usage.
        std::istringstream ss(line);

        vec.push_back({}); // Add one more empty vector (of vectors) to `vec`.

        int x;
        while (ss >> x) // Read next int from `ss` to `x`, stop if no more ints.
            vec.back().push_back(x); // Add it to the last sub-vector of `vec`.
    }
}

I wouldn't call stringstreams a basic feature, but doing what you want without them will be a lot more messy.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • Is there any advantage to using `vec.push_back({});` rather than filling a `std::vect tmp;` with `while (ss >> x) tmp.push_back(x); vec.push_back(tmp);`? – David C. Rankin May 04 '19 at 01:11
  • @DavidC.Rankin It prevents copying (or moving if you do `vec.push_back(std::move(tmp));` the vector. – HolyBlackCat May 04 '19 at 08:05
  • Gotcha, so adding an empty with `vec.push_back({});` and then `vec.back().push_back(x);` you are writing to the final location saving the copy (or move I guess) of `tmp` into a `vector` in `vec`. – David C. Rankin May 04 '19 at 08:38
1

Here is a simple example where std::istringstream is used to extract the values of each line.

(Note that it is not necessary to call eof() before reading.)

std::ifstream file("file.txt");
std::vector<std::vector<int>> vectors;
std::string line;
while (std::getline(file, line))
{
  std::istringstream ss(line);
  std::vector<int> new_vec;
  int v;
  while (ss >> v)                 // populate the new vector
  {
    new_vec.push_back(v);
  }
  vectors.push_back(new_vec);     // append it to the list of vectors
}
file.close();
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
sowlosc
  • 470
  • 3
  • 8