我正在尝试使用C创建一个shell,它可以使用分号(;)分隔多个命令。目前我正在尝试使用strtok来分离命令,但我认为我没有正确使用它。我会在不发布完整代码的情况下发布所有信息。 strtok正确使用了吗?
char *semi=";";
else
{
char *token=strtok(str,semi);
if(token != NULL)
{
token=strtok(NULL,semi);
if((childpid = fork()) == 0)
{
if ((execvp(args[0], args))<0)//prints error message when unknown command is used
{
printf("Error! Command not recognized.\n");
}
execvp(args[0],args);
free(args);//deallocate args
exit(0);
}
编辑:根据指示,我删除了最初发布的大部分代码,专注于使用strtok。编译时,临时shell将一次接受一个命令。我正在尝试使用“;”同时分离和运行两个命令。我正确使用strtok吗?如果没有,有替代方案吗?
如果strtok()
返回NULL
,你应该经常检查。我会改变结构如下:
char* semi = ";"; // Your semikolon
char *token = NULL; // Your token string
// ...
// Split first occour of semicolon
token = strtok(str,semi);
if(token == NULL){
perror("No command given ...");
return NULL;
}
do {
// Execute your code here
// fork() etc.
// You should get each line (each semikolon seperated string)
// and it should be stored into token
} while((token = strtok(NULL, semi) != NULL);
我希望,我确实理解你的问题......
但正如我所看到的,你需要再次用空格分割token
,使它们成为char
(argv[]
的execvp()
(第二个参数)的strtok()
数组。这里的问题是,static
内部使用strtok()
(?)变量来存储最后一个位置。所以在循环中使用另一个char *str; // Your string ...
char semi[1] = ";"; // Your semikolon AND space; strtok() will split at both
char *token = NULL; // Your token string
int len = 0;
char *token2;
int argvpos = 0;
// ...
// Split first occour of semicolon
token = strtok(str,semi);
if(token == NULL){
perror("No command given ...");
return EXIT_FAILURE;
}
do {
// save length of token
len = strlen(token);
// Split for blanks to get the arguments
token2 = strtok(token," ");
// Build array of arguments
while(token2 != NULL){
args[argvpos++] = token2;
token2 = strtok(NULL," ");
}
// Do something with token (as command)
// and args (as arguments)
// ...
} while((token = strtok(token+len+1, semi) != NULL);
// In the while condition you add the length to the token; so you get the "old" last position
会“破坏”你的文本。
你可以这样做:
strtok
我认为这不是一个好的解决方案,但它应该有效。我希望,我确实理解你的问题;-)
亲切的问候。
为了正常工作,execvp
应该与while循环一起使用。此外,您不需要运行#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main()
{
char str[] = "ls -1; echo 'hello world'"; // Input commands separated by ';'
// Break the commands string into an array
char *commands[10]; // Array to hold a max of 10 commands
char *semi = ";";
char *token = strtok(str, semi);
int i = 0;
while (token != NULL)
{
commands[i] = token;
++i;
token = strtok(NULL, semi);
}
int numCommands = i; // numCommands is the max number of input commands
// Run each input command in a child process
i = 0;
while (i < numCommands)
{
printf("Command: %s\n", commands[i]);
// Tokenize the command so that it can be run using execvp
char *args[10] = {}; // Array to hold command args
args[0] = strtok(commands[i], " ");
int tokenCounter = 0;
while (args[tokenCounter] != NULL)
{
tokenCounter++;
args[tokenCounter] = strtok(NULL, " ");
}
// Create a child process
int childpid = fork();
// If this is child process, run the command
if (childpid == 0)
{
if ((execvp(args[0], args)) < 0)
{
printf("Error! Command not recognized.\n");
}
exit(0);
}
// If this is the parent, wait for the child to finish
else if (childpid > 0)
{
wait(&childpid);
}
// If the child process could not be created, print an error and exit
else
{
printf("Error: Could not create a child process.\n");
exit(1);
}
++i;
}
return 0;
}
两次。
我使用您的代码创建了一个小示例程序,以演示如何正确使用您的代码:
qazxswpoi