我已经查看了本网站上先前给出的同一主题的答案,但我的错误仍然没有消失。该程序是关于学生管理系统的,用户可以在其中动态添加新的学生信息,包括姓名、学位和年龄。当我显示节点的所有信息时,年龄显示正确,但名称和程度被最后一个节点覆盖。
#pragma warning(disable: 4996)
#include <stdio.h>
#include <conio.h>
#include <malloc.h>
#include <Windows.h>
struct students{
char *name;
int age;
char *degree;
struct students* next;
};
int TotalStudents = 0;
struct students* ptrToHead;
void insertAtBeginning(char name[], int age, char degree[]){
struct students * temp = (students *)malloc(sizeof(struct students));
temp->name= name;
temp->age = age;
temp->degree=degree;
temp->next = NULL;
if (ptrToHead != NULL)
{
temp->next = ptrToHead;
}
ptrToHead = temp;
//printf("%s\n%d\n%s", temp->name, temp->age, temp->degree);
}
void print(){
struct students* temp = ptrToHead;
printf("List of Students: ");
while (temp != NULL){
printf("\nStudent's Name: %s", temp->name);
printf("\nStudent's Age: %d", temp->age);
printf("\nStudent's Degree: %s", temp->degree);
printf("\nEND - OF - STUDENT");
temp = temp->next;
}
printf("\n");
}
void MainMenu();
void addStudent();
int main(){
MainMenu();
//students * temp= (students *)malloc(sizeof(students));
//temp->age = 22;
//temp->degree = "Software Engineering";
//temp->name = "Fahad Bin Saleem";
//temp->next = NULL;
//ptrToHead = temp;
//
//printf("Age: %d\n", ptrToHead->age);
//printf("Name: %s\n", ptrToHead->name);
//printf("Degree: %s\n", ptrToHead->degree);
//temp = (students *)malloc(sizeof(students));
//temp->age = 19;
//temp->degree = "Electrical Engineering";
//temp->name = "Rafay Hayat Ali";
//temp->next = NULL;
//students * temp1 = ptrToHead;
//while (temp1->next != NULL){
// temp1 = temp1->next;
//}
//temp1->next = temp;
//
_getch();
return 0;
}
void MainMenu(){
int choice;
printf("Welcome to Student Information Center!\n\n");
char* mainmenu[] = { "Display All Students", "Add A Student" };
for (int i = 0; i < 2; i++){
printf("%d: %s\n", i + 1, mainmenu[i]);
}
printf("\n\nEnter Your Choice: ");
scanf_s(" %d", &choice);
if (choice == 2){
addStudent();
}
if (choice == 1){
print();
}
}
void addStudent(){
int NumberOfStudents;
int choiceOfAdding;
char tempName[40];
char tempDegree[40];
int tempAge;
system("cls");
ptrToHead = NULL;
for (int i = 0; i < 15; i++){
printf(" ");
}
printf("**ADD A STUDENT**");
printf("\n\nHow many students do you want to add? Enter Choice: ");
scanf_s(" %d", &NumberOfStudents);
printf("\n\n");
for (int i = 0; i < NumberOfStudents; i++){
printf("\n\n");
printf("Enter Student's Name: ");
fflush(stdin);
gets_s(tempName, 40);
printf("Enter Student's Age: ");
scanf_s(" %d", &tempAge);
printf("Enter Student's Degree: ");
fflush(stdin);
gets_s(tempDegree, 40);
//insert(tempName, tempAge, tempAgeDegree);
//printf("Where Do You Want To Add This Student?\n\n1: At The Beginning\n\n2: At A Position N\n\n3: At The End");
//scanf_s(" %d", &choiceOfAdding);
fflush(stdin);
TotalStudents++;
insertAtBeginning(tempName, tempAge, tempDegree);
/*if (choiceOfAdding == 1){
}*/
printf("\n\n");
}
MainMenu();
}
最佳答案
让我们一一强调一些问题:
在 insertAtBeginning
中,您有
struct students * temp = (students *)malloc(sizeof(struct students));
不要在 C 中强制转换 malloc 的返回值,请阅读它以获取更多详细信息。这不是一个 fatal error ,但无论如何都是不好的形式。
再往下你有temp->name= name;
您分配一个 char[]
作为名称,而不是分配必要的内存并复制您不知道传入名称的生命周期的内容,结果可能是灾难性的。您正在分配一个内存位置,其内容可能会在您不知情的情况下发生变化,并且您存储的名称可能会发生变化以反射(reflect)这一点。 (或更糟糕的是,内存位置将不再保存有效信息)
事实上,这就是每次“添加新学生”时名称都会被覆盖的原因。
为了解决这个问题,您需要:
temp->name= malloc(strlen(name)+1);
//allocate memory and keep 1 extra for \0
strcpy(temp->name, name);
//copy the value of the parameter into the memory location we just allocated
对于 temp-> Degree= Degree;
你也会遇到同样的问题。
更多问题:
正如 Kaylum 提到的,您在彼此的体内调用 MainMenu
和 AddStudent
。
虽然在某些情况下这是可以接受的做法(例如您知道最终会由于基本情况而终止的相互递归),但这不是您想要的行为。
发生的情况是,每次从另一个函数调用其中一个函数时,您都会在彼此之上创建单独的堆栈帧。
这意味着当您有 MainMenu
->addStudent
->MainMenu
->addStudent
原始 MainMenu
堆栈尚未解析,正在等待所有后续函数调用返回,然后再返回。
如果你的程序运行足够长的时间,你肯定会溢出堆栈。
最后一件事:在不需要时尽量避免使用全局变量。
关于c - 链表中的字符串被覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34798145/