【问题标题】:Strings are being overwritten in a linked list字符串在链表中被覆盖
【发布时间】:2016-01-14 19:34:18
【问题描述】:

我已经查看了本网站上给出的同一主题的先前答案,但我的错误仍然没有发生。该程序是关于学生管理系统的,用户可以在其中动态添加新的学生信息,包括姓名、学位和年龄。当我显示节点的所有信息时,年龄显示正确,但名称和学位被最后一个节点覆盖。

    #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();


}

【问题讨论】:

  • temp-&gt;name= name; --> temp-&gt;name= strdup(name);temp-&gt;name= malloc(strlen(name)+1);strcpy(temp-&gt;name, name);
  • fflush(stdin); MSVC pooh!
  • 以上第一条评论将解决您的姓名问题。但你也有其他问题。例如,一个接一个地添加几个学生后会出现堆栈溢出。那是因为你有这样的流程:MainMenu->addStudent->MainMenu->addStudent->...调用栈越来越深,最终会溢出栈。应该在mainMainMenu 中使用适当的循环。
  • 你知道指针是如何工作的吗?
  • 对于 malloc 使用标准库

标签: c pointers linked-list


【解决方案1】:

让我们一一强调一些问题:

insertAtBeginning 你有

    struct students * temp = (students *)malloc(sizeof(struct students));

不要在 C 中强制返回 malloc,请阅读它以获取更多详细信息。这不是一个致命的错误,但无论如何都是错误的形式。

你还有temp-&gt;name= name;

您正在分配 char[] 作为名称,而不是分配必要的内存并复制您不知道传入名称的生命周期的内容,结果可能是灾难性的。您正在分配一个内存位置,其内容可能会在您不知情的情况下发生变化,并且您存储的名称可以更改以反映这一点。 (或者更糟的是,内存位置将不再保存有效信息) 事实上,这就是每次“添加新学生”时名称都会被覆盖的原因。

为了解决这个问题,您需要:

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-&gt;degree=degree; 你会遇到同样的问题。

更多问题: 正如 Kaylum 所提到的,您在彼此的身体内调用MainMenuAddStudent。 虽然在某些情况下这是可以接受的做法(例如您知道的相互递归最终将由于基本情况而终止),但这并不是您想要的行为。

发生的情况是,每次从另一个函数调用其中一个函数时,您都会在彼此之上创建单独的堆栈帧。 这意味着当你有MainMenu->addStudent->MainMenu->addStudent

原始的MainMenu 堆栈尚未解决,它正在等待所有后续函数调用返回,然后再自行返回。

如果您的程序运行时间足够长,您肯定会溢出堆栈。

最后一件事:尽量避免在不需要时使用全局变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 2013-04-28
    • 2015-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多