用户在 for 循环中输入的名称在 C 中会覆盖自身

Names being entered by the user during a for loop are overwriting themselves in C

提问人:Carsdan Dvorachek 提问时间:9/29/2023 更新时间:9/29/2023 访问量:42

问:

我正在尝试用 C 编写一个程序,允许用户输入名称,直到他们输入单词“完成”为止。然后它将列出他们输入的所有名称。我知道我应该使用指针数组来实现此目的,然后使用 while 循环继续输入名称,然后在他们输入名称后将指针放入数组中。问题是,一旦我去打印出名字,所有的名字都等于我最后输入的任何名字。

我编写了一个更简单的程序,它做了与我正在做的事情类似的事情,并遇到了同样的问题。这是它的代码。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    char* first;
    char* second;

    for (int i = 0; i < 2; i++)
    {
        char enteredName[20];
        printf("%s", "Please enter a name: ");
        scanf("%s", enteredName);

        if (i == 0)
        {
            first = enteredName;
        }
        else
        {
            second = enteredName;
        }
    }
    printf("First: %s\n", first);
    printf("Second: %s\n", second);
}

该程序的输出为:

Please enter a name: john
Please enter a name: carl
First: carl
Second: carl

我相信正在发生的事情是,第一个和第二个变量都指向记忆中的同一个位置,所以它们只是说同样的事情。我将如何解决此问题,同时仍然使用循环输入任意数量的名称?

C 字符串 指针

评论

0赞 paddy 9/29/2023
正确。您没有复制字符串。您只是在复制指向字符串的指针。最重要的是,当你使用指针时,你所指向的内存甚至不在范围内,因此你有未定义的行为。事实上,你的程序会打印任何“合理”的字符串,这纯粹是运气。
0赞 paddy 9/29/2023
您应该澄清“任意数量的名称”在程序上下文中的真正含义。可能你只需要存储一些最大数量的名字,所以像 2D 数组这样的东西可能很好:哪里是需要的最大数量。或者,您可以使用动态分配( )来创建内存并根据需要复制字符串: 如果你真的想要“任意”计数,你需要一个动态增长的数组(例如):或实现链表。char names[N][20];Nmallocchar *names[N];reallocchar **names;
0赞 paddy 9/29/2023
另一种选择是将所有字符串存储在单个 char 缓冲区中,您可以根据需要增长该缓冲区。在这个程序中,我认为不需要直接索引,因此您可以在遇到缓冲区和输出名称时对其进行迭代。例如,您的缓冲区可能在内存中看起来像"john\0carl\0"

答:

2赞 0___________ 9/29/2023 #1

我相信正在发生的事情是,第一个和第二个 变量指向内存中的同一位置,所以他们只是说 同样的事情。

是的,这是正确的。指针仅保存对象的引用(地址)。您的指针指向(引用)同一个数组。

我将如何解决此问题,同时仍然使用循环输入 任意数量的名字?

您需要将字符串复制到已分配和分配给指针的内存中

        if (i == 0)
        {
            first = malloc(strlen(enteredName) + 1);
            if(first) strcpy(first, enteredName);
        }
        else
        {
            second = malloc(strlen(enteredName) + 1);
            if(second) strcpy(second, enteredName);
        }

评论

0赞 Chris 9/29/2023
或者,使用 .strdup
0赞 Enno 10/1/2023
请注意,strdup 在 C23 之前不是标准的一部分,而是 POSIX 扩展。