有一种“方法”可能有效。事实上,我想到了两个。
两者都依赖于空白字符(在普通英语、'\n'、' '和'\t')分隔参数 ,我认为这已经足够了。
1
首先,相对简单的一个 - 使用 main(int argc,char *argv[]) 作为大多数 CLI 程序。
然后,运行if()s/else if()s 的长字符串,通过测试strcmp(argv[x],expected_command) 是否返回0,检查输入字符串是否匹配有效参数。
您可能还没有学会如何使用它,它可能看起来很吓人,但如果您已经熟悉 string.h、数组和指针,它很容易。
Google 搜索和 YouTube 视频可能会有所帮助,而且不会超过 20 分钟左右。
2
其次,如果您的程序带有真正的 CLU 'UI',并且程序处于循环中并且不会在生成输出后立即终止 - 不像 cat 或 ls ,那么您将输入'command' 字符串在程序中。
这意味着除了if-ed strcmp()s 和之前,您还必须确保您安全地使用scanf() 进行输入,并且您可以将多个字符串作为输入,因为您讨论像look DIRECTION 这样的子参数。
我自己(过去)这样做的方式如下:
1. 声明一个命令字符串,例如char cmd[21] = ""; 和(可选)将其初始化为空,因为读取的是未初始化的字符串是 UB(并且用户可能输入 EOF)。
2.声明一个函数(为了方便)来检查scanf()这样说:
int handle_scanf(int returned,int expected){
if(returned==expected)
return 0;
if(returned==EOF){
puts("\n Error : Input Terminated Immaturely.");
/* you may alternatively do perror() but then
will have to deal with resetting errno=0 and
including errno.h */
return -1;
}
else{
puts("\n Error : Insufficient Input.");
return -2;
}
}
可以用作:if(handle_scanf(scanf(xyz,&xyz),1)==0) {...}
由于 scanf() 返回“采取”的项目数(与预期格式字符串匹配并因此被保存的项目),这里只有 1 个预期参数。
3. 声明一个函数(为了方便)清除/刷新标准输入,以便在输入中留下不必要的输入时stream ,(如果不处理,将被传递到下一个接受输入的地方)它可以被“吃掉”。
我就是这样做的:
void eat()
{
int eat; while ((eat = getchar()) != '\n' && eat != EOF);
}
基本上清除输入直到读取换行符或EOF。由于 '\n' 和 EOF 代表 End Of Line 和 End Of File ,并且现代 I/O 是行缓冲并通过 stdin 文件执行的,因此在读取它们时停止是有意义的。
EDIT:您也可以使用宏,以获得更好的性能。
4. 打印提示并接受输入,如下所示:
fputs("\n >>> ",stdout);
int check = handle_scanf(scanf("%20s",cmd),1);
注意我在这里做了什么?
"%20s" 做了两件事 - 停止缓冲区溢出(因为超过 20 个字符不会被扫描到 cmd)并且在遇到空白字符时也会停止扫描。所以,你的主要命令必须是一个词。
5. 检查命令是否有效.
这将通过上述检查 strcmp(cmd,"expected_cmd")==0 的列表来完成,以检查 所有 可能的预期命令。
如果没有匹配,使用else,显示错误消息并调用eat();(可以忽略无效命令的参数)但仅限 if(check != -1)。
如果是check==-1,这可能意味着用户已经向程序发送了一个EOF信号,在这种情况下,在循环中调用eat()将导致一个无限循环显示错误消息,你不想要的东西。
6. 如果匹配,吸收分隔字符的空格,然后将scanf()放入一个字符数组(如果用户输入,look DIRECTION,@ 987654355@ 仍在输入流中,现在只会保存到所述 char 数组中)。可以这样做:
#define SOME_SIZE 100 // use an appropriate size
if(strcmp(cmd,"look")==0 && check==0){ // do if(check==0) before these ifs, done here just for my convenience)
getchar(); // absorb whitespace seperator
char strbuff[SOME_SIZE] = ""; // string buffer of appropriate size
if(handle_scanf(scanf("%99[^\n]",strbuff),1)==0){
eat();
/* look at DIRECTION :) */
}
// handle_scanf() generated appropriate error msg if it doesn't return 0
}
结果
总而言之,这段代码主要安全地处理scanf,并且确实可以以用户只会键入的方式使用,比如:
$ ./myprogram
>>> look DIRECTION
# output
>>> | #cursor
如果这一切都在main() 内的一个大循环中完成。
结论
实际上,如果您的程序足够复杂,您最终可能需要同时使用两者:)
我希望我稍微延迟的回答能有所帮助:)
如有任何不准确或遗漏的细节,请发表评论,我会尽快回复您