加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 程序奇怪地返回到循环的顶部

发布时间:2020-12-16 09:47:32 所属栏目:百科 来源:网络整理
导读:我想在这个问题前面说我是C的新手并因此很糟糕,所以我提前为任何明显的错误或糟糕的风格道歉.此外,我不知道如何在向您展示我的代码之前介绍问题,所以这里是: #include stdio.h#include stdlib.h#include string.hint main(){ int MAX_INPUT_SIZE = 200; vol
我想在这个问题前面说我是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向量,按照惯例,该向量中的第一个元素是被调用程序的名称.如果忽略该约定,回声将非常混乱.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读