我正在创建一个外壳,并且我已经有一段时间没有使用C了。我已经正确初始化了外壳,但是当我尝试将用户输入与字符串数组进行比较时,却遇到了段错误。我计划在for循环中添加casce语句,以在用户调用每个进程后启动每个进程。由于我一直试图弄清楚如何使用户输入与字符串数组中的值匹配,所以我没有包括这些内容。在调试下,由于它是正确的指针,因此我仅接收该类生成的builtins [j]值的第一个字符。但是我被困住了,并且可以使用一些想法来解释为什么当我输入“ exit”时它没有返回0。谢谢
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
//This code is for creating a basic shell
void init_shell(int num, char *prompt[]){
char s1[] = "-p";
int result;
if(num>1){
result = strcmp(s1, prompt[1]);
if(result==0){
printf("%s>$", prompt[2]);
}else{
printf("308sh>$");
}
}
//printf("%s\n %s\n %s\n %d\n", prompt[0], prompt[1], prompt[2], result);
else{
printf("308sh>$");
}
}
//用于接受用户输入直到关闭的无限循环
int main(int argc, char *argv[]){
const char *builtins[7];
builtins[0] = "exit\n";
builtins[1] = "pid\n";
builtins[2] = "ppid\n";
builtins[3] = "cd\n";
builtins[4] = "pwd\n";
builtins[5] = "set\n";
builtins[6] = "get\n";
char usr_in[]="";
char cmp[]="";
while(1==1){
init_shell(argc, argv);//intial prompt for the shell
fgets(usr_in,100,stdin);
//Check for builtin Commands
int cmds_size = 7;
int j=0;
int res;
for(j; j<cmds_size; j++){
res=strcmp(usr_in, hold);
if(res==0){
printf("Execucting\n");
}
else{
printf("no command\n");
}
}
}
return(0);
}
答案 0 :(得分:0)
这里的问题是,您正在将用户的输入写入一个缓冲区,该缓冲区的大小不足以容纳空终止符以外的任何内容。
char user_in[] = "";
上面的行告诉C编译器您只需要足够的空间来存储[ '\0' ]
,它是一个字节。 C编译器不知道您以后可能会向该缓冲区写入100字节的字符串。
当写入缓冲区时,用户的输入溢出,并将覆盖堆栈中的其他值。由于堆栈中的其他值是指针,因此会发生段错误,因为您正在将字符值写入这些字节,但将它们解释为char指针。
您正在正确地将允许用户输入的大小限制为100个字符,但是您应确保缓冲区足够大以容纳要读取的值:
char user_in[101];
for(int i = 0; i < sizeof(user_in) / sizeof(user_in[0]); i++) {
user_in[i] = 0; // Since this is allocated on the stack *in main*, this
// shouldn't be necessary
}
这里是如何重写主方法的一个示例:
#include <stdio.h>
#include <string.h>
typedef enum { false, true } bool; // If you don't have this
// defined already
int main(int argc, char *argv[]) {
const char *builtins[7];
builtins[0] = "exit\n";
builtins[1] = "pid\n";
builtins[2] = "ppid\n";
builtins[3] = "cd\n";
builtins[4] = "pwd\n";
builtins[5] = "set\n";
builtins[6] = "get\n";
char user_in[101];
for(int i = 0; i < sizeof(user_in) / sizeof(user_in[0]); i++) {
user_in[i] = 0;
}
while(1) {
printf("Enter a command: ");
fgets(user_in, 100, stdin);
bool found = false;
for(int i = 0; i < sizeof(builtins) / sizeof(builtins[0]); i++) {
if (!strcmp(user_in, builtins[i])) {
printf("Found command %s", builtins[i]);
found = true;
break;
}
}
if (!found) {
printf("Didn't find command\n");
}
}
return 0;
}
此外,关于函数init_shell
:您正在检查argc是否大于1,但这仅保证定义了argv[1]
;它不能保证定义了argv[2]
。 (请记住,argc是argv数组的大小,其中第一个元素是正在执行的程序的名称)。您要确保在以自己的方式检查提示标志之前,argc至少为3。
对于您的用例而言,这可能是过高的选择,但是请考虑使用getopt
函数从用户那里获取自定义提示值。有关该方法的文档,请参见http://man7.org/linux/man-pages/man3/getopt.3.html。