c – 程序奇怪地返回到循环的顶部
我想在这个问题前面说我是C的新手并因此很糟糕,所以我提前为任何明显的错误或糟糕的风格道歉.此外,我不知道如何在向您展示我的代码之前介绍问题,所以这里是:
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { int MAX_INPUT_SIZE = 200; volatile int running = 1; while (running) { char input[MAX_INPUT_SIZE]; char *tokens[100]; const char *cmds[] = { "wait","pwd","cd","exit" }; char *cmdargs[100]; printf("shell> "); fgets(input,MAX_INPUT_SIZE,stdin); // remove newline character at end int nl = strlen(input) - 1; if (input[nl] == 'n') { input[nl] = ' '; } // tokenize input string,put each token into an array char *space; space = strtok(input," "); tokens[0] = space; int i = 1; while (space != NULL) { space = strtok(NULL," "); tokens[i] = space; ++i; } // copy tokens after first one into string int noargscheck; if (tokens[1] != NULL) { noargscheck = 0; strcpy((char *)cmdargs,tokens[1]); for (i = 2; tokens[i] != NULL; i++) { strcat((char *)cmdargs," "); strcat((char *)cmdargs,tokens[i]); } } else { noargscheck = 1; } // compare tokens[0] to list of internal commands int isInternal = -1; for (i = 0; i < 4; i++) { if (strcmp(tokens[0],cmds[i]) == 0) { isInternal = i; } } // internal commands char wd[200]; if (isInternal != -1) { switch (isInternal) { case 0: // wait break; case 1: // pwd if (getcwd(wd,sizeof(wd)) == NULL) { perror("getcwd() error!"); } else { printf("%sn",wd); } break; case 2: // cd if (noargscheck) { chdir("/home"); } else if (chdir((const char *)cmdargs) != 0) { perror("cd failed"); } break; case 3: // exit exit(1); break; } } else { // external commands pid_t child_pid; switch (child_pid = fork()) { case -1: perror("Fork failed"); return 1; case 0: // child printf("nHEREn"); // for debugging execvp(tokens[0],cmdargs); break; } } } } 当我使用输入echo hello world运行此代码时,程序在第二个switch语句中以switch(child_pid = fork())成功输入case 0 case,但输出是意外的,如下所示: 输出:(包括在提示符下显示我的输入的一行) 外壳> echo hello world(我的输入) 外壳> (这是我不明白的部分) 这里 外壳> (程序现在等待下一个用户输入的提示) 我无法弄清楚为什么额外的外壳>提示正在打印.任何人都能看到问题吗? 编辑:修复了execvp的第一个参数.从“回声”(这是因为我很傻)改为令牌[0]. 解决方法
当你分叉时,你现在有两个进程.您的孩子将打印HERE消息,然后拨打execvp.您不检查execvp的返回值,因此可能返回错误. cmdargs应该是一个向量 – 也就是说,一个以空指针终止的字符串指针数组.相反,你传递execvp一个字符串.换句话说,它需要一个char * [],这就是cmdargs,但是你之前已经错误地处理了cmdargs.
例如,你说strcpy((char *)cmdargs,tokens [1]);.这会在* cmdargs处放置一个字符串.字符串是一个零或多个非零字符的数组,后跟一个8位宽的ascii NUL: char* cmdargs[] is a double pointer you treat cmdargs as a single pointer and feed it to strcpy cmdargs points to: 'H' 'e' 'l' 'l' 'o' ' ' 但是,这不是execvp想要的. Execvp需要一个向量,看起来有点像这样: char* cmdargs[] is a double pointer cmdargs[0] is a single pointer cmdargs[0] points to: 'H' 'e' 'l' 'l' 'o' ' ' cmdargs[1] points to: 'w' 'o' 'r' 'l' 'd' ' ' cmdargs[2] is a null pointer,indicating that it is the end of the vector 因此,execvp无法找到向量的末尾并失败,返回-1.你没有测试这个,所以子进程继续回到循环的顶部,就像父进程一样,并且两个进程都打印shell>. 编辑:顺便说一句,argv向量中的FIRST字符串应该是正在执行的文件的名称 – 在这种情况下,echo,然后第二个和第三个字符串应该是第一个和第二个’参数’ – 这里你好和世界.这是输入到您调用的程序的argv向量,按照惯例,该向量中的第一个元素是被调用程序的名称.如果忽略该约定,回声将非常混乱. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- c# – 为什么命名空间类型不应该依赖于嵌套的命名空间类型?
- cocos2d-x-3.3rc2-002 cocos里的两段构造
- swift3.0 dispatch_after 延时操作
- 不要过度依赖JQuery(一)
- PostgreSQL 9.4 Released! 18th December 2014
- 基于手淘 flexible 的 Vue 组件:TextScroll -- 文字滚动
- Oracle SQL Developer如何默认为其他用户表?
- postgresql – 在AWS-RDS中创建Postgres事件触发器
- ruby-on-rails – 使用Active Merchant和PayPal时出现SSL错
- 正则表达式的功法大全,做NLP再也不怕搞不定字符串了