2011-03-09 29 views
2

我是C編程的初學者。我有一個任務使用雙鏈表創建一個學生列表。應用程序應該有三點:顯示列表,添加一個新學生,並用他的ID號刪除一個學生。 我做到了,運行得非常好。 我想問幾個問題:雙鏈表。我做得好嗎?

  1. 是用什麼東西不合適?
  2. 如果有空間可以縮短代碼,我會很樂意收到任何建議。

這裏是我的代碼:

struct student 
{ 
    char first_name[20]; 
    char last_name[20]; 
    char ID_NO[14]; 
    struct student* previous; 
    struct student* next; 
}; 


void Menu(); 
void Show_List(struct student*); 

struct student* Add_Student(char [], char [], char [], struct student*); 
struct student* Erase_Student(char [], struct student*); 

void main(void) 
{ 
    char student_first_name[20]; 
    char student_last_name[20]; 
    char personal_code[14]; 

    struct student* first = NULL; 
    struct student* node0 = NULL; 

    int x = 0; 
    int opt; 

    Menu(); 
    for(; ;) 
    { 
     printf("\nEnter the operation you want to do: \n"); 
     scanf("%d", &opt); 

     switch(opt) 
     { 
     case 1: 
      Show_List(first);   
      break; 
     case 2: 
      printf("\nEnter the student's first name: "); 
      scanf("%s", &student_first_name); 
      printf("\nEnter the student's last name: "); 
      scanf("%s", &student_last_name); 
      printf("\nEnter the student's personal code: "); 
      scanf("%s", &personal_code); 
      node0 = Add_Student(student_first_name, student_last_name, personal_code, first); 
      first = node0; 
      break; 
     case 3: 
      printf("\nEnter the code of the student you want to erase: "); 
      scanf("%s", &personal_code); 
      node0 = Erase_Student(personal_code, first); 
      first = node0; 
      break; 
     default: 
      printf("\nYou entered an invalid option!!! Please try again.\n"); 
      Menu(); 
      break; 
     } 

    } 
    scanf("%d", &x); 

} 

void Menu() 
{ 
    printf("\nSelect from the Menu the operation you want to execute:\n"); 
    printf("\n1) Show students list;"); 
    printf("\n2) Add a student in the list;"); 
    printf("\n3) Erase a student from the list."); 
} 

void Show_List(struct student* firstNode) 
{ 
    struct student* firstNodeCopy = firstNode; 
    int number = 0; 

    if(firstNode == NULL) 
     printf("\nThe list is empty.\n"); 

    while(firstNodeCopy) 
    { 
     printf("\n%d. %s ", ++number, firstNodeCopy->first_name); 
     printf("%s %s\n", firstNodeCopy->last_name, firstNodeCopy->ID_NO); 
     firstNodeCopy = firstNodeCopy->next; 
    } 
} 

struct student* Add_Student(char name_1[], char name_2[], char ID[], struct student* firstNode) 
{ 
    struct student* start = firstNode; 
    struct student* last = NULL; 
    struct student* addNode = (struct student*) malloc(sizeof(struct student)); 

    if(firstNode == NULL) 
    { 
     firstNode = (struct student*) malloc(sizeof(struct student)); 
     strcpy(firstNode->first_name, name_1); 
     strcpy(firstNode->last_name, name_2); 
     strcpy(firstNode->ID_NO, ID); 

     firstNode->next = NULL; 
     firstNode->previous = NULL; 
     return firstNode; 
    } 
    else 
    { 
     strcpy(addNode->first_name, name_1); 
     strcpy(addNode->last_name, name_2); 
     strcpy(addNode->ID_NO, ID); 

     while(start) 
      { 
       if(strcmp(addNode->first_name, start->first_name) > 0) 
       { 
        if(start->next == NULL) 
        { 
         start->next = addNode; 
         addNode->previous = start; 
         addNode->next = NULL; 
         return firstNode; 
        } 
        else 
        { 
         last = start; 
         start = start->next; 
        } 
       } 

       if(strcmp(addNode->first_name, start->first_name) < 0) 
       { 
        if(last == NULL) 
        { 
         addNode->next = start; 
         start->previous = addNode; 
         return addNode; 
        } 
        else 
        { 
         addNode->next = start; 
         addNode->previous = last; 
         last->next = addNode; 
         start->previous = addNode;     
         return firstNode;     
        } 
       } 

       if(strcmp(addNode->first_name, start->first_name) == 0) 
       { 
        if(strcmp(addNode->last_name, start->last_name) < 0) 
        { 
         if(last == NULL) 
         { 
          addNode->next = start; 
          start->previous = addNode; 
          return addNode; 
         } 
         else 
         { 
          addNode->next = start; 
          addNode->previous = last; 
          last->next = addNode; 
          start->previous = addNode;     
          return firstNode; 
         } 
        } 

        if(strcmp(addNode->last_name, start->last_name) > 0) 
        { 
         if(start->next == NULL) 
         { 
          start->next = addNode; 
          addNode->previous = start; 
          addNode->next = NULL; 
          return firstNode; 
         } 
         else 
         { 
          last = start; 
          start = start->next; 
         } 
        } 

        if(strcmp(addNode->last_name, start->last_name) == 0) 
        { 
         if(last == NULL) 
         { 
          addNode->next = start; 
          start->previous = addNode; 
          return addNode; 
         } 
         else 
         { 
          addNode->next = start; 
          addNode->previous = last; 
          last->next = addNode; 
          start->previous = addNode;     
          return firstNode; 
         } 
        } 
       } 
      } 
    } 
} 

struct student* Erase_Student(char ID[], struct student* firstNode) 
{ 
    struct student* start = firstNode; 
    struct student* last = NULL; 

    if(start == NULL) 
    { 
     printf("\nThe list is empty.\n"); 
     return NULL; 
    } 
    else 
    { 
     while(start) 
     { 
      if(strcmp(ID, start->ID_NO) == 0) 
      { 
       if(last == NULL) 
       { 
        start = start->next; 
        return start; 
       } 
       else 
       { 
        last->next = start->next; 
        return firstNode; 
       } 
      } 
      else 
      { 
       last = start; 
       start = start->next; 
      } 
     } 
     printf("\nYou entered a WRONG personal ID number to erase!!! Please try again.\n"); 
     return firstNode; 
    } 
} 
+0

將'main'的簽名更改爲'int main(void)'。 'main'函數總是向操作系統返回一個'int'。 –

回答

2
  • 您有內存泄漏,當您添加的第一個節點,你既分配和ADDNODE firstNode
  • 您有內存泄漏,當你刪除一個學生,你需要free()刪除的節點。
  • 您應該使用函數來比較名稱而不是重複的代碼。像int compareStudents(char * LeftFirstName, char * LeftLastName, char * RightFirstName, char * RightLastName);

除此之外,邏輯是好的。

0

你所做的一切非常清楚!幹得好,開始!保持學習。

0

這實際上非常好!我承認,在你介紹之後,我希望得到一個爛攤子。

你在那裏做得非常好,男人。無論你能改善什麼,你都會在適當的時候學習:)。繼續努力吧!

我剛纔建議你看看「抽象數據類型」是什麼,以及如何暴露模糊實現的接口,但正如我所說 - 你會很快學會!

乾杯。

0

快速瀏覽一下Add_Student(...)函數。看起來像一個小內存泄漏。如果你想,我可以更具體一些,但認爲你可能想要練習。

0
  • 您對scanf的使用是不安全的(輸入可能會溢出目標char數組)。嘗試scanf("%19s", &student_first_name);
  • 使用strcpy也是不安全的。看看strncpy。
0

您選擇了多個變量名稱會使代碼不必要地混淆。例如,在Show_List中,有名爲firstNodeCopy的東西不是任何節點的副本,並且並不總是引用第一個節點。

Add_Student,你有很多不同的比較我甚至不知道你甚至想要完成什麼,但我很確定你有什麼可以改進。再次,你有一些變量(例如,start),它們的名字似乎並不是他們真正應該做什麼的可靠指示。

我建議改變結構了一下:創建一個函數compare_students(或類似的東西)是只是手柄比較一個學生到另一個,並且(例如)告訴你兩個學生A和B是否在訂單或不按順序。我可能還會添加一個「創建學生」來獲取一組輸入並從中創建一個學生結構。從那裏,插入算法看起來像:

if list is empty, put new node in list 
if new node precedes first item in list, insert at head of list 
Walk through list until end of list or current node precedes new node 
     if at end of list, add new node to end 
     else insert new node before current node 
0

有些吹毛求疵,我發現

  • #include:在這個程序,你需要<stdio.h><stdlib.h><string.h>
  • 神奇數字:使用enum#define而不是用「神奇數字」衝擊你的源代碼
  • 注意當使用時緩衝區溢出和檢查返回值
  • 風格:在輸出端更喜歡'\n'printf("...\n") VS printf("\n...")
  • 儘量不重複strcmp小號

編譯警告級別推到最大,並嘗試擺脫所有警告。

0

您可以將void Menu()的原型更改爲void Menu(void)。這樣編譯器可以檢查函數是否被正確調用。如果在編譯時已經可以找到錯誤,那總是很好。