我有一个链表,我正在尝试插入一个新节点,这似乎是成功插入我希望它去的节点,但变量一直是NULL。有人能指出我导致这种情况发生的地方吗?
这是打印和插入方法。
void printList(node *head)
{
node *p;
p = head;
if(p->next == NULL)
printf("No stops currently in the tour.");
else
{
while(p->next != NULL)
{
printf("Tour Stop: %s - Description: %s\n", p->name, p->name);
p = p->next;
}
}
}
void insertInOrder(node *head, node *newNode)
{
printf("What is the stop you want the new stop to come after? Type 'end' to insert at the end of the tour.");
char key[100];
scanf("%s", &key);
getchar();
node *p;
p = head->next;
if(head->next == NULL)
head->next = newNode;
else if(key == "end")
{
while(p->next != NULL)
p = p->next;
p->next = newNode;
printf("\nAT 57, newNode->info = %s and newNode->name = %s", newNode->info, newNode->name);
}
else
{
while(strcmp(p->name, key) != 0)
{
if(p->next == NULL)
{
printf("Couldn't find the tour stop you requested, inserting at end of tour.");
break;
}
p = p->next;
}
p->next = newNode;
}
这是我用来传递给插入方法的createNewNode方法
node* createNewNode()
{
node *newNode;
newNode = malloc(sizeof(struct node));
printf("Enter the name of the new tour stop.\n");
char newName[100];
fgets(newName, sizeof(newName), stdin);
newNode->name = newName;
printf("Enter information about the tour stop. Max number of characters you can enter is 1000.\n");
char newDescription[1000];
newNode->info = newDescription;
fgets(newDescription, sizeof(newDescription), stdin);
return newNode;
}
答案 0 :(得分:3)
您没有将字符串复制到结构中。您只是将指针复制到createNewNode()
:
char newName[100];
fgets(newName, sizeof(newName), stdin);
newNode->name = newName;
这意味着当您稍后访问该存储的指针时,未定义的行为,因为它不再有效。
您需要在结构中包含字符空间,并复制(或只读取)字符串,以便在节点存在时保持分配。
答案 1 :(得分:1)
这段代码存在很多问题,我甚至不知道从哪里开始。
printf("What is the stop you want the new stop to come after? Type 'end' to insert at the end of the tour.");
char key[100];
scanf("%s", &key);
getchar();
如果您绝对需要使用scanf(建议不要)读取字符串,则应在'%s'格式说明符之前添加要读取的最大字符,如scanf(“%99s”,& key)。您应该读取99个字符而不是100个字符,以便空终止不会溢出您的数组。
else if(key == "end")
{
//code
}
这里不是将key的内容与const char *“end”进行比较,而只是将数组 key 的地址与const char *“end”的地址进行比较,你应该使用 而是strcmp。 (甚至更好strncmp)
node* createNewNode()
{
node *newNode;
newNode = malloc(sizeof(struct node));
printf("Enter the name of the new tour stop.\n");
char newName[100];
fgets(newName, sizeof(newName), stdin);
newNode->name = newName;
printf("Enter information about the tour stop. Max number of characters you can enter is 1000.\n");
char newDescription[1000];
newNode->info = newDescription;
fgets(newDescription, sizeof(newDescription), stdin);
return newNode;
}
此处新节点的名称和信息指针将指向在返回 createNewNode 的调用后释放的内存。这是未定义的行为,您的程序可能会出现段错或更糟。
您应该将读取缓冲区复制到堆上分配的新缓冲区,并将指针设置为指向它们,或者首先在堆上分配缓冲区。
int newDescriptionLength = strlen(newDescription) + 1; //plus 1 for null termination
char* newDescriptionCopy = malloc(newDescriptionLength);
strncpy(newDescriptionCopy, newDescription, newDescriptionLength);
newNode->info = newDescriptionCopy;
strncpy将确保您的newDescriptionCopy字符串在之后以空值终止 已复制源字符串newDescription的所有字符。
释放节点时应考虑分配的缓冲区。
另外,你应该用fgets读取一个字符,因为提供了准确的计数 允许的字符不会为null终止你的字符串。
您应该在深入研究问题之前解决这些问题,因为您的程序充满了未定义的行为,并且在调试过程中做出假设是不安全的。
答案 2 :(得分:0)
从我所看到的你的代码(你没有打印调用函数或链表的init,如果有的话),看起来你永远不会检查第一个元素(即头部)。所以当列表完成时为空,那么head将指向NULL。因此,使用您的打印功能作为示例,您应该:
void printList(node *head)
{
node *p;
p = head;
// Check if the list contains anything
if (p == NULL)
{
printf("List is empty");
}
else
{
printf("Tour Stop: %s - Description: %s\n", p->name, p->name); // print first/head element
// Continue while there are more elements
while(p->next != NULL)
{
printf("Tour Stop: %s - Description: %s\n", p->name, p->name);
p = p->next;
}
}
}
你的插入函数可能是一样的,所以你永远不要插入任何东西吗?
注意:放松在他的回答中也有一个非常有效的观点