1

I am trying to assign and print vector<vector<int>> dynamically , However i cannot figure out how to do this i am stuck here is my program

#include<iostream>
#include<vector>
#include<string>
using namespace std;
class A {
public:
    vector<int> getVector(int s) {

        vector <int> A(s);
        for (int j = 0; j < s; j++) {
            A.push_back(j);
        }
        return A;
    }
};
int main() {
    A obj;
    int n = 5;
    vector<vector<int>> A;
    
    A.push_back(obj.getVector(n));     // pushes a vector on vector A
    A.push_back(obj.getVector(n - 1));

    vector<vector<int>> ::iterator it;
    it = A.begin();
    for (it; it != A.end(); it++) {
        cout << *it;
    }


    return 0;
}
Phil
  • 435
  • 2
  • 9
  • 28
  • 2
    You need two loops to do this. `std::vector` doesn't have a output operator for `std::ostream` defined. So just nest another for loop into the one you have already. – πάντα ῥεῖ Sep 05 '20 at 13:37
  • can you please post a code snippet i am very new to C++ and STL please – Phil Sep 05 '20 at 13:38
  • I believe it's simple enough and you'll have a better learning effect if you figure that out yourself. The code you have is almost there. So nope. – πάντα ῥεῖ Sep 05 '20 at 13:39
  • Avoid using same name for class and variable. – hafiz031 Sep 05 '20 at 14:12
  • change `vector A(s)` to `vector A` otherwise say for n = 5 it will create a vector of length 5 initialized with `{0, 0, 0, 0, 0}` and again push `{0, 1, 2, 3, 4}` and finally will result in `{0, 0, 0, 0, 0, 0, 1, 2, 3, 4}` – hafiz031 Sep 05 '20 at 14:17
  • You are trying to print a vector directly, as `*it` is basically a vector as `it` is an iterator to a vector. So an easy approach for you: store this vector into a `vector` like `vector v = *it` and then print `v` using a loop. – hafiz031 Sep 05 '20 at 14:20

5 Answers5

3

Consider vector<vector> like a dynamic 2D array.

You will require 2 loops for this.

Also, you need to change a few things:

  1. vector <int> A(s); will initialise a vector of size s with all elements set to 0 and then you are pushing the first n elements into A. So, changed vector <int> A(s); to vector <int> A;.

  2. using namespace std is not considered as a good practice. Find out why.

Have a look at the following implementation:

#include<iostream>
#include<vector>
#include<string>

class A {
    
    public:
        
        std::vector<int> getVector(int s) {

            std::vector <int> A; //Change 1

            for (int j = 0; j < s; j++) {
                A.push_back(j);
            }
            return A;
        }
};

int main() {

    A obj;
    int n = 5;
    std::vector<std::vector<int>> test_vector;
    
    test_vector.push_back(obj.getVector(n));     // pushes a vector on vector A
    test_vector.push_back(obj.getVector(n - 1));

    std::vector<std::vector<int>> :: iterator test_vector_iterator;
    
    test_vector_iterator = test_vector.begin();
    
    for (test_vector_iterator; test_vector_iterator != test_vector.end(); test_vector_iterator++) {
        
        std::vector<int> :: iterator inner_vector_iterator = (*test_vector_iterator).begin();

        for(inner_vector_iterator; inner_vector_iterator != (*test_vector_iterator).end(); inner_vector_iterator++){

            std::cout << *inner_vector_iterator <<" ";
        }

        std::cout << std::endl;
    }


    return 0;
}

Output:

0 1 2 3 4 
0 1 2 3 
Deepak Tatyaji Ahire
  • 4,883
  • 2
  • 13
  • 35
2

Use range loop like

for( const auto &i : A )      // for elements in A, i is vector<int>
{
    for( const auto &j : i )  // for sub elements in A, j is int
    {
        std::cout<<j;
    }
}

or using iterator

for( vector<vector<int>>::iterator i = A.begin() ; i != A.end(); i++ )
{
    for( vector<int>::iterator j = i->begin(); j != i->end(); j++ )
    {
        std::cout<<*j;
    }
}

Thanks.

srilakshmikanthanp
  • 2,231
  • 1
  • 8
  • 25
  • 2
    That likely confuses the OP more than it helps. They already grasped the iterators correctly, and now you introduce a completely new concept to them without any further explanation. – πάντα ῥεῖ Sep 05 '20 at 13:43
  • 1
    agreed iterators are good for now and first method is kind of confusing however he has updated solution written both ways to do this so i think he deserves a +1 :) – Phil Sep 05 '20 at 13:52
1
vector<vector<int>> ::iterator it;
    it = A.begin();
    for (it; it != A.end(); it++) {
        for(vector<int>::iterator it2 = it->begin(); it2 != it->end(); ++it2)
            cout << *it2;
    }
j__
  • 632
  • 4
  • 18
  • 1
    Perfect this is what i was looking for! i get the concept of it now basically we have to initialize multiple iterators based on how many nestings we have thank you :) – Phil Sep 05 '20 at 13:50
0

Nested std::for_each could do the trick

Applies the given function object f to the result of dereferencing every iterator in the range [first, last), in order.

We will make f take std::vector<int> as argument, and print it.

#include <iostream>
#include <vector>
#include <algorithm>


int main()
{
    std::vector<std::vector<int>> A{ {1,2}, {3, 4} };

    std::for_each(A.begin(), A.end(), [](const auto& v) {
        std::for_each(v.begin(), v.end(), [](auto const& it) {
            std::cout << it << std::endl;
        });
    });

    return 0;
}

Output

1
2
3
4
Tony Tannous
  • 14,154
  • 10
  • 50
  • 86
0

Vector of vectors is an analog of 2d array. There is no standard method to serialize vector, a nested loop will do.

#include<iostream>
#include<vector>
#include<string>
#include <algorithm>

using std::for_each;
using std::cout;
using std::vector;
using std::endl;

class A {
public:
    vector<int> getVector(int s) {

        vector <int> A(s);
        for (int j = 0; j < s; j++) {
            A.push_back(j);
        }
        return A;
    }
};
int main() {
    A obj;
    int n = 5;
    vector<vector<int>> A;
    
    A.push_back(obj.getVector(n));     // pushes a vector on vector A
    A.push_back(obj.getVector(n - 1));

    // classic for loop
    for (auto itV = A.begin(), itVE =  A.end(); itV != itVE; itV++)
    {
        for (auto itI = itV->begin(), itIE = itV->end(); itI != itIE; itI++) 
        {
             cout << *itI;
        }
    }
    cout << endl;
    
    // much simpler range-based loop
    for (auto& rowV : A )     // note that this a reference 
                              // - no copy of stored vector is made.
        for (auto el : rowV)
             cout << el;

    cout << endl;

    // a generic lambda to serialize vector
    auto print_vector =  [](const auto& v) {
        std::for_each(v.begin(), v.end(), [](auto const& it) {
            std::cout << it << std::endl;
        });
    };

    std::for_each(A.begin(), A.end(), print_vector );

    return 0;
}

There are several ways to do that: use classic for() which is quite mouthful but allows fie control over some aspects, a range-based for loop is the shortest and most concise variant. THird approach is use of idiomatic function from standard library like for_each, which would require creation of callable, which can be preferred if callable can be re-used of be swapped with something else, allowing some flexibility.

Swift - Friday Pie
  • 12,777
  • 2
  • 19
  • 42
  • Not a suitable use of for_each – j__ Sep 05 '20 at 13:55
  • @lajoh90686 pardon? – Swift - Friday Pie Sep 05 '20 at 13:58
  • for_each wasn’t designed to be immediately called like this. You have range-based for-loops and even normal for loops for this. It’s an over complicated misuse or over engineered solution to the simple for loop – j__ Sep 05 '20 at 14:02
  • @lajoh90686 we have no idea what purpose OP actually have, his example is a minimal recreation. `for_each` and alike meant for idiomatic use in template code or generic code, use within generic lambda is appropriate because it IS a template. What OP actually does and chooses depends on their real application.. With C++20 we also have parallelized analogs of those iterating functions, but it isn't relevant here. Note that some partially-compliant but popular in certain industries compilers do not support range-based for, but support those other features. – Swift - Friday Pie Sep 05 '20 at 14:07
  • `// pushes a vector on vector A` It’s clear OP is just learning. You’d be hard pressed to find a question like this where the answer is std::for_each. In my many years of C++ programming, for_each is one of the most useless features of the algorithm library. Especially when you can just do `for(auto a: std::ranges::view::reverse(as))` (or substitute reverse with whatever your iterator helper is - I picked a C++20 one because it’s standard) – j__ Sep 05 '20 at 14:15
  • @lajoh90686 not clear for me, because I get same question in real-life from programmers with 10-20 years of work experience. Such action was outside of their scope and they were under particular restrictions. And while`for_each` is most useless one,ranged-based for is one of most frequently banned by enterprise coding standard , especially in case of C++ for chips and controllers. It's too easy to introduce huge space or complexity costs by making single character type and it's harder to spot or detect the mistake because underlying actions were in syntax sugar. E.g. in this case, forget & . – Swift - Friday Pie Sep 05 '20 at 14:26