C++ - 链表字符串重复

C++ - Linked list strings are repeating

本文关键字:字符串 链表 C++      更新时间:2023-10-16

UPDATE:这是C++,不是C

我正在用 C 语言创建一个学生链表。问题是当我运行它时:

Input:
ID: 1
Name: John
Mark: 10
ID: 2
Name: Jane
Mark: 6
ID: 0 /*to end the list*/
Output:
1   Jane   10
2   Jane   6

您可以看到ID 1正在重复ID 2中的名称,如果我有更多ID 例如5 ID,它将重复ID 5中的名称

这是我的代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student {
int ID;
char *Name;
float Mark;
};
struct ttNode {
struct student data;
struct ttNode *pNext;
};
typedef ttNode NODE;
struct ttList {
NODE *pHead, *pTail;
};
typedef ttList LIST;
void CreateEmptyList (LIST &list) {
list.pHead = list.pTail = NULL;
}
int IsEmptyList(LIST list) {
if((list.pHead==NULL) && (list.pTail==NULL)) return 1;
return 0;
}
void AddHead (LIST &list, NODE *pNew) {
if(IsEmptyList(list))
{
list.pHead = list.pTail = pNew;
}
else
{
pNew -> pNext = list.pHead;
list.pHead = pNew;
}
}
void AddTail (LIST &list, NODE *pNew) {
if (IsEmptyList(list)) {
list.pHead = list.pTail = pNew;
}
else
{
list.pTail -> pNext = pNew;
list.pTail = pNew;
}
}
NODE *CreateNode (int id, char *name, float mark) {
NODE *p;
p = (NODE*) malloc(sizeof(NODE));
if(p==NULL)
{
printf("Allocation error!");
exit(0);
}
p->data.ID = id;
p->data.Name = name;
p->data.Mark = mark;
p->pNext=NULL;
return p;
}
void Input_AddHead (LIST &list) {
int id;
char *name;
float mark;
NODE *pNew;
CreateEmptyList(list);
do {
fflush(NULL);
printf("Input ID (0 to end): ");
scanf("%d", &id);
if(id == 0)
break;
printf("Input name: ");
scanf("%s", name);
printf("Input mark: ");
scanf("%f", &mark);
printf("n");
pNew=CreateNode(id,name,mark);
AddHead(list,pNew);
} while (1);
}
void Output(LIST list)
{
NODE *p = list.pHead;
while(p)
{
printf("t%d t%s t%fn ", p->data.ID, p->data.Name, p->data.Mark);
p = p -> pNext;
}
}
int main ()
{
LIST list;
Input_AddHead(list);
Output(list);
return 0;
}

Xcode 保持警告scanf("%s", name);名称在这里是未初始化的 如果我通过char *name;更改为char *name = nullptr;来遵循 Xcode,则程序在输入名称时崩溃。那么这段代码有什么问题。

这是因为列表中的name指针被指定为指针。

p->data.Name = name;

因此,p->data.Name将始终指向name中的更新值。

请尝试如下所示。

p->data.Name = strdup(name);

其中 strdup 计算所需的空间并分配内存 动态并复制输入字符串并返回新的 分配的指针。另请注意,strdup不是标准的CC++,因此它不可移植。

如果不想使用strdup请将内存分配给动态p->data.Name并使用strcpy进行复制。


添加以回答代码的主要问题。

void Input_AddHead (LIST &list) {
.....
char *name;
.....
do {
.....
printf("Input name: ");
scanf("%s", name);
......              
pNew=CreateNode(id,name,mark);
.....
} while (1);
}

如您所见,您的name未分配,引用它将导致未定义的行为。

scanf("%s", name);

因此,我建议您更改如下。

void Input_AddHead (LIST &list) {
.....
char *name;
.....
do {
.....
char line[100];
printf("Input name: ");
scanf("%s",line);
......              
name = strdup(line);
pNew=CreateNode(id,name,mark);
.....
} while (1);
}

int 在这种情况下,指针分配如下CreateNode应该按原样工作。 无需额外分配p->data.Name.

p->data.Name = name;

createNode函数中,语句p->data.Name = name;不复制name。要复制name,您必须使用strcpy库函数。

char * strcpy ( char * destination, const char * source );

在此之前,您还必须使用mallocname分配内存。分配的内存应该是您传递给它的namesizeof

乍一看问题似乎是

p->data.Name = name;

这应该作为快速修复

p->data.Name = strdup(name);

但是使用mallocstrcpy总是更好

还有很多其他errors我仍然可以看到,但我会把它留给你

您似乎将c++ referencesc-pointers混合在一起,我不确定您的代码是否正在编译,如果是,则非常怀疑,它可能仍然是错误的。

程序具有未定义的行为,name调用函数时未初始化scanf

void Input_AddHead ( // current codee
...
printf("Input name: ");
scanf("%s", name);   // <--- name is uninitialized
printf("Input mark: ");

您应该创建临时缓冲区,在此缓冲区中输入一个字符串,然后复制字符串并将其传递给创建新节点的函数:

void Input_AddHead ( // ... fix
int id;
float mark;
NODE *pNew;
CreateEmptyList(list);
do {
fflush(NULL);
printf("Input ID (0 to end): ");
scanf("%d", &id);
if(id == 0)
break;
printf("Input name: ");
char buf[80];     // create temp buffer
scanf("%s", buf); // enter data
char* name = (char*)malloc(strlen(buf)+1); // make copy
strcpy(name,buf);                          // of string 
printf("Input mark: ");
scanf("%f", &mark);
printf("n");
pNew=CreateNode(id,name,mark); // you can pass pointer to unique string