Search code examples
c++vectordata-structures2d-vector

How to push characters of a string into a 2d vector


I have a string s = "if man was meant to stay on the ground god would have given us roots".

I removed spaces and had "ifmanwasmeanttostayonthegroundgodwouldhavegivenusroots".

Now I want to push the characters of the string into a 2d vector of 7 rows and 8 columns. The output should look like:

ifmanwas 
meanttos 
tayonthe 
groundgo 
dwouldha 
vegivenu 
sroots

I tried the following method but wasn't working.

void encryption(string s)
{
    const int rows = 7;
    const int colums = 8;

    vector<vector<char>> v;
    for (int i = 0; i < rows; i++)
    {
        vector<char>temp;
        for (int j = 0; i < colums; j++)
        {
            temp.push_back(s[0]);
            s.erase(0);
        }
        v.push_back(temp);
    }
    for (int i = 0; i < v.size(); i++)
    {
        for (int j = 0; j < v[i].size(); j++)
            cout << v[i][j];
    }
}

Solution

  • There are several issues with your code:

    1) Wrong index variable used in the loop here: for (int j = 0; i < colums; j++)

    2) The std::vector::erase function takes an iterator as the argument, not a position.

    3) Even if you fix the loop mentioned in 1), you do not check to see if you're at the end of the string.

    4) Your final output does not output carriage returns, making the output look "wrong".

    Given the string you used, making the appropriate changes, the code could look like this:

    #include <string>
    #include <vector>
    #include <iostream>
    
    using namespace std;
    
    void encryption(string s)
    {
        const int rows = 7;
        const int colums = 8;
    
        vector<vector<char>> v;
        for (int i = 0; i < rows; i++)
        {
            vector<char>temp;
            for (int j = 0; j < colums && !s.empty(); j++)  // <-- Note we stop the loop if the string is empty.
            {
                temp.push_back(s[0]);
                s.erase(s.begin());  // <-- This erases the first character
            }
            v.push_back(temp);
        }
        for (size_t i = 0; i < v.size(); i++)
        {
            for (size_t j = 0; j < v[i].size(); j++)
                cout << v[i][j];
            cout << "\n";    // <-- You are missing this in your output
        }
    }
    
    int main()
    {
        encryption("ifmanwasmeanttostayonthegroundgodwouldhavegivenusroots");
    }
    

    Output:

    ifmanwas
    meanttos
    tayonthe
    groundgo
    dwouldha
    vegivenu
    sroots
    

    Given this, this is a highly inefficient in that you are erasing the first character of the string. There is no need for erasing a character for this.

    Here is an alternate solution using std::vector<std::string>, and a while loop that keeps track of starting and ending iterators within the string:

    #include <string>
    #include <vector>
    #include <algorithm>
    #include <iostream>
    
    void encryption(std::string s)
    {
        const size_t columns = 8;
    
        std::vector<std::string> v;
    
        // start at beginning of string
        auto startIter = s.begin();
    
        // point to either 8 characters after the start, or the end of the
        // string, whichever comes first
        auto endIter = startIter + std::min(columns, static_cast<size_t>(std::distance(startIter, s.end())));
        while (true)
        {
            // just push on a string using the start and end iterators
            v.push_back({startIter, endIter});
    
            // if the end iterator is at the end of the string, quit
            if (endIter == s.end())
                break;
    
            // move the start to the end
            startIter = endIter;
    
            // move the end to either 8 characters after the start, or the
            // end of the string, whichever comes first
            endIter = startIter + std::min(columns, static_cast<size_t>(std::distance(startIter, s.end())));
        }
    
        // Output the results
        for (auto& vrow : v)
            std::cout << vrow << "\n";
    }
    
    int main()
    {
        encryption("ifmanwasmeanttostayonthegroundgodwouldhavegivenusroots");
    }
    

    Output:

    ifmanwas
    meanttos
    tayonthe
    groundgo
    dwouldha
    vegivenu
    sroots