1

I got this problem in one of the coding questions in my university exam where I knew the answer but couldn't follow as I didn't know how to parse the string and convert it into a 2d vector. So I have got a 2d vector in the form of a string

"[[1,4], [5,7], [4,1], [8,9]]"

I want to convert this string into a vector<vector<int>>

EDIT

Maybe I wasn't clear the last time and there's one thing I missed. The string is

"[[1,4], [5,7], [4,1], [8,9]]"

I want this string to be in the form of a 2d vector. So, let's say I have a vector vec defined as vector<vector<int>> vec. Then vec[0]={1,4}, vec[1]={5,7}, vec[2]={4,1}, vec[3]={8,9}. Below is what I did and it shows incorrect output

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

int main()
{
    string str="[[1,4], [5,7], [4,1], [8,9]]";
    stringstream ss(str);
    vector<vector<int>> vec;
    string temp;
    while(ss>>temp){
        cout<<temp<<endl;
        vector<int> t;
        int x,y;
        stringstream ss2(temp);
        while(ss2>>x>>y)
        {
            t.push_back(x);
            t.push_back(y);

        }
        vec.push_back(t);
    }
}
Levi
  • 79
  • 1
  • 7
  • Please provide an end-2-end example i.e. this string should become this object. There are many ways to go from your example string a vector of vectors. Then provide what you have tried so far that didn't work. – Mansoor Dec 19 '20 at 13:29
  • Are `, ` and `,` the two different separators? Is this format fixed? In that case you can first remove the first two characters and the last two characters, split by `], [` and then split by `,`. – Thomas Sablik Dec 19 '20 at 13:31
  • this is actually a variation of this question: https://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c. The solution needs only small adaptions – 463035818_is_not_an_ai Dec 19 '20 at 13:59
  • Does this answer your question? https://stackoverflow.com/questions/1120140/how-can-i-read-and-parse-csv-files-in-c – 463035818_is_not_an_ai Dec 19 '20 at 13:59
  • General advice for such things: 1. Try to write functions that are general which you can reuse later. Like for example a function that can delimit a given string, that is string -> vector of string. 2. Consider creaating a state machine. Have there be an enum for phases and then a big loop with a switch over the current phase. With that technique, you can do a lot. 3. If you ask on SO, show some effort from your side. If you need any sort of start, consider that you can iterate through the chars of a string like through an array. – Aziuth Dec 19 '20 at 14:35

3 Answers3

2

The generic answer is to write a recursive descent parser (look it up). It's a fancy way of saying that you write a function for each of the non-terminals (vector2, vector, int) then you usually look at just the first byte to figure out to do. In this case your grammar might be:

vector2 = "[" vector (, " " vector) "]"
vector = "[" int (, number) "]"
number = 0 | 1 [0-9]

Then you implement number, vector and vector_vector similar to how @StPiere showed you previously.

I usually use c, and I found this generic function signature to be a useful start:

char *parse_something(const char *s, something *v)

where s is the string you are parsing and the return value is what the next thing is you want to parse.

Allan Wind
  • 23,068
  • 5
  • 28
  • 38
0
#include <iostream>
#include <vector>
using namespace std;

template <typename Range>
void print_range(const Range& r)
{
    for (const auto& e : r)
        cout << e << " ";
    cout << endl;
}

int main()
{
    vector<int> v;
    vector<vector<int>> vv;

    char c;
    int cnt = 0;

    while (cin >> c)
    {
        if (c == ',' || c == ' ' || c == '\n')
        {
            continue;
        }

        if (c == '[')
        {
            ++cnt;
            v.clear();
            continue;
        }

        if (c == ']')
        {
            --cnt;
            if (cnt == 0)
                break;

            vv.push_back(v);
            v.clear();
            continue;
        }

        cin.unget();

        int x;
        if (cin >> x)
            v.push_back(x);
    }

    for (const auto& vec : vv)
        print_range(vec);
}
StPiere
  • 4,113
  • 15
  • 24
  • 4
    https://meta.stackoverflow.com/questions/334822/how-do-i-ask-and-answer-homework-questions – Thomas Sablik Dec 19 '20 at 13:59
  • 2
    @ThomasSablik From your link: “Don't downvote others who answer homework questions in good faith, even if they break these guidelines (unless the answer would merit downvotes even if the question weren't homework related).” – Sneftel Dec 19 '20 at 14:45
0

Here is quick implementation Godbolt:

Note: This answer does not handle cases where integers have more than one digit. It is not generic or easily extensible, but as this is a homework question, you can understand and improve the code.

#include <string>
#include <vector>
#include <istream>
#include <sstream>
#include <cctype>
#include <iostream>
#include <iterator>

int main()
{
    std::string input{"[[1,4], [5,7], [4,1], [8,9]]"};

    std::stringstream ss{input};
    auto it = std::istream_iterator<char>{ss};

    std::vector<std::vector<int>> output;
    std::vector<int> inner;

    // Loop through the string, one character at a time
    while (it != std::istream_iterator<char>{})
    {
        ++it;
        
        // If we encounter a digit, push it into the inner vector
        if (std::isdigit(*it))
        {
            // Dirty hack to convert char to integer (assumes ASCII)
            inner.push_back(*it - 48);
        }

        // If you encounter a ']' char, then push inner vector into the outer vector
        // and then clear the inner vector

        // For the final ']', the inner vector will be size 0, ignore this case
        if (*it == ']')
        {
            if (inner.size() != 0)
            {
                output.push_back(inner);
            }
            inner.clear();
        }
    }
}
Mansoor
  • 2,357
  • 1
  • 17
  • 27
  • 3
    https://meta.stackoverflow.com/questions/334822/how-do-i-ask-and-answer-homework-questions – Thomas Sablik Dec 19 '20 at 13:59
  • @ThomasSablik Which aspect of this answer do you think needs improving? – Mansoor Dec 19 '20 at 14:10
  • Remove the code. This is a homework question. You can help to solve the problem but you shouldn't provide a complete solution. – Thomas Sablik Dec 19 '20 at 14:25
  • Hey, thanks that's what I wanted. Can you point out the mistake that I did in my code? – Levi Dec 19 '20 at 16:47
  • @Levi Sure, your code assumes that everything which is read in is an `int`, but you also have to parse open/close bracket and commas characters. My implementation gets around this by reading in the string as a series of characters, and checking if they are digits. So it will handle the delimiters `,` and closing brackets `]`. – Mansoor Dec 21 '20 at 10:27