简体   繁体   中英

Why does fgets overwrite seemingly unconnected variables?

I'm working on a small project while learning C, and have stumbled across a problem that's slowly driving me mad. I have a struct which contains pointers to other structs of the same type, and an input array to take in strings from 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)
  {
   ...

However, upon attempting to use fgets to accept input, it will overwrite seemingly unrelated variables.

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

Even when using a variable entirely separate from the structures, the exact same problem occurs.

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

I've been working on this problem for ages and can't find any solutions online, though it's probably just some weird malloc error, does anyone know why this is happening?

When you do this:

pNew->objectName = input;

You're assigning the address of the input array to objectName . You are not making a copy.

Then when you do this:

currentNode->question = input;

You are again assigning the address of input to this field. So now pNew->objectName and currentNode->question both point to the same place , ie input . So anytime input changes it will be reflected when you use either of the variables above.

To make a copy of the string, use strdup :

pNew->objectName = strdup(input);

This dynamically allocates memory for a copy of the string, copies the string to the newly allocated memory, and returns the address of that memory.

Just be sure to call free on each of these objects when you clean up the containing struct.

You are scanning into the same variable all the time, ie into input

You need to allocate new memory for each variable. Like:

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;

An alternative is to use strdup but that isn't part of the standard so it's not supported by all systems.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM