【问题标题】:Why isn't C++ strtok() working for me?为什么 C++ strtok() 不适合我?
【发布时间】:2010-02-19 16:55:53
【问题描述】:

该程序应该通过 cin 接收输入,对其进行标记,然后输出每个输入以向我显示它工作正常。它没有。

程序编译没有错误,并接受输入,但没有输出任何内容。

我做错了什么?

int main(int argc, char* argv[])
{
  string input_line;

  while(std::cin >> input_line){
    char* pch = (char*)malloc( sizeof( char ) *(input_line.length() +1) );

    char *p = strtok(pch, " ");
    while (p != NULL) {
      printf ("Token: %s\n", p);
      p = strtok(NULL, " ");
    }
  }
  return 0;
}

我按照这里的代码示例:http://www.cplusplus.com/reference/clibrary/cstring/strtok/

谢谢。

【问题讨论】:

  • 附带说明,sizeof(char) 始终为 1(根据定义),new char[] 将避免对任何类型的 sizeof 以及对结果的指针强制转换。
  • 您确定要cin >> input_line(读取一个字符串,在空白处停止)而不是getline(cin, input_line)(读取一个字符串,在换行符处停止)?
  • ...别忘了释放 pch。或者更好的是,使用 std::vector 而不是手动管理的缓冲区
  • 另一方面,您将 C++ 和 C 混合得非常糟糕。混合 stdio 和流 I/O 并不是一个好主意,而且 C++ 具有比 C 更好的字符串处理功能。此外,strtok() 是一个设计非常糟糕的函数。

标签: c++ tokenize strtok


【解决方案1】:

您好像忘记将input_line 的内容复制到pch:

strcpy(pch, input_line.c_str());

但我不确定你为什么要进行字符串标记化。执行cin >> input_line 不会读取一行,而是读取一个令牌.. 所以无论如何你都会得到令牌?

【讨论】:

    【解决方案2】:

    这是一个正确的帖子,汉斯有你的问题。

    获取一行输入的正确方法是使用getline:

    std::string s;
    std::getline(std::cin, s);
    

    std::cin 无论如何都会在空白处中断,所以如果您输入 asd 123 并运行您的代码,input_line 将首先是“asd”,然后是循环中的第二次“123”(无需等待输入)。

    也就是说,获得结果的一种简单方法是使用stringstream。任何时候你明确分配内存,尤其是malloc,你可能正在做一些艰难的事情。这是标记字符串的一种可能的解决方案:

    #include <sstream>
    #include <string>
    #include <iostream>
    
    int main(void)
    {
        std::string input;
        std::getline(std::cin, input);
    
        std::stringstream ss(input);
        std::string token;
        while(std::getline(ss, token, ' '))
        {
            std::cout << token << "...";
        }
    
        std::cout << std::endl;
    }
    

    如果你真的想使用strtok,你可以这样做:

    #include <cstring>
    #include <string>
    #include <iostream>
    #include <vector>
    
    int main(void)
    {
        std::string input;
        std::getline(std::cin, input);
    
        std::vector<char> buffer(input.begin(), input.end());
        buffer.push_back('\0');
    
        char* token = strtok(&buffer[0], " ");
        for (; token; token = strtok(0, " "))
        {
            std::cout << token << "...";
        }
    
        std::cout << std::endl;
    }
    

    记住,手动内存管理是不好的。对数组使用vector,可以避免泄漏。 (你的代码有!)

    【讨论】:

      【解决方案3】:

      你没有初始化你的字符串。插入

      strcpy(pch, input_line.c_str());
      

      在malloc 行之后。

      【讨论】:

        【解决方案4】:

        GMan 的答案可能更好,更纯粹是 c++。这更像是一个专门使用strtok() 的组合,因为我认为这是你的目标。

        我使用了strdup()/free(),因为它是复制字符串的最简单方法。在问题中,您正在泄漏内存,因为您 malloc() 没有匹配的 free()。

        带有字符串的

        Also operator>> 将在空格处中断,因此不适合获取行。请改用getline()。

        token.cpp

        #include <iostream>
        #include <string>
        #include <cstring> /* for strtok() and strdup() */
        #include <cstdlib> /* for free() */
        
        int main(int argc, char * argv[]){
            std::string line;
        
            while(getline(std::cin, line)){
                char *pch = strdup(line.c_str());
        
                char *p = strtok(pch, " ");
        
                while(p){
                    std::cout<<"Token: "<<p<<std::endl;
                    p = strtok(NULL, " ");
                }
        
                std::cout <<"End of line"<<std::endl;
                free(pch);
            }
            return 0;
        }
        

        当你运行它时,你会得到看起来正确的结果/

        $ printf '你好,我喜欢记号\n也可以在新行上\n\n空格很好'|./token
        代币:嗨
        令牌:那里,
        代币:我
        代币:喜欢
        代币:代币
        行尾
        令牌:开启
        代币:新
        代币:行
        代币:太
        行尾
        行尾
        代币:空白
        代币:是
        代币:很好
        行尾

        【讨论】:

          【解决方案5】:

          或者使用这个:

          pch = strdup(input_line.c_str());
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2017-07-07
            • 2014-01-03
            • 2011-04-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多