更新:这是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%f\n ", 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,则程序在输入名称时崩溃。那么这段代码有什么问题。
答案 0 :(得分:1)
在npm install ng2-meta@5.0.0
函数中,语句createNode
不复制p->data.Name = name;
。要复制name
,您将必须使用name
库函数。
strcpy
在此之前,您还必须使用char * strcpy ( char * destination, const char * source );
为name
分配内存。并且分配的内存应该是您传递给它的malloc
和sizeof
。
答案 1 :(得分:1)
这是因为您在列表中的name
指针被分配为指针。
p->data.Name = name;
因此p->data.Name
将始终指向name
中的更新值。
尝试如下操作。
p->data.Name = strdup(name);
strdup在其中计算所需的空间并分配内存 动态地复制输入字符串并返回新的 分配的指针。另外请注意,
strdup
不是标准的C
或C++
,因此它不是可移植的。
如果您不想使用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;
答案 2 :(得分:1)
首先看问题似乎是
p->data.Name = name;
这应该作为快速解决方法
p->data.Name = strdup(name);
但是使用malloc
和strcpy
还有很多其他errors
仍然可以看到,但我会留给你
您似乎正在将c++ references
与c-pointers
混合使用,而且我不确定您的代码是否还在编译,如果它是高度怀疑的话,可能仍然错误的。
答案 3 :(得分:1)
您的程序具有未定义的行为,当您调用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