Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在自定义shell中处理参数_C_Memory_Exec_Argv - Fatal编程技术网

C 在自定义shell中处理参数

C 在自定义shell中处理参数,c,memory,exec,argv,C,Memory,Exec,Argv,我目前正在开发一个用C实现的shell,用于我希望随着时间的推移构建的类,但在执行我的参数时遇到了问题。我的程序使用getchar()将条目解析到参数数组中,然后使用execvp()执行参数。我遇到的问题是重复输入参数,任何后续较短的参数都会与内存中某个地方的字符连接。下面的例子。我需要使用getchar,这就排除了获取参数的其他方法 //Global Variables char argument[64]; char **argv; int main(int argc, char

我目前正在开发一个用C实现的shell,用于我希望随着时间的推移构建的类,但在执行我的参数时遇到了问题。我的程序使用
getchar()
将条目解析到参数数组中,然后使用
execvp()
执行参数。我遇到的问题是重复输入参数,任何后续较短的参数都会与内存中某个地方的字符连接。下面的例子。我需要使用
getchar
,这就排除了获取参数的其他方法

//Global Variables    
char argument[64];  
char **argv;

int main(int argc, char** argv) {
    mainloop();                      //Loop that calls the commands
    return (EXIT_SUCCESS);
}

void prompt(){                       //Modular prompt
    printf ("?:");
}

void mainloop(){                    //Loop that calls the functions
    while(1){
        prompt();
        argv = (char**)malloc(sizeof(char*)*64);  //allocate memory for argv
        getcommand(argument, argv);
        if((strcmp(argv[0],"exit" )) == 0){  //check for exit
            return 0;
        }
        executecommand();
        printcommand();
        //clearcommand();
        //printcommand();
    }
}

void getcommand(char* argument, char** argv){  //Parser for the command
    int i=0,j=0;
    char c;
    char* token;
    while((c = getchar()) != '\n' ){ //gets char and checks for end of line
        argument[i] = c;
        i++;
    }
    token = strtok(argument, " ,.");  //tokenize the command
    while (token != NULL){ 
        argv[j] = token;   //pass command to array of arguments
        token = strtok(NULL, " ,.");
        j++;
    }
    //argv[j] = "\0";
}

void executecommand(){  //Function to call fork and execute with errors
    pid_t childpid = fork();
    int returnStatus;
    if(childpid == -1){                           //Fail to Fork
        printf("failed to fork");
        exit(1);
    }
    else if(childpid == 0){                      //Child process
        if (execvp(*argv, argv) < 0){
            printf("error executing\n");
            exit(1);
        }
        else{                                   //Execute successful
            printf("executed");
        }
    }
    int c=(int)waitpid(childpid, &returnStatus, 0);
    if (returnStatus == 0)  // Verify child process terminated without error.  
        {
            printf("The child process terminated normally. \n");   
        }

    if (returnStatus == 1)      
        {
            printf("The child process terminated with an error!.\n");    
        }
    //realloc(argv,64);
}

void printcommand(){  //Test function to print arguments
    int i = 0;
    while(argv[i] != NULL){
        printf("Argv%d: %s \n",i, argv[i] );
        i++;
    }
}

/*void clearcommand(){     //Function to clear up the memory, does not work
  int i=0;
  argv[0] = "       \0";
  argv[1] = "       \0";

  }*/

任何短于前一个条目的条目都是如此。我不明白exec为什么在
'\0'
之后继续读取参数,我确信我在这里犯了内存错误。非常感谢您的帮助,我已经在这个问题上纠缠了几天了。

您需要用包含空指针的元素指示
argv
数组的结尾。注释掉的行:

argv[j] = "\0";
应该是:

argv[j] = NULL;
您还需要在
参数
字符串的末尾放置一个空终止符。执行
echo
时,您将得到
l
,因为
参数仍然包含上一个命令行。因此,第一行将
参数设置为:

ls -l
然后用
echo
覆盖前4个字符,使其变为:

echol
因此,全部功能将是:

void getcommand(char* argument, char** argv){  //Parser for the command
    int i=0,j=0;
    char c;
    char* token;
    while((c = getchar()) != '\n' ){ //gets char and checks for end of line
        argument[i] = c;
        i++;
    }
    argument[i] = '\0';
    token = strtok(argument, " ,.");  //tokenize the command
    while (token != NULL){ 
        argv[j] = token;   //pass command to array of arguments
        token = strtok(NULL, " ,.");
        j++;
    }
    argv[j] = NULL;
}
您也可以使用
fgets()
读取一行输入,而不是自己调用
getchar()


您还应该检查输入是否大于
参数的大小

您需要用包含空指针的元素指示
argv
数组的结尾。注释掉的行:

argv[j] = "\0";
应该是:

argv[j] = NULL;
您还需要在
参数
字符串的末尾放置一个空终止符。执行
echo
时,您将得到
l
,因为
参数仍然包含上一个命令行。因此,第一行将
参数设置为:

ls -l
然后用
echo
覆盖前4个字符,使其变为:

echol
因此,全部功能将是:

void getcommand(char* argument, char** argv){  //Parser for the command
    int i=0,j=0;
    char c;
    char* token;
    while((c = getchar()) != '\n' ){ //gets char and checks for end of line
        argument[i] = c;
        i++;
    }
    argument[i] = '\0';
    token = strtok(argument, " ,.");  //tokenize the command
    while (token != NULL){ 
        argv[j] = token;   //pass command to array of arguments
        token = strtok(NULL, " ,.");
        j++;
    }
    argv[j] = NULL;
}
您也可以使用
fgets()
读取一行输入,而不是自己调用
getchar()


您还应该检查输入是否大于
参数的大小

在读取输入行的循环之后,您需要使用NUL字符终止该行

while((c = getchar()) != '\n' ){ //gets char and checks for end of line
    argument[i] = c;
    i++;
}
argument[i] = '\0';  // <<---- terminate the input line
while((c=getchar())!='\n'){//获取字符并检查行尾
参数[i]=c;
i++;
}

参数[i]='\0';// 在读取输入行的循环之后,需要使用NUL字符终止该行

while((c = getchar()) != '\n' ){ //gets char and checks for end of line
    argument[i] = c;
    i++;
}
argument[i] = '\0';  // <<---- terminate the input line
while((c=getchar())!='\n'){//获取字符并检查行尾
参数[i]=c;
i++;
}

参数[i]='\0';//如果你能向我解释为什么使用全局变量…我已经编辑了你的问题。您对“C shell”的引用可能会令人困惑;它通常指现有的
csh
shell。使用原型!不要在C中使用
malloc
&friends!我根据你的建议删除了全局变量,谢谢Keith,我没有意识到这一点!如果你能向我解释为什么使用全局变量…我已经编辑了你的问题。您对“C shell”的引用可能会令人困惑;它通常指现有的
csh
shell。使用原型!不要在C中使用
malloc
&friends!我根据你的建议删除了全局变量,谢谢Keith,我没有意识到这一点!谢谢你这么清楚的解释!我完全忽略了争论这个问题。谢谢你这么清楚的解释!我完全忽略了争论这个问题。