2016-01-14 4 views
1

Я уже проверил предыдущие ответы на ту же тему, данный на этом веб-сайте, но по-прежнему моя ошибка не идет. Программа посвящена системе управления студентами, в которой пользователи динамически добавляют новую информацию о студенте, которая включает имя, возраст и возраст. Когда я показываю всю информацию о узлах, возраст отображается правильно, но имя и степень перезаписываются последним узлом.Строки переписываются в связанном списке

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


} 
+3

'temp-> name = name;' -> 'temp-> name = strdup (name);' или 'temp-> name = malloc (strlen (name) +1); strcpy (temp-> name , name); ' – BLUEPIXY

+0

' fflush (stdin); 'MSVC pooh! –

+2

Выше первого комментария разрешит вашу проблему с именем. Но у вас есть и другие проблемы. Например, вы получите переполнение стека после добавления нескольких учеников один за другим. Это потому, что у вас есть этот поток: 'MainMenu'->' addStudent'-> 'MainMenu'->' addStudent' -> ... Стек вызова становится все глубже и глубже и, в конечном счете, переполняет стек. Должен использовать правильный цикл в 'main' или' MainMenu'. – kaylum

ответ

2

Позволяет выделить некоторые вопросы один за другим:

В insertAtBeginning у вас есть

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

Не отвергни возвращение таНос в C, читать на нем для более подробной информации. Это не фатальная ошибка здесь, но плохая форма.

дальше у вас есть temp->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->degree=degree; вы будете иметь один и тот же вопрос.

Другие проблемы: Как упоминалось в Kaylum, вы звоните MainMenu и AddStudent внутри тел друг друга. Хотя в некоторых случаях это приемлемая практика (например, взаимная рекурсия, которую вы знаете, в конечном итоге закончится из-за базового случая). Это не то поведение, которое вы хотите здесь.

Что происходит, вы создаете отдельные кадры стека друг на друга каждый раз, когда вы вызываете одну из этих функций из другой. Это означает, что если у вас есть MainMenu ->addStudent ->MainMenu ->addStudent

оригинальный MainMenu стек до сих пор не решен, и ждет всех последующих вызовов функций, чтобы вернуться, прежде чем он сам возвращается.

Если ваша программа работает достаточно долго, вы наверняка переполните стек.

Последнее: старайтесь избегать использования глобальных переменных, когда вам это не нужно.

Смежные вопросы