2012-11-08 62 views
0

它第一次正常工作。我可以添加一個項目,然後使用顯示功能進行顯示。但是當我嘗試添加第二個值時,只要我在fgets處點擊「a」,就會遇到seg錯誤。我已經在頂部註釋過了。fgets鏈接列表程序分段錯誤?

(我還沒有與除添加其他功能還困擾。)

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <ctype.h> 
#include "sortedll.h" 

int  main(void) 
{ 

int    intVal; 
LNode   *headPtr = NULL; 
char   buf[BUFLEN]; 
int    result; 

do { 
    // ask the user what they want to do 
    DisplayMenu(); 
    printf("Please enter a selection: "); 
    fgets(buf, BUFLEN, stdin); 
    *buf = toupper(*buf); 
    switch (*buf) 
     { 
     case 'A': 
      // prompt the user for a value; if we get one, add it to the 
      // list 
      printf("Please enter an integer value to add: "); 
      fgets(buf, BUFLEN, stdin); 

      //======================================================================= 
      printf("check"); //doesn't print this second time around. seg fault at fgets? 
      //======================================================================= 

      if (1 != sscanf(buf, "%d", &intVal)) 
       { 
       puts("Error reading the integer value..."); 
       } 
      else 
       { 
       printf("1"); 
       headPtr = AddItem(headPtr, intVal); 
       } 
      break; 

     case 'R': 
      // if the list is empty display a message; else, get a value 
      // from the user and attempt to remove it from the list 
      if (NULL == headPtr) 
       { 
       puts("The list is currently empty..."); 
       } 
      else 
       { 
       printf("Please enter an integer value to remove: "); 
       fgets(buf, BUFLEN, stdin); 
       if (1 != sscanf(buf, "%d", &intVal)) 
        { 
        puts("Error reading the integer value..."); 
        } 
       else 
        { 
        headPtr = RemoveItem(headPtr, intVal); 
        } 
       } 
      break; 

     case 'D': 
      // display the current contents of the list 
      result = DisplayList(headPtr); 
      printf("Currently there %s %d node%s in the list.\n" 
           , (result != 1) ? "are" : "is" 
           , result 
           , (result != 1) ? "s" : ""); 
      break; 

     case 'Q': 
      // release all allocated memory and set the head pointer to 
      // NULL to indicate that it is empty 
      result = ReleaseMemory(headPtr); 
      printf("There %s %d node%s released." 
           , (result != 1) ? "were" : "was" 
           , result 
           , (result != 1) ? "s" : ""); 
      headPtr = NULL; 
      break; 

     default: 
      puts("Unrecognized option; please try again."); 
      break; 
     } 
    puts(" "); 

    } while ('Q' != *buf); 

puts("Thanks for playing! Bye!!\n"); 
return 0; 

} // end of "main" 



// ==== AddItem =============================================================== 


LNode* AddItem(LNode *headPtr, int newItem) 
{ 
    LNode *node = malloc(sizeof(*node)); 
    node->value = newItem; 


    if(headPtr == NULL) 
     { 
     node->next = NULL; 
     return node; 
     } 

    LNode *leadPtr = headPtr; 
    LNode *trailPtr = headPtr; 

    while(leadPtr->value != newItem) 
     { 
     leadPtr = leadPtr->next; 
     trailPtr = leadPtr; 
     }  

    leadPtr = leadPtr->next; 
    free(trailPtr->next);  
    trailPtr->next = node; 
    node->next = leadPtr; 

    return headPtr; 

} // end of "AddItem" 



// ==== DisplayList =========================================================== 


int  DisplayList(LNode *nodePtr) 
{ 
    auto int   counter = 0; 

    // if the list is empty, indicate as such and return zero 
    if (NULL == nodePtr) 
     { 
     puts("The list is currently empty..."); 
     return (0); 
     } 

    while (NULL != nodePtr) 
     { 
     printf("%d\n", nodePtr->value); 
     nodePtr = nodePtr->next; 
     counter++; 
     } 

    return (counter); 

} // end of "DisplayList" 



// ==== DisplayMenu =========================================================== 


void DisplayMenu(void) 
{ 
    puts("A)dd a value"); 
    puts("R)emove a value"); 
    puts("D)isplay the list"); 
    puts("Q)uit"); 

} // end of "DisplayMenu" 



// ==== ReleaseMemory ========================================================= 


int  ReleaseMemory(LNode *headPtr) 
{ 


} // end of "ReleaseMemory" 



// ==== RemoveItem ============================================================ 


LNode* RemoveItem(LNode *headPtr, int targetItem) 
{ 


} // end of "RemoveItem" 

回答

0

貌似找你想在這裏訪問leadPtr->值時leadPtr可能爲空。

while(leadPtr->value != newItem) 
    { 
    leadPtr = leadPtr->next; 
    trailPtr = leadPtr; 
    } 

您需要在嘗試訪問它的成員之前確保leadPtr!= NULL。

我建議你重構代碼片段所屬的函數,它在內存訪問方面看起來有點脆弱。

+0

那麼,我試圖在添加函數的最開始處進行printf檢查,並在顯示任何內容之前對它進行了細分。所以這並不意味着在崩潰之前它甚至不會進入該功能? 即使是我在第29行寫的原始支票,也沒有顯示。所以它必須是fgets的權利? –

+0

什麼是BUFLEN的定義?另外,toupper的參數應該是一個unsigned char,否則它有未定義的行爲。 – Jite

+0

也嘗試使用不同的緩衝區進行菜單選擇和值輸入。但首先確保你傳遞'unsigned char'到'toupper()'。我認爲在調用像toupper()這樣的函數時,通常不建議源和目的地相同。 – Jite

0

你真的應該從你的malloc調用來檢查返回值:

葉子節點*節點=的malloc(的sizeof(*節點));

node-> value = newItem;

如果您的堆空間用完了會怎麼樣?

+0

應該總是這樣做,但是它不太可能成爲問題的答案。 – Jite