0

我正在尝试编写一个类似 shell 的简单接口,它接受用户输入(通过 char)并通过指向指针 * 的指针存储它(正是 argv 的工作原理)。这是我的代码:

char input[100];
char **argvInput;
char ch;
int charLoop = 0;
int wordCount = 0;

argvInput = malloc(25 * sizeof(char *));

while((ch = getc(stdin))) {
    if ((ch == ' ' || ch == '\n') && charLoop != 0) {
        input[charLoop] = '\0';
        argvInput[wordCount] = malloc((charLoop + 1) * sizeof(char));
        argvInput[wordCount] = input;
        charLoop = 0;
        wordCount++;

        if (ch == '\n') {
            break;
        }

    } else if (ch != ' ' && ch != '\n') {
          input[charLoop] = ch;
          charLoop++;
        } else {
            break;
        }
    }

如果我通过 argvInput 循环:

int i = 0;
for (i = 0; i < wordCount; i++)
    printf("Word %i: %s\n", i, argvInput[i]);

argvInput[i] 的所有值都是最后一个输入赋值。所以如果我输入:“快乐的日子快到了”,循环的输出是:

Word 0: soon
Word 1: soon
Word 2: soon
Word 3: soon
Word 4: soon

我不知所措。显然每个循环都覆盖了以前的值,但我盯着屏幕,无法弄清楚为什么......

4

3 回答 3

4

This line is your bane:

    argvInput[wordCount] = input;

Doesn't matter that you allocate new space, if you're going to replace the pointer to it with another one (i.e. input).

Rather, use strncpy to extract parts of the input into argvInput[wordCount].

于 2013-02-22T01:45:36.887 回答
2

argvInput[wordCount] = input;只是使指针argvInput[wordCount]指向内存,input而不是将输入内容复制到新分配的内存中。您应该使用 memcpy 或 strcpy 来更正您的程序。

分配指针后,内存状态如下图所示。分配的内存malloc((charLoop + 1) * sizeof(char));,即图中灰色的内存,您的程序无法再访问,这将导致一些内存泄漏问题。请注意这一点。

在此处输入图像描述

于 2013-02-22T02:01:28.497 回答
0

我建议使用 %p 而不是 %s 打印您的 argvInput 指针,以识别此问题:printf("Word %i: %p\n", i, (void *) argvInput[i]);

你注意到它打印的值是什么?这与 argv 的行为有何不同?尝试打印 argv 的指针:for (size_t x = 0; x < argc; x++) { printf("Word %zu: %p\n", x, (void *) argv[x]); }

既然您已经观察到问题,解释它可能会变得更容易。

此代码分配内存,并将指向该内存的指针存储在 argvInput[wordCount] 中:(argvInput[wordCount] = malloc((charLoop + 1) * sizeof(char));顺便说一下,sizeof char 在 C 中始终为1,因此您不必要地乘以 1)。

此代码用指向输入的指针替换了指向已分配内存的指针:argvInput[wordCount] = input;...因此,您的所有项目都包含指向同一数组的指针:输入,并且您分配的内存泄漏,因为您失去了对它的引用。显然,这是有问题的路线;它不会做你最初认为它会做的事情。

建议您将 malloc 调用替换为 strdup 调用,并删除有问题的行。我不喜欢这个建议,因为 strdup 不在 C 标准中,所以它不需要存在。

strncpy 会起作用,但它不必要地复杂。strcpy 保证也能正常工作,因为分配的目标数组足够大以存储字符串。因此,我建议将有问题的行替换为strcpy(argvInput[wordCount], input);.

另一个没有详细解释的选项是strtok。似乎最好暂时不要探索它,因为它需要对您的代码进行太多修改。

我对这段代码有一点要挑剔:char ch; ch = getc(stdin);是错误的。getc 返回一个 int 是有原因的:任何成功读取的字符都将以 unsigned char 值的形式返回,它不可能是负数。如果 getc 遇到 EOF 或错误,它将返回一个负值。将返回值分配给 ch 后,如何区分错误和成功?

你有没有想过如果第一个字符是''会发生什么?目前,您的代码将跳出循环。如果您的代码要模仿常见的 argv 解析行为,这似乎是一个错误。调整此代码来解决您的问题可能是一个好主意:

for (int c = getc(stdin); c >= 0; c = getc(stdin)) {
    if (c == '\n') {
        /* Terminate your argv array and break out of the loop */
    }
    else if (c != ' ') {
        /* Copy c into input */
    }
    else if (charLoop != 0) {
        /* Allocate argvInput[wordCount] and copy input into it,
         * reset charLoop and increment wordCount */
    }
}
于 2013-02-22T04:41:27.413 回答