2012-11-08 36 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