strtok 只返回一个 token

发布于 2024-12-20 08:40:32 字数 1024 浏览 2 评论 0原文

我正在编写一个简单的 shell,它接受一些标准命令,例如 C 中的 cd 和 ls。我正在尝试实现一个功能,用户可以输入“;”位于命令之间,以便可以将一堆命令写在同一行并单独执行。因此,如果我输入“cd Desktop; ls”,shell 应该 cd 到 Desktop 并打印目录中的内容。问题是它只执行第一个命令。这是我的主要方法:

char input[1024];

while(1)
{
    printf("%s ", prompt);
    fgets(input, 1024, stdin);

    char delims[] = ";";
    char *result = NULL;
    result = strtok( input, delims );

    while( result != NULL )
    {
        printf("%s\n", result);

        char * copy = malloc(strlen(result) + 1); //Create a copy of the input token
        strcpy(copy, result);

        format(copy);

        if(programs)
        {
            handle();
            cleanup(programs);
            programs = NULL;
        }
        free(copy);
        result = strtok( NULL, delims );
        cmdno++;
    }
}

首先,我尝试根据“;”将输入分解为标记。然后将令牌提供给 format() 方法,如下所示:

int format(char input[])
{
    input = strtok(input, "\n");
    ...
}

我知道 strtok 会对原始字符串进行更改,这就是为什么我在将令牌传递给 format 之前首先创建令牌的副本。我正在做的事情正确吗?

I'm writing a simple shell that accepts some standard commands like cd and ls in C. I'm trying to implement a feature where the user can enter a ";" in between commands so that a bunch of commands can be written on the same line and be executed separately. So if I input "cd Desktop; ls" the shell should cd to Desktop and print the what's in the directory. The problem is it only executes the first command. Here's my main method:

char input[1024];

while(1)
{
    printf("%s ", prompt);
    fgets(input, 1024, stdin);

    char delims[] = ";";
    char *result = NULL;
    result = strtok( input, delims );

    while( result != NULL )
    {
        printf("%s\n", result);

        char * copy = malloc(strlen(result) + 1); //Create a copy of the input token
        strcpy(copy, result);

        format(copy);

        if(programs)
        {
            handle();
            cleanup(programs);
            programs = NULL;
        }
        free(copy);
        result = strtok( NULL, delims );
        cmdno++;
    }
}

First I try to break up the input into tokens based on ";" and then feed the token to the format() method which looks like this:

int format(char input[])
{
    input = strtok(input, "\n");
    ...
}

I know that strtok makes changes to the original string, which is why I create a copy of the token first before passing it to format. Is what I'm doing correct??

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

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

发布评论

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

评论(2

秋千易 2024-12-27 08:40:32

您不能混合多个 strtok 调用。发生的事情是这样的:

  • 您开始拆分 input,以便 strtok 记录并在内部存储内容
  • 您在拆分 input 中休息一下>
    • 您开始拆分copy,因此strtok再次记录下来,从而破坏了之前的信息
  • 此时strtok > 只了解复制业务,对原始输入一无所知。

主要问题是 strtok 不知道您正在同时做两件事。从它的角度来看,您只是在完成第一个字符串之前开始处理不同的字符串。


可能的解决方案:

  • 使用 strtok_r(如果有)。它不是标准 C(但它是标准 POSIX)。 r 代表可重入
  • 使用您自己的拆分函数(strchr /循环等)
  • 更改您的程序逻辑,以便在完成之前不需要拆分copy input

关于最后一点:

  • 保留一个 char * 数组并用 strtok 填充它,而无需暂停来拆分子令牌。因此每个元素应该是不同的命令
  • 当您完成 ";" 分割后,开始处理每个数组元素

You can't mix multiple strtok calls. Here's what's happening:

  • You start splitting input so strtok takes note and stores stuff internally
  • You take a break from splitting input
    • You start splitting copy so again strtok takes note, thereby destroying the previous info
  • At this point strtok only knows about the copy business and doesn't know anything about the original input.

The main problem is that strtok doesn't know that you're doing two things at the same time. From its point of view, you simply started processing a different string before finishing the first string.


Possible solutions:

  • Use strtok_r if you have it. It's not standard C (but it is standard POSIX). The r stands for reentrant
  • Use your own splitting function (strchr / looping etc)
  • Change your program logic such that you don't need to split copy before finishing with input

About that last point:

  • Keep an array of char * and fill it with strtok without pausing to split sub-tokens. So each element should be a different command
  • When you're done with the ";" split, start processing each of the array elements
何处潇湘 2024-12-27 08:40:32

这个怎么样:

char line[1024];
char *token;
while (1) {
  printf("$ ");
  fgets(line, 1000, stdin);
  token = strtok(line, ";");
  while (token != NULL) {
    printf("%s\n", token);
    token = strtok(NULL, ";");
  }
}

What about this:

char line[1024];
char *token;
while (1) {
  printf("$ ");
  fgets(line, 1000, stdin);
  token = strtok(line, ";");
  while (token != NULL) {
    printf("%s\n", token);
    token = strtok(NULL, ";");
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文