我在学习C的同时从事一个小项目,偶然发现了一个让我疯狂的问题。 我有一个结构,其中包含指向同一类型的其他结构的指针,以及一个从stdin获取字符串的输入数组
typedef struct Node
{
char *objectName;
char *question;
struct Node *yesPtr;
struct Node *noPtr;
}Node;
int main(int argc, char **argv)
{
Node *rootNode = initialise(LAUNCH_TYPE);
Node *currentNode = rootNode;
int quit = 0;
char input[INPUT_SIZE];
while (quit == 0)
{
...
但是,在尝试使用fgets接受输入时,它将覆盖看似无关的变量。
fgets(input,INPUT_SIZE,stdin);
input[strcspn(input, "\n")] = '\0';
pNew->objectName = input; //Code works here, input behaves as expected..
printf(pNew->objectName); //..and this is correct
printf("Please type a question!\n");
fgets(input,INPUT_SIZE,stdin); //However, this line overwrites pNew->objectName to its input
input[strcspn(input, "\n")] = '\0';
currentNode->question = input; //While this line still functions as expected
printf(pNew->objectName); //This will now (incorrectly) print out the string that had just been entered
即使使用完全独立于结构的变量,也会出现完全相同的问题。
fgets(input,INPUT_SIZE,stdin);
input[strcspn(input, "\n")] = '\0';
char *newObject = input; //Even when replacing the pointer with another variable
printf(newObject);
printf("Please type a question!\n");
fgets(input,INPUT_SIZE,stdin); //This line will overwrite the new variable too
input[strcspn(input, "\n")] = '\0';
currentNode->question = input;
pNew->objectName = newObject;
printf(pNew->objectName); //And results in the same problem
我已经解决了这个问题多年,并且无法在线找到任何解决方案,虽然它可能只是一些奇怪的malloc错误,有谁知道为什么会发生这种情况?
答案 0 :(得分:1)
执行此操作时:
pNew->objectName = input;
您已将input
数组的地址指定给objectName
。您不制作副本。
然后当你这样做时:
currentNode->question = input;
您再次将input
的地址分配给此字段。所以现在pNew->objectName
和currentNode->question
都指向同一个地方,即input
。因此,当您使用上述任一变量时,任何时候input
更改都会反映出来。
要制作字符串的副本,请使用strdup
:
pNew->objectName = strdup(input);
这为字符串的副本动态分配内存,将字符串复制到新分配的内存,并返回该内存的地址。
在清理包含的结构时,请确保在每个对象上调用free
。
答案 1 :(得分:1)
您一直在扫描同一个变量,即进入input
您需要为每个变量分配新内存。像:
fgets(input,INPUT_SIZE,stdin);
input[strcspn(input, "\n")] = '\0';
char* tmp = malloc(strlen(input) + 1); // Allocate memory - Plus 1 for the string termination
if (tmp == NULL)
{
// ups... out of mem
exit(1);
}
strcpy(tmp, input);
pNew->objectName = tmp;
另一种方法是使用strdup
,但这不是标准的一部分,因此并非所有系统都支持它。