Mardaloescu Serban
Mardaloescu Serban

Reputation: 73

Error trying to use 'strtok' for a string

#include <iostream>
#include <string.h>
using namespace std;

int main() {
char *tok;
string s = "Ana and Maria are dancing.";
tok = strtok(s.c_str(), " ");
while(tok != NULL) {
    cout << tok << " ";
    tok = strtok(NULL, " ");
}
return 0;
}

And I'm getting this error:

:9:29: error: invalid conversion from ‘const char*’ to ‘char*’ [-fpermissive]
In file included from ceva.cc:2:0:
348:14: error: initializing argument 1 of ‘char* strtok(char*, const char*)’ [-fpermissive]"

Upvotes: 2

Views: 4743

Answers (2)

Andy Prowl
Andy Prowl

Reputation: 126442

The problem is that c_str() returns a const char*, because the string object is supposed to be the owner of the buffer where the encapsulated string is stored, so you are not entitled to modify it except through member functions of string.

On the other hand, strtok() accepts a pointer to (non-const) char, i.e. a char*, and this is what the compiler complains about: you are trying to pass something non-modifiable to a function that wants to modify that thing.

If I may suggest a better approach which is more idiomatic in C++11, since you are using std::string anyway, rather do the following:

#include <iostream>
#include <string>

int main() 
{
    std::string s = "Ana and Maria are dancing";

    std::string::size_type start = 0;
    std::string::size_type pos = s.find(" ");
    while (pos != std::string::npos)
    {
        std::string tok = s.substr(start, pos - start);
        std::cout << tok << " ";

        start = pos + 1;
        pos = s.find(" ", start);
    }
}

The above code also removed this directive:

using namespace std;

It is commonly considered bad programming practice (especially when placed at global namespace scope), because it easily leads to name clashes with entities that belong to the std namespace.

Upvotes: 2

Joachim Isaksson
Joachim Isaksson

Reputation: 180917

strtok() is destructive in its parsing (ie it writes to the string you're parsing while you're parsing it), so it takes a char* as a parameter, not a const char*.

c_str() returns a const char* since it does not expect you to write to the content of the buffer it returns.

A way to do the parsing is to strdup() (ie copy) the buffer you want to work and parse that, ie;

char* buf = strdup(s.c_str());
tok = strtok(buf, " ");
...

Remember to free the copy once you're done with it.

Upvotes: 5

Related Questions