为什么C ++ strtok()不适合我?

时间:2010-02-19 16:55:54

标签: c++ tokenize strtok

该程序应该通过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/

感谢。

5 个答案:

答案 0 :(得分:9)

您似乎忘了将input_line的内容复制到pch:

strcpy(pch, input_line.c_str());

但是我不知道你为什么要进行字符串标记化。执行cin >> input_line不会读取一行,而是一个令牌..所以你还是得到了令牌?

答案 1 :(得分:5)

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

获得一行输入的正确方法是使用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,可以避免泄漏。 (你的代码有哪些!)

答案 2 :(得分:1)

您没有初始化字符串。插入

strcpy(pch, input_line.c_str());

malloc行之后。

答案 3 :(得分:0)

或者使用它:

pch = strdup(input_line.c_str());

答案 4 :(得分:0)

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

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

也是运营商&gt;&gt;字符串将在空格上打破,因此不适合获取行。请改用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
  令牌:你好   令牌:那里,
  令牌:我   令牌:喜欢
  令牌:令牌
  行尾
  令牌:上   令牌:新的   令牌:行
  令牌:太多了   行尾
  行尾
  令牌:空白   令牌:是   令牌:罚款
  行尾