You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言Shell实现:使用strtok解析多命令的用法是否正确?

你的strtok用法确实有问题,我给你捋捋~

首先看你这段代码里的几个明显问题:

  • 第一个命令直接被丢弃了
    你第一次调用strtok(str, semi)已经拿到了分号前的第一个命令,但紧接着又调用token=strtok(NULL, semi),直接跳过这个命令去拿第二个,等于完全没处理第一个命令,这肯定不是你想要的效果对吧?

  • 没有遍历所有命令
    strtok要处理所有分号分隔的命令,得用循环结构才行。你现在的写法只能拿到前两个命令,后面的都会被漏掉。正确的遍历方式应该是先拿到第一个token,然后循环拿剩下的,直到token为NULL:

    char *token = strtok(str, semi);
    while (token != NULL) {
        // 处理当前命令
        token = strtok(NULL, semi);
    }
    
  • token和execvp的args完全没关联
    你代码里直接用execvp(args[0], args),但这里的args根本没从你拆分出来的token里提取参数啊?每个拆分出来的命令字符串(比如ls -l)还需要进一步拆分成参数数组,才能传给execvp执行。

  • 额外提醒:strtok会修改原字符串
    如果你的str是字符串字面量(比如char *str = "ls;pwd"),那调用strtok会触发未定义行为,因为字面量是只读内存区域。你得把字符串拷贝到可写的缓冲区里,比如用strdup或者字符数组存储。

给你一个简化的修正示例,你可以参考下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

// 辅助函数:把命令字符串拆分成参数数组
char **split_args(char *cmd) {
    int bufsize = 64;
    int position = 0;
    char **args = malloc(bufsize * sizeof(char*));
    char *token;

    if (!args) {
        perror("malloc failed");
        exit(EXIT_FAILURE);
    }

    // 按空格、制表符、换行符拆分参数
    token = strtok(cmd, " \t\n");
    while (token != NULL) {
        args[position] = token;
        position++;

        // 缓冲区不够时扩容
        if (position >= bufsize) {
            bufsize += 64;
            args = realloc(args, bufsize * sizeof(char*));
            if (!args) {
                perror("realloc failed");
                exit(EXIT_FAILURE);
            }
        }

        token = strtok(NULL, " \t\n");
    }
    args[position] = NULL; // execvp需要以NULL结尾的参数数组
    return args;
}

int main() {
    char input[1024] = "ls -l;pwd;echo hello world"; // 示例输入
    char *semi = ";";
    char *token = strtok(input, semi);

    while (token != NULL) {
        pid_t childpid = fork();
        if (childpid == 0) {
            // 子进程:拆分参数并执行命令
            char **args = split_args(token);
            if (execvp(args[0], args) < 0) {
                perror("unknown command");
                exit(EXIT_FAILURE);
            }
        } else if (childpid < 0) {
            perror("fork failed");
        } else {
            // 父进程等待子进程执行完成
            wait(NULL);
        }
        token = strtok(NULL, semi);
    }

    return 0;
}

内容的提问来源于stack exchange,提问作者Shinrabansho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:18:06