I am trying to create a function that will take in a long string with " " and "," dividing different elements gained from a text file. "," represents a new line and " " represents the end of a number in the line. once split the strings should be part of an array.
string* splitstr(string text, string deli = " ")
{
int start = 0;
int end = text.find(deli);
string *numbers[end];
for (int i = 0; end != -1; i )
{
numbers[i] = text.substr(start, end - start);
start = end deli.size();
end = text.find(deli, start);
}
return numbers;
}
However I am facing a problem where I get this:
cannot convert 'std::string**' {aka 'std::__cxx11::basic_string<char>**'} to 'std::string*' {aka 'std::__cxx11::basic_string<char>*'} in return
How can I resolve this, or improve my function?
I was expecting to be able to store string elements in a string array and make the function return the array. I'm fairly new to programming and I started off with java so this logic might not work in c .
CodePudding user response:
You should avoid using arrays like this and instead use a vector
like as follows:
std::vector<std::string> splitstr(const std::string & text, const std::string & deli = " ")
{
int start = 0;
int end = text.find(deli);
std::vector<std::string> numbers;
for (int i = 0; end != -1; i )
{
numbers.push_back(text.substr(start, end - start));
start = end deli.size();
end = text.find(deli, start);
}
return numbers;
}
note this will not get the last item in the string if there is not a delimiter after it.
CodePudding user response:
Use a combination of std::vector and std::string_view. A string_view avoids the need to allocate new output strings, the caveat is that you can only use the split result if the original input string is still in memory.
#include <iostream>
#include <string>
#include <string_view>
#include <vector>
#include <set>
// returns vector of string views to avoid copying of string data
// this function can split on multiple delimiters.
auto split_string(std::string_view input, std::string_view delimiters)
{
std::vector<std::string_view> substrings;
std::size_t substring_len{ 0ul };
// string_view can be constructed from a pointer and a length
auto start_of_substring_ptr = input.data();
auto current_char_ptr = input.data();
// use range based for to never run beyond end of input string
for (const char c : input)
{
// if a delimiter is found
if (delimiters.find(c) != std::string::npos)
{
if (substring_len != 0ul)
{
// add another string_view to the output
substrings.emplace_back(start_of_substring_ptr , substring_len);
}
// assume the next substring will start after this delimter
// if there are multiple delimiters in a row it will just move ahead
start_of_substring_ptr = current_char_ptr 1;
substring_len = 0ul;
}
else
{
substring_len ;
}
current_char_ptr ;
}
return substrings;
}
int main()
{
std::string input{ "Time flies when you are having fun, kermit said!"};
for (const auto& substring : split_string(input, " ,!"))
{
std::cout << substring << "\n";
}
return 0;
}