使用带有std :: string的strtok

45 c++ strtok

我有一个我想要标记的字符串.但是C strtok()函数需要我的字符串char*.我怎么能这么做呢?

我试过了:

token = strtok(str.c_str(), " "); 
Run Code Online (Sandbox Code Playgroud)

因为把它变成a const char*而不是a 而失败了char*

Chr*_*ell 61

#include <iostream>
#include <string>
#include <sstream>
int main(){
    std::string myText("some-text-to-tokenize");
    std::istringstream iss(myText);
    std::string token;
    while (std::getline(iss, token, '-'))
    {
        std::cout << token << std::endl;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

或者,如上所述,使用boost可以获得更大的灵活性.


Tod*_*lin 20

  1. 如果升压为你的系统上(我认为这是大多数Linux发行版,这些天标准),它有一个标记生成器,你可以使用类.

  2. 如果没有,那么快速谷歌会为std :: string 打开一个手动滚动的标记器,你可以复制和粘贴它.它很短.

  3. 而且,如果你不喜欢其中任何一个,那么这里是我写的一个split()函数,让我的生活更轻松.它会使用"delim"中的任何字符作为分隔符将字符串分解成碎片.片断被附加到"部分"向量:

    void split(const string& str, const string& delim, vector<string>& parts) {
      size_t start, end = 0;
      while (end < str.size()) {
        start = end;
        while (start < str.size() && (delim.find(str[start]) != string::npos)) {
          start++;  // skip initial whitespace
        }
        end = start;
        while (end < str.size() && (delim.find(str[end]) == string::npos)) {
          end++; // skip to end of word
        }
        if (end-start != 0) {  // just ignore zero-length strings.
          parts.push_back(string(str, start, end-start));
        }
      }
    }
    
    Run Code Online (Sandbox Code Playgroud)

  • 手卷链接失效了 (2认同)

Doc*_*Max 15

复制字符串,对其进行标记,然后释放它.

char *dup = strdup(str.c_str());
token = strtok(dup, " ");
free(dup);
Run Code Online (Sandbox Code Playgroud)

  • 这不是更好的问题,为什么在有问题的语言有更好的原生选项时使用strtok? (2认同)
  • 不必要。如果问题的背景涉及维护脆弱的代码库,那么放弃现有方法(在我的示例中名义上是 strtok)比改变方法风险更大。如果问题没有更多背景,我更愿意回答所问的问题。 (2认同)

Mar*_*rov 6

有一个更优雅的解决方案.

使用std :: string,您可以使用resize()分配适当大的缓冲区,使用&s [0]来获取指向内部缓冲区的指针.

在这一点上,许多优秀的人都会在屏幕上大喊大叫.但这是事实.大约2年前

图书馆工作组决定(在利勒哈默尔召开会议)就像std :: vector一样,std :: string也应该正式地,而不仅仅是在实践中,有一个保证连续的缓冲区.

另一个问题是strtok()增加了字符串的大小.MSDN文档说:

每次调用strtok都会通过在该调用返回的标记之后插入空字符来修改strToken.

但这不正确.实际上,该函数用\ 0 替换第一次出现的分隔符.字符串的大小没有变化.如果我们有这个字符串:

一二三四

我们最终会结束

一个\ 0two\0 - 三\ 0四

所以我的解决方案非常简单:


std::string str("some-text-to-split");
char seps[] = "-";
char *token;

token = strtok( &str[0], seps );
while( token != NULL )
{
   /* Do your thing */
   token = strtok( NULL, seps );
}
Run Code Online (Sandbox Code Playgroud)

阅读讨论 http://www.archivum.info/comp.lang.c++/2008-05/02889/does_std::string_have_something_like_CString::GetBuffer