Какой тип данных написать что бы вернуть массив строк
Какой тип должен стоять у функции что бы она вернула массив строк.
Класс
#include <iostream>
#include <string>
#include <regex>
class Fun {
public:
Split(std::string text, std::string separator) {
int i = 0;
std::regex regex("\\"+separator);
std::vector<std::string> out(
std::sregex_token_iterator(text.begin(), text.end(), regex, -1),
std::sregex_token_iterator()
);
for (auto &s: out) {
i++;
}
std::string res_arr[i] ;
i=0;
for (auto &s: out) {
res_arr[i] = s;
i++;
}
return res_arr;
}
};
вызов:
Fun testclass;
result = Fun.Split("Текст который хочу ! разделить","!");
p.s. Не судите строго за авнокод, только неделю учу плюсы.
Ответы (1 шт):
Начнем с того, что объявление массива с размером, известным во время выполнения — действие не стандартное, это расширение компилятора GCC. Так что
std::string res_arr[i] ;
в этом смысле — соответствия стандарту — не работает. Но если бы и работало — то при возврате массива возвращается указатель на его первый элемент, сам массив не копируется. Но это указатель на локальную переменную, которая исчезнет при выходе из функции и остаетесь вы у разбитого корыта...
Можно создать массив динамически:
string * res_arr = new string[i];
и вернуть res_arr. Функция при этом имеет вид
string * Split(std::string text, std::string separator)
Внутри функции с res_arr вы работаете так же, как с массивом. Это сработает. Но есть пару "но": по указателю неизвестен размер массива, а значит, его надо передавать отдельно, и теперь вы отвечаете за освобождение выделенной памяти.
Есть интересное решение — "завернуть" массив в структуру, что-то вроде
struct Ret
{
string res_arr[i]; // Или string * res_arr
int res_arr_size;
};
Так можно убить двух зайцев: во-первых, структура при возврате копируется, так что пропадает проблема с локальной переменной, а во-вторых, вы возвращаете заодно и размер массива.
Но это, по сути, изобретение велосипеда, так как такая (вернее, куда более мощная) структура давно есть в С++ — это vector.
Так что лучше всего объявить
std::vector<std::string> Split(std::string text, std::string separator)
(а еще лучше
std::vector<std::string> Split(const std::string& text, const std::string& separator)
чтобы не копировать большие строки), а в функции написать
std::vector<std::string> res_arr(i);
и работать точно так же. Но поскольку вектор — это больше, чем просто структура, вам даже не надо делать предварительный проход для выяснения количества элементов — можно сразу же добавлять элементы в вектор. Он сам разберется с выделением памяти. Так вы не имеете проблемы с локальной переменной, не меняете синтаксис обращения к элементам, всегда знаете количество элементов в векторе (для чего используется функция .size()) — одни плюсы. Небольшой минус — немного лишней памяти, но, как правило, она невелика, да и ту можно уменьшить — в вашем случае таки определяя, сколько элементов будет в векторе, заранее.