Split a String Using C++11

Parse (split) a string in C++ using string delimiter (standard C++)

You can use the std::string::find() function to find the position of your string delimiter, then use std::string::substr() to get a token.

Example:

std::string s = "scott>=tiger";
std::string delimiter = ">=";
std::string token = s.substr(0, s.find(delimiter)); // token is "scott"
  • The find(const string& str, size_t pos = 0) function returns the position of the first occurrence of str in the string, or npos if the string is not found.

  • The substr(size_t pos = 0, size_t n = npos) function returns a substring of the object, starting at position pos and of length npos.


If you have multiple delimiters, after you have extracted one token, you can remove it (delimiter included) to proceed with subsequent extractions (if you want to preserve the original string, just use s = s.substr(pos + delimiter.length());):

s.erase(0, s.find(delimiter) + delimiter.length());

This way you can easily loop to get each token.

Complete Example

std::string s = "scott>=tiger>=mushroom";
std::string delimiter = ">=";

size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
std::cout << token << std::endl;
s.erase(0, pos + delimiter.length());
}
std::cout << s << std::endl;

Output:

scott
tiger
mushroom

C++ splitting a String feedback

The rule of thumb is:

  1. Use & when you want to signal that your function can modify the argument and changes should be visible outside. Also passing an argument via & does not create a copy.

  2. Use const when you want to indicate that the function is not going to modify the object. Although it will copy it.

  3. Use const & to combine both those situations above: the object will not be modified by the function but also will not be copied (which is important when copying is expensive like in the case of strings)

So for you the best solution is: use const std::string& value (please change the name of the variable). You don't modify the string and it may be too big to copy it.


As for std::move. What it does is (basically) it turns a non-temporary object to a temporary. So as you can see using std::move on temporaries (your case) is pointless.

Why do we do that? In order to allow the C++ compiler to apply aggressive optimizations. Consider this code:

std::string text = "abcd";
result.push_back(text);

C++ doesn't know that text is not going to be used anymore. So it has to copy it. But with this:

std::string text = "abcd";
result.push_back(std::move(text));

you tell the C++ compiler: "hey, I'm not going to use text variable anymore, so you don't have to copy it, just move its internals to the vector". And all you have to know is that in the case of strings copying is more expensive (linear complexity) than moving (always constant time).

Warning - an opinion incoming: I find the std::move name really confusing. It doesn't actually move anything. It's just a static cast. Why not call it std::cast_to_temp or something?

Anyway this result.push_back(std::move(std::string(cache))); is wrong. Pointless. You don't avoid a copy and std::move does nothing. But this result.push_back(std::move(cache)); indeed makes sense. But careful analysis has to be made: is cache really not needed afterwards? It looks like it is (although I didn't dive deeply into your code).


Finally you only care about destruction when you construct, i.e. for each new you need a delete. You don't have new, you don't need delete*.

* that's not always true, sometimes you deal with a nasty code that does an implicit, invisible new for you but actually forces you to do delete. Yeah, sometimes it is hard. But AFAIK this doesn't happen in the standard (or any other self respecting) library. This is a very bad practice.

Final note: of course this is C++, in reality everything is much more complicated, there are exceptions to each rule and so on, and so on. But don't worry about details at the moment, it is ok to learn gradually.

Splitting a string by a character

Using vectors, strings and stringstream. A tad cumbersome but it does the trick.

#include <string>
#include <vector>
#include <sstream>

std::stringstream test("this_is_a_test_string");
std::string segment;
std::vector<std::string> seglist;

while(std::getline(test, segment, '_'))
{
seglist.push_back(segment);
}

Which results in a vector with the same contents as

std::vector<std::string> seglist{ "this", "is", "a", "test", "string" };

C++ how to split string with alphabets and numbers

Thanks to igor.

    size_t first_digit = idToCheckStr.find_first_of("0123456789");
cout << "first_digit: " << first_digit <<endl;

std::string str1 = idToCheckStr.substr (0,first_digit);
cout << "str1: " << str1 <<endl;

std::string str2 = idToCheckStr.substr (first_digit,idToCheckStr.length());
cout << "str2: " << str2 <<endl;

OUTPUT:
first_digit: 2
str1: CH
str2: 1000003

Split string by a character?

stringstream can do all these.

  1. Split a string and store into int array:

    string str = "102:330:3133:76531:451:000:12:44412";
    std::replace(str.begin(), str.end(), ':', ' '); // replace ':' by ' '

    vector<int> array;
    stringstream ss(str);
    int temp;
    while (ss >> temp)
    array.push_back(temp); // done! now array={102,330,3133,76531,451,000,12,44412}
  2. Remove unneeded characters from the string before it's processed such as $ and #: just as the way handling : in the above.

PS: The above solution works only for strings that don't contain spaces. To handle strings with spaces, please refer to here based on std::string::find() and std::string::substr().



Related Topics



Leave a reply



Submit