我正在开发一个充当shell解释器的程序,该解释器读取带参数的命令,并创建一个子程序,用execvp()执行命令。我一直在做一些字符串操作来收集char数组,特别是使用*args[]fgets
这是我的密码。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>

#define MAX_LINE 80

int main(void){
    //initialize variables
    char *args[MAX_LINE/2 + 1];
    char input[MAX_LINE];
    //char input[MAX_LINE] = "some sentence unknown"; // <-- this line works fine..

    int counter = 0;
    printf("COMMANDER>");
    fflush(stdout);

    //receive input
    fgets(input,MAX_LINE,stdin);

    //parse input
    char *parser;
    parser = strtok(input," \r\t");

    //parse line
    while(parser != NULL){
                args[counter] = parser;
        counter++;
        parser = strtok(NULL," ");
    }

    //print results
    int i = 0;
    for(i = 0; i < counter + 1;i++){
        printf("1");
        printf(" - %d: %s\n",i,args[i]);
    }

    return 0;
}

这里的问题是输出。当我尝试运行此命令时,会得到以下输出:
COMMANDER>some sentence unknown
1 - 0: some
1 - 1: sentence
1 - 2: unknown

1 - 3: (null)

我的问题是那片空地。我不知道它是从哪里来的,也不知道我做了什么。
据我所知,它可能是字符串末尾的一个字符,或其他字符,但将其传递到strtokasexecvp会创建一个错误,因为它将此空行解释为“”的参数。
有一行我已经注释掉了,它只是execvp(args[0],args)开头的一个字符串赋值。如果使用此赋值而不是main,则程序工作,并且我获得所需的输入:
COMMANDER>some sentence unknown
1 - 0: some
1 - 1: sentence
1 - 2: unknown
1 - 3: (null)

谢谢你的阅读。我的C有点生疏,所以我一个人坚持了几个小时,仍然找不到解决办法。

最佳答案

如果你读到例如this fgets reference的话,你会看到上面写着
如果出现文件结尾或找到换行符,解析将停止,在这种情况下,str将包含该换行符。
[强调我的]
您所看到的“那个空白”是在字符串末尾添加的新行。
然而,在您的代码中有一个更严重的问题。

char *args[MAX_LINE/2 + 1];

定义一个指针数组,但不初始化该数组。在C中,未初始化的局部(和非静态)变量实际上是未初始化的。它们的内容将是不确定的,看起来几乎是随机的。
更具体地说,您碰巧在fgets处得到一个空指针纯粹是运气。
尝试以任何方式使用此指针而不进行初始化将导致undefined behavior
简单的解决方案是显式地将数组初始化为满是空指针:
char *args[MAX_LINE/2 + 1] = { NULL };

以上将“零初始化”所有元素,这对于指针意味着它们将args[counter]

关于c - strtok和fgets的奇数数组行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/52579474/

10-11 15:59