A vector of vector, but only know the inner dimension

Hi I have a simple question to ask.
If I want to read a table, which has 16 columns, but unknown rows (which is big).
How could I initial the vector of string vector.
Outer vector for the rows, and inner vector for 16 columns.

1
2
std::vector<std::vector<std::string>> vecVec(here unknow, std::vector<std::string>(16));
You don't need to set the size of a vector when you create and initialise it. One of the big strengths of vectors is that they can resize themselves as you add more elements. If you use the push_back() method, for example, the vector will resize itself.

Alternatively, you can resize a vector explicitly, once you know how big it needs to be, by calling the resize() method.
> How could I initial the vector of string vector.
> Outer vector for the rows, and inner vector for 16 columns.

To initialise the vector of vectors,
write a function which populates a vector with strings read from the file and returns it,
and initialise your vector with the value returned by the function.

For example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <vector>
#include <string>
#include <fstream>

// populate a 2d vector with each column having col_size items and return it
std::vector< std::vector<std::string> > make_vector_2d( std::istream& stm, std::size_t col_size )
{
    std::vector< std::vector<std::string> > vec2d(1) ; // create a vector with one empty row

    std::string item ;
    while( stm >> item ) // for each item read from the stream
    {
        vec2d.back().push_back(item) ; // add the item to the end of the current row

        // if this row now has col_size items, start a new row (add a new empty row)
        if( vec2d.back().size() == col_size ) vec2d.emplace_back() ;
    }

    if( vec2d.back().empty() ) vec2d.pop_back() ; // if the last row is empty, discard it
    else vec2d.back().resize(col_size) ; // otherwise add empty items to make it have col_size items

    return vec2d ;
}

int main()
{
    const std::string input_file_name = "input_file.txt" ;

    std::ifstream file(input_file_name) ; // open the file for input
    const std::size_t col_size = 16 ;

    // initialise a 2d vector from the value returned by the function
    const auto my_initialised_vec2d = make_vector_2d( file, col_size ) ;
}
Last edited on
closed account (E0p9LyTq)
How to initialize a 2D vector with known dimensions:

1
2
3
4
5
6
7
8
9
10
#include <vector>
#include <string>

int main()
{
   const int row_size = 3;
   const int col_size = 4;

   std::vector<std::vector<std::string>> aVector(row_size, std::vector<std::string>(col_size));
}

If you want to fill each element on vector creation with a value other than a blank string:

std::vector<std::vector<std::string>> aVector(row_size, std::vector<std::string>(col_size, "A"));
Last edited on
If you are certain about the 16-per-row, then a row does not need to be a vector:
std::vector<std::array<std::string,16>> table;
you could also iterate the file and get the line count and then preallocate what you need, go back and read the data. This is not normally worth the trouble, but if push back is costing you a lot of time growing the vector as it reads, it could be a useful thing to do. Depends on what you call 'big'. If its using up more than 25% of your hardware-ram (as opposed to virtual memory) then vector may start to struggle to find contiguous memory locations depending on what else is running. (25% because it needs twice that, one for the current copy, one for the new bigger location, and that leaves 50% for the os and whatever else is running + memory fragmentation concerns).
Topic archived. No new replies allowed.