У меня возникла эта проблема в одном из вопросов по кодированию на экзамене в университете, где я знал ответ, но не мог понять, так как не знал, как разобрать строку и преобразовать ее в 2d-вектор. Итак, у меня есть 2d-вектор в виде строки
"[[1,4], [5,7], [4,1], [8,9]]"
Я хочу преобразовать эту строку в vector<vector<int>>
РЕДАКТИРОВАТЬ
Может быть, я не ясно выразился в прошлый раз, и есть одна вещь, которую я пропустил. Строка
"[[1,4], [5,7], [4,1], [8,9]]"
Я хочу, чтобы эта строка была в виде двумерного вектора. Итак, допустим, у меня есть вектор vec, определенный как vector<vector<int>> vec. Тогда vec[0] = {1,4}, vec[1] = {5,7}, vec[2] = {4,1}, vec[3] = {8,9}. Ниже то, что я сделал, и он показывает неправильный вывод
#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);
}
}
, и , это два разных разделителя? Этот формат фиксированный? В этом случае вы можете сначала удалить первые два символа и два последних символа, разделить на ], [, а затем разделить на ,.
на самом деле это вариант этого вопроса: stackoverflow.com/questions/1120140/…. Решение требует лишь небольших доработок
Отвечает ли это на ваш вопрос? stackoverflow.com/questions/1120140/…
Общий совет для таких вещей: 1. Старайтесь писать общие функции, которые вы сможете использовать позже. Как, например, функция, которая может разграничить заданную строку, то есть строка -> вектор строки. 2. Рассмотрим создание конечного автомата. Имейте перечисление для фаз, а затем большой цикл с переключением на текущую фазу. С помощью этой техники вы можете многое. 3. Если вы спрашиваете на SO, проявите некоторое усилие с вашей стороны. Если вам нужно какое-то начало, учтите, что вы можете перебирать символы строки, как через массив.





#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);
}
@ThomasSablik Из вашей ссылки: «Не минусуйте тех, кто добросовестно отвечает на вопросы о домашнем задании, даже если они нарушают эти правила (если только ответ не заслуживает отрицательных голосов, даже если вопрос не был связан с домашним заданием)».
Вот быстрая реализация Godbolt:
Примечание. Этот ответ не обрабатывает случаи, когда целые числа имеют более одной цифры. Он не является общим или легко расширяемым, но, поскольку это вопрос домашнего задания, вы можете понять и улучшить код.
#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();
}
}
}
@ThomasSablik Какой аспект этого ответа, по вашему мнению, нуждается в улучшении?
Удалите код. Это вопрос домашнего задания. Вы можете помочь решить проблему, но не должны предлагать полное решение.
Эй, спасибо, это то, что я хотел. Можете ли вы указать на ошибку, которую я сделал в своем коде?
@Levi Конечно, ваш код предполагает, что все, что читается, является int, но вам также нужно анализировать открывающие/закрывающие квадратные скобки и запятые. Моя реализация обходит это, читая строку как серию символов и проверяя, являются ли они цифрами. Таким образом, он будет обрабатывать разделители , и закрывающие скобки ].
Общий ответ - написать парсер рекурсивного спуска (поищите его). Это причудливый способ сказать, что вы пишете функцию для каждого из нетерминалов (vector2, vector, int), тогда вы обычно смотрите только на первый байт, чтобы понять, что делать. В этом случае ваша грамматика может быть:
vector2 = "[" vector (, " " vector) "]"
vector = "[" int (, number) "]"
number = 0 | 1 [0-9]
Затем вы реализуете число, вектор и вектор_вектор аналогично тому, как @StPiere показал вам ранее.
Я обычно использую c, и я нашел эту универсальную сигнатуру функции полезной для начала:
char *parse_something(const char *s, something *v)
где s — это строка, которую вы анализируете, а возвращаемое значение — это то, что вы хотите проанализировать следующим образом.
не используйте выше/ниже для ссылки на другие ответы. Это зависит от сортировки каждого пользователя. Я не вижу ответа выше твоего
Хорошая точка зрения. Вместо этого использовал временную ссылку, чтобы указать, что подробный ответ был опубликован к тому времени, когда я отправил свой ответ.
Пожалуйста, предоставьте пример end-2-end, т.е. эта строка должна стать этим объектом. Есть много способов перейти от вашего примера к строке векторов. Затем предоставьте то, что вы пробовали до сих пор, но это не сработало.