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

时间:2009-10-07 15:28:43

标签: c++ casting strtok

我需要将字符串转换为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);
    }
}

相关question

10 个答案:

答案 0 :(得分:8)

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

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

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

答案 1 :(得分:5)

正如丹尼尔所说,你可以选择

strdup(line.c_str());

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

答案 2 :(得分:5)

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

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

How do I tokenize a string in C++?

答案 3 :(得分:2)

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调用delete[] temp_line;。不要使用temp_line,因为您希望在处理后strtok()

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

答案 4 :(得分:1)

strtok的工作原理如下:

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

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

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

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

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

答案 5 :(得分:1)

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

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

如果您确实需要访问字符串的内部缓冲区,请按以下方式进行操作:&*string.begin()。 在某些情况下,直接访问字符串的缓冲区非常有用,here您可以看到这种情况。

答案 8 :(得分:0)

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

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

答案 9 :(得分:-1)

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