C ++如何将字符串转换为char *

时间:2023-02-04 16:23:40

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

我需要将字符串转换为char *以便在strtok_s中使用,并且无法弄明白。 c_str()转换为const char *,它是不兼容的。

Also, if someone could explain to me why the second strtok_s function (inside the loop) is necessary, it'd be a great help. Why do i need to explicitly advance the token rather than, for example, the while loop it is in, which fetches each line of a file consecutively, implicitly.

此外,如果有人可以向我解释为什么第二个strtok_s函数(在循环内)是必要的,这将是一个很大的帮助。为什么我需要显式地提升令牌而不是例如它所处的while循环,它隐式地连续地获取文件的每一行。

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.

10 个解决方案

#1


8  

Use strdup() to copy the const char * returned by c_str() into a char * (remember to free() it afterwards)

使用strdup()将c_str()返回的const char *复制到char *中(之后记得free())

Note that strdup() and free() are C, not C++, functions and you'd be better off using methods of std::string instead.

请注意,strdup()和free()是C,而不是C ++,函数,你最好使用std :: string的方法。

The second strtok_s() is needed because otherwise your loop won't terminate (token's value won't change).

第二个strtok_s()是必需的,否则你的循环不会终止(标记的值不会改变)。

#2


5  

You can't convert to a char * because that would that would allow you to write to std::string's internal buffer. To avoid making std::string's implementation visible, this isn't allowed.

你不能转换为char *,因为这将允许你写入std :: string的内部缓冲区。为避免使std :: string的实现可见,不允许这样做。

Instead of strtok, try a more "C++-like" way of tokenizing strings. See this question:

而不是strtok,尝试更多“类似C ++”的方式来标记字符串。看到这个问题:

How do I tokenize a string in C++?

如何在C ++中对字符串进行标记?

#3


5  

As Daniel said, you could go with

正如丹尼尔所说,你可以一起去

strdup(line.c_str());

Which is better then the strcpy I originally proposed since it allocates the necessary space

这比我最初提出的strcpy更好,因为它分配了必要的空间

#4


2  

strtok() is a badly designed function to begin with. Check your documentation to see if you have a better one. BTW, never use strtok() in any sort of threaded environment unless your docs specifically say it's safe, since it stores state in between calls and modifies the string it's called on. I assume strtok_s() is a safer version, but it's not going to be a really safe one.

strtok()是一个设计糟糕的函数。检查您的文档,看看您是否有更好的文档。 BTW,永远不要在任何类型的线程环境中使用strtok(),除非你的文档特别说它是安全的,因为它在调用之间存储状态并修改它所调用的字符串。我假设strtok_s()是一个更安全的版本,但它不会是一个非常安全的版本。

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

要将std :: string转换为char *,您可以执行以下操作:

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, which will duplicate the above.

并使用temp_line。您的安装可能有strdup()函数,它将复制上述内容。

The reason you need two calls to strtok_s() is that they do different things. The first one tells strtok_s() what string it needs to work on, and the second one continues with the same string. That's the reason for the NULL argument; it tells strtok_s() to keep going with the original string.

你需要两次调用strtok_s()的原因是他们做了不同的事情。第一个告诉strtok_s()它需要处理什么字符串,第二个字符串继续使用相同的字符串。这就是NULL参数的原因;它告诉strtok_s()继续使用原始字符串。

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;

and so on, since that would call strtok_s() once with the string pointer and after that with NULL. Don't use temp_line for this, since you want to delete[] temp_line; after processing.

等等,因为那会用字符串指针调用strtok_s()一次,然后用NULL调用。不要使用temp_line,因为你要删除[] temp_line;经过处理。

You may think this is a lot of fiddling around, but that's what strtok() and relatives usually entail.

你可能认为这很多摆弄,但这就是strtok()和亲戚通常需要的东西。

#5


1  

strtok works like this:

strtok的工作原理如下:

First call return string from beginning unril the delimiter or all the string if no delimiter were found:

首先从unril开始调用返回字符串,如果没有找到分隔符则调用所有字符串:

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

Second call using with NULL allow you to continue parsing the same string to find the next delimiter:

使用NULL进行第二次调用允许您继续解析相同的字符串以查找下一个分隔符:

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

If you reach the end of the string next call will return NULL;

如果到达字符串的末尾,则下一次调用将返回NULL;

#6


1  

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

每当你有一个std :: string,你需要的是一个(可修改的)字符数组,那么你需要std :: vector :

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());
}

#7


0  

the 2nd strtok call is inside the loop. It advances you token pointer so that you print out tokens one-by-one, until you've printed out all of them, the pointer becomes null and you exit the loop.

第二个strtok调用是在循环内部。它会使您的令牌指针前进,以便您逐个打印出令牌,直到您打印出所有这些令牌,指针变为空并退出循环。

To answer the 1st part of your question, as other have suggested, c_str() only gives you the internal buffer pointer - you can't modify that, that's why it's const. If you want to modify it, you need to allocate your own buffer and copy the string's contents into it.

要回答问题的第一部分,正如其他人所建议的那样,c_str()只给你内部缓冲区指针 - 你不能修改它,这就是为什么它是const。如果要修改它,则需要分配自己的缓冲区并将字符串的内容复制到其中。

#8


0  

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

如果你真的需要访问字符串的内部缓冲区,请参见:&* string.begin()。在某些情况下,直接访问字符串的缓冲区非常有用,在这里您可以看到这种情况。

#9


0  

You can easily write a conversion routine that will tokenize a string and return a vector of sub-strings:

您可以轻松编写一个转换例程,该例程将标记字符串并返回子字符串向量:

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;
}

#10


-1  

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

我想你可以先将字符串转换为const char *,然后将const char *复制到char *缓冲区以供进一步使用。

#1


8  

Use strdup() to copy the const char * returned by c_str() into a char * (remember to free() it afterwards)

使用strdup()将c_str()返回的const char *复制到char *中(之后记得free())

Note that strdup() and free() are C, not C++, functions and you'd be better off using methods of std::string instead.

请注意,strdup()和free()是C,而不是C ++,函数,你最好使用std :: string的方法。

The second strtok_s() is needed because otherwise your loop won't terminate (token's value won't change).

第二个strtok_s()是必需的,否则你的循环不会终止(标记的值不会改变)。

#2


5  

You can't convert to a char * because that would that would allow you to write to std::string's internal buffer. To avoid making std::string's implementation visible, this isn't allowed.

你不能转换为char *,因为这将允许你写入std :: string的内部缓冲区。为避免使std :: string的实现可见,不允许这样做。

Instead of strtok, try a more "C++-like" way of tokenizing strings. See this question:

而不是strtok,尝试更多“类似C ++”的方式来标记字符串。看到这个问题:

How do I tokenize a string in C++?

如何在C ++中对字符串进行标记?

#3


5  

As Daniel said, you could go with

正如丹尼尔所说,你可以一起去

strdup(line.c_str());

Which is better then the strcpy I originally proposed since it allocates the necessary space

这比我最初提出的strcpy更好,因为它分配了必要的空间

#4


2  

strtok() is a badly designed function to begin with. Check your documentation to see if you have a better one. BTW, never use strtok() in any sort of threaded environment unless your docs specifically say it's safe, since it stores state in between calls and modifies the string it's called on. I assume strtok_s() is a safer version, but it's not going to be a really safe one.

strtok()是一个设计糟糕的函数。检查您的文档,看看您是否有更好的文档。 BTW,永远不要在任何类型的线程环境中使用strtok(),除非你的文档特别说它是安全的,因为它在调用之间存储状态并修改它所调用的字符串。我假设strtok_s()是一个更安全的版本,但它不会是一个非常安全的版本。

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

要将std :: string转换为char *,您可以执行以下操作:

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, which will duplicate the above.

并使用temp_line。您的安装可能有strdup()函数,它将复制上述内容。

The reason you need two calls to strtok_s() is that they do different things. The first one tells strtok_s() what string it needs to work on, and the second one continues with the same string. That's the reason for the NULL argument; it tells strtok_s() to keep going with the original string.

你需要两次调用strtok_s()的原因是他们做了不同的事情。第一个告诉strtok_s()它需要处理什么字符串,第二个字符串继续使用相同的字符串。这就是NULL参数的原因;它告诉strtok_s()继续使用原始字符串。

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;

and so on, since that would call strtok_s() once with the string pointer and after that with NULL. Don't use temp_line for this, since you want to delete[] temp_line; after processing.

等等,因为那会用字符串指针调用strtok_s()一次,然后用NULL调用。不要使用temp_line,因为你要删除[] temp_line;经过处理。

You may think this is a lot of fiddling around, but that's what strtok() and relatives usually entail.

你可能认为这很多摆弄,但这就是strtok()和亲戚通常需要的东西。

#5


1  

strtok works like this:

strtok的工作原理如下:

First call return string from beginning unril the delimiter or all the string if no delimiter were found:

首先从unril开始调用返回字符串,如果没有找到分隔符则调用所有字符串:

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

Second call using with NULL allow you to continue parsing the same string to find the next delimiter:

使用NULL进行第二次调用允许您继续解析相同的字符串以查找下一个分隔符:

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

If you reach the end of the string next call will return NULL;

如果到达字符串的末尾,则下一次调用将返回NULL;

#6


1  

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

每当你有一个std :: string,你需要的是一个(可修改的)字符数组,那么你需要std :: vector :

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());
}

#7


0  

the 2nd strtok call is inside the loop. It advances you token pointer so that you print out tokens one-by-one, until you've printed out all of them, the pointer becomes null and you exit the loop.

第二个strtok调用是在循环内部。它会使您的令牌指针前进,以便您逐个打印出令牌,直到您打印出所有这些令牌,指针变为空并退出循环。

To answer the 1st part of your question, as other have suggested, c_str() only gives you the internal buffer pointer - you can't modify that, that's why it's const. If you want to modify it, you need to allocate your own buffer and copy the string's contents into it.

要回答问题的第一部分,正如其他人所建议的那样,c_str()只给你内部缓冲区指针 - 你不能修改它,这就是为什么它是const。如果要修改它,则需要分配自己的缓冲区并将字符串的内容复制到其中。

#8


0  

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

如果你真的需要访问字符串的内部缓冲区,请参见:&* string.begin()。在某些情况下,直接访问字符串的缓冲区非常有用,在这里您可以看到这种情况。

#9


0  

You can easily write a conversion routine that will tokenize a string and return a vector of sub-strings:

您可以轻松编写一个转换例程,该例程将标记字符串并返回子字符串向量:

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;
}

#10


-1  

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

我想你可以先将字符串转换为const char *,然后将const char *复制到char *缓冲区以供进一步使用。