1
\$\begingroup\$

I'm working on a text based rpg game and a couple of commands make use of a target and container pattern. So I wrote this function to split the string up on a given word and put it back together. I'm not sure how efficient it will be in the real world, but I think that it can be improved.

An example of such input and output would be:

splitOnWord("turkey leg from table", "from") -> {"turkey leg", "table"}
typedef std::vector<std::string> StringVector;
StringVector splitOnWord(std::string line, std::string word){
 std::stringstream sstr(line);
 StringVector tmp;
 std::string str;
 int rescnt = 0;
 sstr >> str;
 tmp.push_back(str);
 while(sstr >> str) {
 if(str == word) {
 ++rescnt;
 tmp.push_back(std::string());
 } else {
 tmp[rescnt] += ' ';
 tmp[rescnt] += str;
 }
 }
 return tmp;
}
asked May 23, 2017 at 0:21
\$\endgroup\$

3 Answers 3

2
\$\begingroup\$

I'm not overly fond of the tmp.push_back(std::string());.

I'd rather some of the names were clearer and more readable--for example, I'm not entirely sure what rescnt is supposed to mean.

Under the circumstances, I'd tend to wonder whether we're getting enough good out of the stringstream to justify its existence either. They can be handy, but here we don't seem to be putting the capabilities to a whole lot of use.

std::vector<std::string> split(std::string const &in, std::string const &word) {
 std::vector<std::string> ret;
 int begin = 0;
 int end = 0;
 while (std::string::npos != (end = in.find(word, begin))) {
 ret.push_back(in.substr(begin, end-begin));
 begin = end + word.length()+1;
 while (::isspace(in[begin]))
 ++begin;
 }
 ret.push_back(in.substr(begin));
 return ret;
}
answered May 23, 2017 at 5:33
\$\endgroup\$
0
\$\begingroup\$

I would extend this even further to have iterator support and other std::basic_string instantiations. The extension might not be worth it if the project is small and unlikely to change.

template <typename CharT, typename CharTraits, 
 typename Allocator, typename OutputIt>
OutputIt split_on_word(const std::basic_string<CharT, CharTraits, Allocator>& in, 
 const std::basic_string<CharT, CharTraits, Allocator>& word, 
 OutputIt out)
{
 ...
}

Supporting other string types might be a good thing for internationalization. Also adding a check if the value type of iterator is the same as string type would be a good boon in debugging template issues or avoiding some bugs.

Nevertheless, the extension will require creating and resizing a vector, or using std::back_inserter. So it really should be weighed if the extension worth the trouble.

answered May 23, 2017 at 7:58
\$\endgroup\$
0
\$\begingroup\$

There is an even simpler solution:

https://stackoverflow.com/questions/11719538/how-to-use-stringstream-to-separate-comma-separated-strings

You can define a separator between the different words of a stream, which of course can also be any word you like

answered May 23, 2017 at 10:49
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.