2016-03-12 199 views
2

我在將數據添加到鏈接列表時遇到問題。這段代碼基本上是試圖先將新的課程名稱插入到結構中,然後將結構插入到鏈接列表中,然後循環重複。用戶負責插入新的課程名稱。被覆蓋的鏈接列表數據

現在的問題是,當用戶使用scanf進入添加課程操作時,它總是覆蓋鏈接列表中現有的課程名稱並添加到其中。

這是從控制檯應用程序的輸入和輸出:

Enter operation: 1 
Add Course: asdgvsdrgf 
Enter operation: 1 
Add Course: ehtyerdc 
Enter operation: 1 
Add Course: nbcnvbergt 
Enter operation: 5 (// Just Print course name in the linked list) 
Current enrolments: 
nbcnvbergt 
nbcnvbergt 
nbcnvbergt 

Current enrolments: 

(改變.h文件是不可能的,因爲它是從大學轉讓的要求)

這裏是c和h以下文件附:

bst.h

#pragma once 

#include <stdio.h> 
#include <stdlib.h> 

typedef struct bstNode { 
long student_id; 
struct bstNode *left; 
struct bstNode *right; 
} *BST; 

courselist.h

#include <stdio.h> 
#include <stdlib.h> 
#include "bst.h" 

typedef struct course { 
char *name; 
BST students; 
} Course; 

typedef struct courseNode { 
Course data; 
struct courseNode *next; 
} *CourseList; 

bst.c

(not yet written) 

courselist.c

#include <stdio.h> 
#include "courselist.h" 
#include <stdlib.h> 

void print_course_and_num_students(CourseList *self) { 
CourseList current = *self; 
while (current != NULL) 
{ 
    printf("%s\n", (current->data).name); 
    current = current->next; 
} 
printf("\n"); 
} 

void insert_course_at_front(CourseList *self, Course data) { 
CourseList newNode = (CourseList)malloc(sizeof(struct courseNode)); 

if (*self == NULL) 
{ 
    *self = newNode; 
    (*self)->data = data; 
    (*self)->next = NULL; 
    return; 
} 

    newNode->data = data; 
    newNode->next = *self; 
    *self = newNode; 
} 

的main.c

#include <stdio.h> 
#include "courselist.h" 
#include "bst.h" 
#include <stdlib.h> 
#include <cstdbool> 

#define MAX_LEN 100 

void main() 
{ 
CourseList my_course = (CourseList)malloc(sizeof(struct courseNode)); 
my_course = NULL; 
Course my_list; 
(&my_list)->name = (char *)malloc(100 * sizeof(char)); 

bool program_quit = false; 
int input_op; 

char *insert_course_word; 
insert_course_word = (char *)malloc(100 * sizeof(char)); 

char *delete_course_word; 
delete_course_word = (char *)malloc(100 * sizeof(char)); 

do 
{ 
    printf("Enter operation: "); 
    scanf("%d", &input_op); 

    switch (input_op) 
    { 
    case 0:   // Quit 
     program_quit = true; 
     break; 

    case 1:   // Add Course 
     program_quit = false; 
     printf("Add Course: "); 
     scanf("%s", (&my_list)->name); 

     //(&my_list)->name = (insert_course_word); 

     insert_course_at_front(&my_course, my_list); 
     break; 

    case 2:   // Remove Course 
     program_quit = false; 
     printf("Remove Course: "); 
     scanf("%s", delete_course_word); 
     (&my_list)->name = (delete_course_word); 
     delete_course(&my_course, my_list); 
     break; 

    case 3:   // Enrol Student 
     program_quit = false; 
     break; 

    case 4:   // Un-enrol student 
     program_quit = false; 
     break; 

    case 5:   // Print a summary of courses and the number of students enrolled in each course 
     program_quit = false; 
     printf("Current enrolments:\n"); 
     print_course_and_num_students(&my_course); 
     break; 

    case 6:   // Print an ordered list of students enrolled in a course 
     program_quit = false; 
     break; 

    case 7:   // Print a list of courses that a given student is enrolled in 
     program_quit = false; 
     break; 

    default: 
     printf("Invalid operation\n"); 
    } 
} while (program_quit == false); 

if (my_course != NULL) 
{ 
    destroy(&my_course); 
} 

//destroy(&my_list); 
return; 
} 
+0

你可以在前面插入特殊情況'if(* self == NULL)';常規代碼將適用於空頭。 –

+0

謝謝,但問題仍然存在。 在main.c中,對於開關狀態1:當用戶繼續輸入新的課程名稱時,它只會覆蓋以前的名稱,並且還會添加新的名稱。 例如:用戶第一個輸入:abc123,第二個輸入:poiu123。 但是在鏈表中它只會顯示poiu123和poiu123,這是完全錯誤的。 –

+0

您是否使用過調試器來查找您的問題。 – MikeMB

回答

1

的問題是,你永遠不會創建一個新名稱,但所有課程結構的名稱指針都指向同一個內存區域,這是您正在分配的內存區域在main開始。

這應該這樣做(華林未經測試):

program_quit = false; 
printf("Add Course: "); 
char* name = malloc(100 * sizeof(char)); 
scanf("%s", name);  
my_list.name=name; 
insert_course_at_front(&my_course, my_list); 

不過,我想警告不要在涉及到生產代碼編寫任何代碼等。如果用戶輸入超過100個字符,則會損壞內存,如果他輸入較少,則會浪費內存。我認爲在C(我沒有長時間寫出高質量的c代碼),你通常會將輸入的字符逐字符地讀入本地緩衝區(當緩衝區si滿了或者例如換行符時停止)然後分配合適大小的內存塊,最後將字符串複製到分配的內存塊中。

+0

是啊我同意你,我需要創建新的'my_list'同時加入了新課程進入'my_course' 。我不知道該怎麼做,因爲我是比較新的C語言特別是數據結構 –

+0

@PangYiYang:我添加了一個未經測試的代碼,應該做你想做的 – MikeMB

+0

是你的代碼的工作非常感謝!!! !不用擔心100個字符,我的任務說明I/O限制不會超過100個字符。 –

0

變化

typedef struct course { 
char *name; 
BST students; 
} Course; 

typedef struct course { 
char name[MAX_LEN]; 
BST students; 
} Course; 

有一定的空間來放置名

編輯 - 在新的信息

Course new_course; 
    new_course-> name = malloc(MAX_LEN); 

    scanf("%s", new_course->name); // This could be better to prevent buffer overwrite 
    insert_course_at_front(&my_course, new_course); 
+0

感謝您的建議,但是我不允許從h文件中更改任何內容,所以它不是一個選項。 (我的任務將被處罰爲失敗) –

+0

取而代之的是'malloc'的字符串'name'(我很抱歉,但我的水晶球正在使用由巫隔壁) –

+0

該方案的問題是不是內存字符串的管理 現在在main.c中(我用的malloc的,而不是固定MAX_LEN它),用於開關盒1:當用戶繼續輸入新的課程名稱,它只會覆蓋以前的名稱,並添加新的一個例如:第一個輸入:abc123,第二個輸入:poiu123。 但是在鏈接列表中它只會顯示poiu123和poiu123。 –