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

发布于 2024-08-07 15:00:53 字数 641 浏览 6 评论 0原文

我需要将字符串转换为 char * 以在 strtok_s 中使用,但一直无法弄清楚。 c_str() 转换为 const char *,这是不兼容的。

另外,如果有人可以向我解释为什么第二个 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);
    }
}

相关问题

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.

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.

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

原野 2024-08-14 15:00:53

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

请注意,strdup()free() 是 C 函数,而不是 C++ 函数,你会更好使用 std::string 方法代替。

需要第二个 strtok_s() ,因为否则循环将不会终止(token 的值不会改变)。

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

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

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

空城仅有旧梦在 2024-08-14 15:00:53

您无法转换为 char *,因为这将允许您写入 std::string 的内部缓冲区。为了避免使 std::string 的实现可见,这是不允许的。

尝试一种更“类似 C++”的字符串标记方式,而不是 strtok。请参阅此问题:

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

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.

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

How do I tokenize a string in C++?

‖放下 2024-08-14 15:00:53

正如丹尼尔所说,你可以使用

strdup(line.c_str());

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

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

肤浅与狂妄 2024-08-14 15:00:53

strtok() 本来就是一个设计糟糕的函数。检查您的文档,看看是否有更好的文档。顺便说一句,永远不要在任何类型的线程环境中使用 strtok() ,除非您的文档明确表示它是安全的,因为它在调用之间存储状态并修改它所调用的字符串。我认为 strtok_s() 是一个更安全的版本,但它不会是一个真正安全的版本。

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

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

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

您需要两次调用 strtok_s() 的原因是它们执行不同的操作。第一个告诉 strtok_s() 它需要处理什么字符串,第二个继续使用相同的字符串。这就是 NULL 参数的原因;它告诉 strtok_s() 继续使用原始字符串。

因此,您需要一次调用来获取第一个令牌,然后为每个后续令牌调用一次。它们可以与诸如此类的东西组合起来

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

,因为这样会使用字符串指针调用一次 strtok_s() ,然后使用 NULL 调用。不要为此使用 temp_line,因为您希望在处理后delete[] temp_line;

您可能认为这需要大量的摆弄,但这正是 strtok() 及其相关函数通常需要做的事情。

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.

To convert a std::string into the 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, which will duplicate the above.

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.

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.

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

人事已非 2024-08-14 15:00:53

strtok 的工作原理如下:

第一个调用从头开始返回字符串,如果未找到分隔符,则返回整个字符串:

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

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

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

如果到达末尾string 下一次调用将返回 NULL;

strtok works like this:

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

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

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

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

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

追风人 2024-08-14 15:00:53

每当您有一个 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());
}

Whenever you have a std::string and what you need is a (modifiable) character array, 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());
}
深巷少女 2024-08-14 15:00:53

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

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

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.

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.

会傲 2024-08-14 15:00:53

如果您确实需要访问字符串的内部缓冲区,请执行以下操作:&*string.begin()
在某些情况下,直接访问字符串的缓冲区很有用,在这里你可以看到这样的一个案例。

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.

べ映画 2024-08-14 15:00:53

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

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

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;
}
转身以后 2024-08-14 15:00:53

我认为您可以首先将 string 转换为 const char*,然后将 const char* 复制到 char* 缓冲区以供进一步使用。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文