C ++ How to convert a string to char *

I need to convert a string to char * for use in strtok_s and failed to figure it out. c_str () is converted to const char *, which is incompatible.

Also, if someone can explain to me why the second strtok_s function is needed (inside the loop), that would be a big help. Why do I need to explicitly promote the token, and not, for example, the while loop in which it is located, which implicitly selects each line of the file.

while( getline(myFile, line) ) { // Only one line anyway. . . is there a better way? char * con = line.c_str(); token = strtok_s( con, "#", &next_token); while ((token != NULL)) { printf( " %s\n", token ); token = strtok_s( NULL, "#", &next_token); } } 

related question .

+4
source share
10 answers

Use strdup() to copy the const char * returned by c_str() to char * (don't forget free() after that)

Note that strdup() and free() are C, not C ++, and you'd better use the std::string methods.

The second strtok_s () is necessary because otherwise your loop will not end (the token value will not change).

+8
source

Like Daniel said, you can go with

strdup(line.c_str());

Which is better than originally suggested by strcpy as it allocates the necessary space

+5
source

You cannot convert to char * because it will allow you to write std::string to the internal buffer. To avoid the visibility of the std::string implementation, this is not allowed.

Instead of strtok try a more β€œC ++ -like” way of string tokenization. See this question:

How to make string tokenization in C ++?

+5
source

strtok() is a poorly designed function to get you started. Check your documentation to see if you have the best. BTW, never use strtok() in any kind of streaming environment unless your docs talk about it safely, as it stores state between calls and changes the line it called. I assume strtok_s() is a more secure version, but it will not be really safe.

To convert a std::string to char * , you can do:

 char * temp_line = new char[line.size() + 1]; // +1 char for '\0' terminator strcpy(temp_line, line.c_str()); 

and use temp_line . Your installation may have a strdup() function that will duplicate the above.

The reason you need two calls to strtok_s() is because they do different things. The first tells strtok_s() which line it should work on, and the second with the same line. This is the reason for the NULL argument; it tells strtok_s() to continue working with the source string.

Therefore, you need one call to get the first token, and then one for each subsequent token. They could be combined with something like

 char * temp_string_pointer = temp_line; while ((token = strtok_s( con, "#", &next_token)) != NULL) { temp_string_pointer = NULL; 

etc., since it will call strtok_s() once with a pointer to a string and after that with NULL . Do not use temp_line for this, since you want delete[] temp_line; after processing.

You might think that this is a lot of messing around, but what strtok() and relatives usually mean.

+2
source

strtok works as follows:

The first line to return the call from the start of the unril separator or the entire line if no separator is found:

 token = strtok_s(con, "#", &next_token); 

The second call using NULL allows you to continue parsing the same line to find the following delimiter:

 token = strtok_s(NULL, "#", &next_token); 

If you get to the end of the line, the next call will return NULL;

+1
source

Whenever you have std::string and you need a (modifiable) array of characters, then std::vector<char> is what you need:

 void f(char* buffer, std::size_t buffer_size); void g(std::string& str) { std::vector<char> buffer(str.begin(),str.end()); // buffer.push_back('\0'); // use this if you need a zero-terminated string f(&buffer[0], buffer.size()); // if you added zero-termination, consider it for the size str.assign(buffer.begin(), buffer.end()); } 
+1
source

the second call to strtok is inside the loop. It advances the marker so that you print the markers one by one until you print them all, the pointer becomes zero, and you exit the loop.

To answer the first part of your question, as others have suggested, c_str () provides only an internal buffer pointer - you cannot change this, therefore it is const. If you want to change it, you need to allocate your own buffer and copy the contents of the string into it.

0
source

If you really need access to the internal string buffer, here's how to do it: &*string.begin() . Direct access to the string buffer is useful in some cases, here you can see such a case.

0
source

You can easily write a conversion procedure that will tokenize a string and return a vector of substrings:

 std::vector<std::string> parse(const std::string& str, const char delimiter) { std::vector<std::string> r; if(str.empty()) return r; size_t prev = 0, curr = 0; do { if(std::string::npos == (curr = str.find(delimiter, prev))) curr = str.length(); r.push_back(str.substr(prev, curr - prev)); prev = curr + 1; } while(prev < (int)str.length()); return r; } 
0
source

I think you can convert the string to const char * first, and then copy const char * to the char * buffer for later use.

-one
source

All Articles