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 ofstr
in the string, ornpos
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 positionpos
and of lengthnpos
.
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:
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.Use
const
when you want to indicate that the function is not going to modify the object. Although it will copy it.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.
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}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
How True Is "Want Speed? Pass by Value"
How to Write Log Base(2) in C/C++
Using a Stl Map of Function Pointers
In C++, What Is a "Namespace Alias"
Overriding a Base's Overloaded Function in C++
Why Is There Not an Std::Is_Struct Type Trait
C-Style Strings as Template Arguments
Opencv Videocapture Lag Due to the Capture Buffer
Qtcore.Qobject.Connect in a Loop Only Affects the Last Instance
Is Inline Assembly Language Slower Than Native C++ Code
Is It Smart to Replace Boost::Thread and Boost::Mutex with C++11 Equivalents
Do I Need to Explicitly Call the Base Virtual Destructor