2013-04-05 70 views
0

我對c(和本站)相當陌生,而且在分段錯誤方面存在很多問題。我正在編寫一個程序,用於創建數字的鏈接列表並按升序插入值。C編程分段錯誤鏈表程序

 void insert(struct element **head, struct element *new){ 
      if((*head)->next == NULL && (*new).i > (*(*head)->next).i){ 
       (*head)->next = new; 
       return;  
      } 
      if((*head)->next == NULL && (*new).i < (*(*head)->next).i){ 
       new->next = (*head)->next; 
       *head = new;  
       return; 
      } 
      struct element *prev = *head; 
      struct element *current = (*head)->next; 
      while(current->next != NULL){ 
       if((*new).i < (*current).i){ 
        prev = current; 
        current = current->next; 
       } else if((*new).i > (*current).i){ 
        new->next = current; 
        prev->next = new; 
       } 
      } 
     } 
     int main (void){ 
      struct element **head; 
      int value; 
      printf("%s", "TEST"); 
      printf("%s" , "Please type in an integer value. "); 
      scanf("%d" , &value); 
      printf("%s", "TEST"); 
      do{ 
       printf("%s", "TEST"); 
       struct element *new; 
       if((new = malloc(sizeof(struct element))) == NULL){ 
       return(NULL); 
       } 
       printf("%s", "TEST"); 
       (*new).i = value; 
       printf("%s", "TEST"); 
       if(head == NULL){ 
        *head = new; 
        printList(*head); 
       } else if(value <= 0){ 
        printListBackwards(*head); 
       } 
       else { 

        insert(head, new); 
        printList(*head); 
       } 
       } while(value > 0); 

我不需要幫助邏輯是否正確插入或任何東西。我甚至沒有機會真正測試它,因爲在提示符後輸入一個整數後,我立即得到了分段錯誤。我知道它看起來很時髦,但規格要求您使用指向結構(鏈表頭)的指針。

+1

共享代碼時,請確保其他用戶可以快速編譯您的代碼並重現錯誤。你的代碼在'main'函數中缺少結構定義,函數,甚至是大括號。另外,在尋求幫助之前,請確保您的代碼在編譯時不顯示警告/錯誤。嘗試使用標誌'-Wall -Wextra'進行編譯。當找出段錯誤時,我發現'valgrind'是一個非常有用的工具,試試吧。只要記住用'-g'標誌編譯生成調試符號 – 2013-04-05 01:53:09

回答

0

有您的文章的第二行正在引起了賽格故障

if((*head)->next == NULL && (*new).i > (*(*head)->next).i){ 
    (*head)->next = new; 
    return;  
} 

段錯誤意味着您試圖訪問你不準內存。例如,您不能取消引用NULL指針。

您的if聲明是這樣評估的。 檢查(*head)->next是否爲空。

如果它不是NULL,則跳過其餘部分。

如果它是NULL,那麼你可以用NULL替換每個後面的(*head)->next。這意味着下面的部分&& (*new).i > (*(*head)->next.i)可以改寫如下:&& (*new).i > ((*NULL).i) ...

簡而言之,您試圖取消引用NULL指針值。

請同時參考@Parker Kemp的帖子。有很多次您正在檢查NULL,但誤解它的含義。

我可以重寫你的代碼,但我認爲你會從通過教程去像this onethis one

我強烈建議提請你的數據結構圖和繪圖箭指針獲益更多。

+0

好的謝謝。你能告訴我爲什麼當我運行該程序時,它甚至在嘗試調用函數insert之前未能輸出第二個「TEST」行?什麼是安全的方法來檢查C中的NULL? – user2247284 2013-04-05 01:49:54

+0

您正確測試NULL,但您沒有使用正確的比較。 'if(pointer == NULL)...'會告訴你指針是否包含一個NULL值,意味着它指向禁止的內存。 – nonsensickle 2013-04-05 01:54:58

2

您確定要將頭變爲element**而不是element*?這種額外的分離程度會導致你的問題,其中最重要的是難以閱讀的代碼。

這裏有一個跳出我的主要事情:

if(head == NULL){ 
    *head = new; 
    printList(*head); 
} 

你確認頭是一個空指針,然後立即嘗試取消對它的引用與*。如果你真的堅持頭是一個雙指針,那麼你需要在解引用它之前動態分配它。像這樣:

if(head == NULL){ 
    head = malloc(sizeof(element*)); 
    *head = new; 
    printList(*head); 
} 

這實際上可能不是完美的語法(我來自C++),但你的想法。雖然說到C++,但在C中命名變量「new」通常被認爲是不好的做法,因爲new是C++中的一個關鍵字。

+0

謝謝。我將要改變一個單一的指針,看看它是否更好。我仍然不確定爲什麼當我運行該程序時,它不會在失敗之前從主打印出第二條「TEST」行。 – user2247284 2013-04-05 02:01:55

+0

@ user2247284您的printf字符串不會以換行符結束,因此它們不會被刷新。另外,通常只要執行'printf(「TEST \ n」);' – 2013-04-05 02:08:08

+0

爲了擴展Jim的說法,printf實際上並不會立即打印,除非必須。在你的程序中,它將「TEST」放入緩衝區,但之後決定等待,因爲尚未到達換行符。然後你的程序在它衝過緩衝區之前崩潰了。 – 2013-04-05 02:11:14

0
struct element **head; 

你不想那樣。相反,

struct element *head = NULL; 

然後,當你調用插入,使用

insert(&head, new); 

你有很多其他錯誤和貧困慣例,但是這對你的特定問題的開始。