我目前正在编写一个原始shell,允许用户输入一些基本命令:ls
,cat
等。我正在从用户那里获取如下输入:ls /home/someUser/someDirectory
并存储这是一个字符数组,比如说input
。我写了一些小函数ls
,cat
等等,这些函数接受一个参数并打印到stdout
预期的结果。
我想知道的是:将input
分解为命令和论证的最佳方法是什么?对于上述示例,我想获得两个不同的块:ls
和/home/someUser/someDirectory
,以便我可以使用什么参数检查用户想要执行的命令。当然,我可以维护指针并检查数组的前几个字符并比较它们,然后在空格后继续处理字符并相应地解析参数,但这将是非常乏味和低效的。有没有更好的方法来做到这一点,可能是一个内置函数?
提前致谢。
答案 0 :(得分:1)
您可以尝试使用strtok
:
#include <string.h>
#include <stdio.h>
int main(){
char example_input[80] = "ls /home/user/directory/file.ext";
const char s[2] = "-";
char *token = strtok(example_input, " ");
/* walk through other tokens */
while( token != NULL ){
printf("%s\n", token );
token = strtok(NULL, s);
}
return(0);
}
转义字符会有些棘手。
如果你只需要将字符串分成命令和参数,这可能有效:
#include <string.h>
#include <stdio.h>
void cmd_ls(const char *arg){
printf("lsing %s\n",arg);
}
void cmd_pwd(const char *arg){
printf("pwding %s\n",arg);
}
int main(){
char example_input[80] = "psdwd /home/user/directory/file.ext";
const char s[2] = "-";
//Find command, assuming it ends at the first space
//Points to first space in string, will eventually point to beginning of
//command
char *command = strchr(example_input, ' ');
//Will point to beginning of argument
char *argument = NULL;
//If command is not NULL, then there is at least one space, so the string has
//the form "<COMMAND> X" where X is either '\0' (string terminator) or another
//character. If the string contains a space, edit it so that there is a
//terminator after the command. If there is an argument, return a pointer to
//its beginning (which may be a space).
if(command!=NULL){
*(command) = '\0'; //Terminate command string
if(*(command+1)!='\0') //If there are argument characters, point to them
argument = command+1;
}
command = example_input; //Point command to beginning of command
//Do I recognise this command?
if(strcmp(command,"ls")==0){
cmd_ls(argument);
} else if(strcmp(command,"pwd")==0) {
cmd_pwd(argument);
} else {
printf("Unrecognised command!\n");
}
return(0);
}
答案 1 :(得分:1)
检查出来
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **split(char *const source, const char *const delimiter)
{
size_t length;
char **list;
size_t count;
char *pointer;
char *token;
void *saved;
if ((source == NULL) || (delimiter == NULL))
return NULL;
list = NULL;
pointer = source;
count = 0;
while ((token = strtok(pointer, delimiter)) != NULL)
{
saved = realloc(list, (1 + count) * sizeof(*list));
if (saved == NULL)
goto abort;
length = strlen(token);
list = saved;
list[count] = malloc(1 + length);
if (list[count] == NULL)
goto abort;
strcpy(list[count], token);
pointer = NULL;
count++;
}
saved = realloc(list, (1 + count) * sizeof(*list));
if (saved == NULL)
return list;
list = saved;
list[count] = NULL;
return list;
abort:
while (count != 0)
free(list[count--]);
free(list);
return NULL;
}
int main()
{
size_t k;
char string[] = "example string with spaces";
char **list;
list = split(string, " ");
if (list == NULL)
return -1;
k = 0;
while (list[k] != NULL)
{
printf("%s\n", list[k]);
free(list[k]);
k++;
}
free(list);
return 0;
}
split函数将返回一个包含标记的char
指针数组,并有一个sentinel NULL
指针,告诉你列表末尾的位置。
答案 2 :(得分:1)
你可以简单地使用scanf。你必须阅读输入,直到你得到一个&#39; \ n&#39;字符。 这样做的代码是:
scanf("%[^\n]", string);
总字符串将存储在数组字符串中。你可以做进一步的字符串处理来提取所需的数据。