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
相关产品推荐
相关产品推荐

