As Jonathan Leffler's comment explains, strtok actually modifies the buffer in place to terminate successive tokens. That's great for speed - saves copying each token out to some other memory area while still giving you convenient access to it as a separate NUL-terminated sequence. It's an interesting question whether it's legitimate to use strtok on a std::string
instance - certainly, the c_str()
member returns a const char*
because you're not meant to write over parts of that buffer. But, as long as you don't have an empty string (for which it'd give undefined behaviour), you can get a char*
to the first element with &line[0]
. Having done that, you can mutate the string, but only at offsets [0]..[size()-1]
... it's not guaranteed to be NUL terminated the way the c_str()
-returned buffer is, and precisely because of that the &line[0]
-returned buffer may not be suitable for use by strtok
. You could append a NUL (i.e. line += '\0'
- NUL is legal std::string
content), but it would make the code a bit hackish and harder to maintain, and you might need to remove the NUL afterwards if you're planning to use the original value for anything.
If you really want to use strtok
, seems best to copy the data to a separate writable NUL-terminated buffer first. For example:
char* p = strdup(line.c_str());
... use strtok on p ...
free(p);
You could use alloca()
, a smart pointer, a std::vector<char>
to minimise potential for memory leaks. (I don't see any particular reason to prefer C++ new
and delete
for the above - you're using strtok
anyway, but if you've smart-pointer libraries that expect it go for it).
All that said, finding another mechanism - like those in boost - is a better option. I'm guessing alternatives like that are discussed in the link chris posted in a comment under your question....