为什么 C++ strtok() 为我工作吗?

发布于 2024-08-22 09:02:54 字数 643 浏览 4 评论 0原文

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

谢谢。

The program is supposed to receive an input through cin, tokenize it, and then output each one to show me that it worked properly. It did not.

The program compiles with no errors, and takes an input, but fails to output anything.

What am I doing wrong?

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

I followed the code example here: http://www.cplusplus.com/reference/clibrary/cstring/strtok/

Thanks.

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

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

发布评论

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

评论(5

停滞 2024-08-29 09:02:54

看起来您忘记将 input_line 的内容复制到 pch:

strcpy(pch, input_line.c_str());

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

Looks like you forget to copy the contents of input_line to pch:

strcpy(pch, input_line.c_str());

But I'm not sure why you're doing string tokenization anyway. Doing cin >> input_line will not read a line, but a token.. so you get tokens anyway?

揽月 2024-08-29 09:02:54

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

获取一行输入的正确方法是使用 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;
}

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

This is more of a correctness post, Hans has your problem.

The correct way to get a line of input is with getline:

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

std::cin breaks at whitespace anyway, so if you typed asd 123 and ran your code, input_line would first be "asd", then the second time in the loop "123" (without waiting for enter).

That said, an easy way to get your result is with a stringstream. Any time you explicitly allocate memory, especially with malloc, you're probably doing something the hard way. Here's one possible solution to tokenizing a string:

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

If you really want to use strtok, you might do something like this:

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

Remember, manually memory management is bad. Use a vector for arrays, and you avoid leaks. (Which your code has!)

笑,眼淚并存 2024-08-29 09:02:54

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

strcpy(pch, input_line.c_str());

malloc 行之后

You didn't initialize your string. Insert

strcpy(pch, input_line.c_str());

after the malloc line.

夏末的微笑 2024-08-29 09:02:54

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

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

也算符>>字符串会在空格处中断,因此不适合获取行。请改用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
代币:嗨
令牌:有,
代币:I
代币:喜欢
代币:代币
行尾
令牌:开启
代币:新
令牌:行
代币:太
行尾
行尾
令牌:空白
令牌:是
令牌:很好
行尾

GMan's answer is probably better and more purely c++. This is more of a mix which specifically uses strtok(), since I think that was your goal.

I used strdup()/free() since it was the easiest way to copy the string. In the question you were leaking memory since you'd malloc() with no matching free().

Also operator>> with the string will break on whitespace and so inappropriate for getting lines. Use getline() instead.

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

When you run this, you get what appears to be the correct result/

$ printf 'Hi there, I like tokens\nOn new lines too\n\nBlanks are fine'|./token
Token: Hi
Token: there,
Token: I
Token: like
Token: tokens
End of line
Token: On
Token: new
Token: lines
Token: too
End of line
End of line
Token: Blanks
Token: are
Token: fine
End of line

你又不是我 2024-08-29 09:02:54

或者使用这个:

pch = strdup(input_line.c_str());

Or use this:

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