2013-10-16 6 views
0

안녕하세요 여러분, 프로젝트를하고 있는데 "라이브러리가 비어 있습니다."라는 메시지가 계속 표시되고 seg 오류가 발생하여 gdb가 실행되어 오류가 count_list 함수에 있음을 알게됩니다. 하지만 왜 그럴 수없는 것 같아? 어떤 팁이라도 끝내기가 너무 가까워서 이걸 끊어 버리는 것에 감사 할 것입니다.라이브러리가 비어 있고 seg 오류가 발생했습니다.

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

/* Assume max char count in file */ 
#define MAX 20 

/* library struct - DO NOT CHANGE */ 
typedef struct library 
{ 
    char *genre; 
    char *band; 
    char *album; 
    float rating; 
    struct library *next; 
}Library; 

/* Function Prototypes - DO NOT CHANGE */ 
Library *Read_File(FILE *); 
void Print(Library *); 
Library *Create_List(Library *, Library *); 
Library *Create_Album(char *, char *, char *, float); 
Library *Merge(Library *, Library *); 
int Count_List(Library *); 
void Split_List(Library *, Library **, Library **); 
Library *Merge_Sort(Library *); 
Library *Delete_Genre(Library *); 
void Free_Entry(Library *); 
Library *Clean(Library *); 

    /* MAIN 
    * Error check file parameter 
    * Call Read_File to fill our list 
    * Print our list 
    * Merge Sort the linked list (by genre) 
    * Delete a genre 
    * Free the list 
    */ 
    int 
    main(int argc, char **argv) 
    { 

     if(argc != 2) 
     { 
      printf("Not enough arguments.\n"); 
      return 0; 
     } 

     FILE *fp = NULL; 

     if((fp = fopen(argv[1], "r")) == NULL) 
     { 
      printf("File can not be opened.\n"); 
      return 0; 
     } 

     Library *Head = NULL; 
     Head = Read_File(fp); 
     Print(Head); 

     Merge_Sort(Head); 
     Print(Head);    

     Head = Delete_Genre(Head); 
     Print(Head); 

     Head = Clean(Head); 
     Print(Head);   

     return 0; 
    } 
    /* Clean() 
    * Delete the linked list, recursively 
    */ 
    Library * 
    Clean(Library *Head) 
    { 
     if(Head) return NULL; 

     Library *Tmp = Head->next; 
     Free_Entry(Head); 
     Clean(Tmp->next); 
    } 

    /* Free_Entry() 
    * wrapper function to free a struct Library 
    */ 
    void 
    Free_Entry(Library *Entry) 
    { 
     free(Entry); 
    } 

    /* Delete_Genre() 
    * Deletes a genre inputted by user 
    * Logic: 
    * prompt user for genre input 
    * traverse list deleting all structs that contain the genre 
    */ 
    Library * 
    Delete_Genre(Library *Head) 
    { 
     if(!Head) 
     { 
      printf("List Empty.\n"); 
      return NULL; 
     } 

     char *input = malloc(MAX * sizeof(char *)); 
     Library *Current = Head; 
     Library *Tail = NULL; 

     printf("Which genre would you like to delete?\n"); 

     scanf("%s", input);  

     while(Current) 
     { 
      if(strcmp(Current->genre, input)) 
      { 
       if(Current = Head) 
       { 
        Head = Head->next; 
        Free_Entry(Current); 
        Current = Head; 
       } 
       else 
        Tail->next = Current->next; 

      } 
      else 
       Current = Current->next; 
     } 
    } 

    /* Read_File() 
    * Open file fp 
    * Create a struct from information in text file 
    * Link our list with newly created struct 
    */ 
    Library * 
    Read_File(FILE *fp) 
    { 
     Library *Head, *Entry; 
     Head = Entry = NULL; 

     char *genre, *band, *album; 
     float rating;  

     while(1) 
     { 
      fscanf(fp, "%s %s %s %f", &genre, &band, &album, &rating); 
      if(!feof(fp)) 
       break; 
      Entry = Create_Album(genre, band, album, rating); 
      Head = Create_List(Entry, Head); 
     } 

     return Head; 
    } 

    /* Print() 
    * Print the linked list 
    */ 
    void 
    Print(Library *Head) 
    { 
     if(!Head) 
     { 
      printf("Library is empty.\n"); 
      return; 
     } 

     while(Head) 
     { 
      printf("%20s %20s %20s %20.2f \n", 
       Head->genre, Head->band, Head->album, Head->rating); 
      Head = Head->next; 
     } 
     printf("\n\n"); 
     //return Head; 
    } 

    /* Create_Album 
    * Create a struct and assign the given args to it as appropriate 
    */ 
    Library * 
    Create_Album(char *genre, char *band, char *album, float rating) 
    { 
     Library *Entry = malloc(sizeof(Library)); 
     strcpy(Entry->genre, genre); 
     strcpy(Entry->band, band); 
     strcpy(Entry->album, album); 
     Entry->rating = rating; 
     Entry->next = NULL; 

     return Entry; 
    } 

    /* Create_List() 
    * Push Entry onto our List 
    */ 
    Library * 
    Create_List(Library *Head, Library *Entry) 
    { 
     if(!Head) 
      return Entry; 

     Entry->next = Head; 
     return Entry; 
    } 
    /* Merge_Sort() 
    * Recursively split our list between Left and Right 
    * Merge our Left and Right lists 
    */ 
    Library * 
    Merge_Sort(Library *Head) 
    { 
     Library *Tmp = Head; 
     Library *Left, *Right, *Result; 
     Left = Right = Result = NULL; 

     int count = Count_List(Head); 

     if(count = 1) 
      return Tmp; 

     Left = Merge_Sort(Left); 
     Right = Merge_Sort(Right); 

     Result = Merge(Left, Right); 

     return Result; 
    } 
    /* Split_List() 
    * split our list in half 
    */ 
    void 
    Split_List(Library *Head, Library **Left, Library **Right) 
    { 
     int size = Count_List(Head); 
     int i; 
     Library *Tmp = Head; 

     *Left = Head; 

     for(i=1; i<size/2; ++i) 
      Tmp=Tmp->next; 

     *Right = Tmp->next; 
     Tmp->next = NULL; 
    } 

    /* Merge() 
    * Merge two linked lists Left and Right together in sorted order 
    */ 
    Library * 
    Merge(Library *Left, Library *Right) 
    { 
     Library *Result, *Tmp; 
     Result = Tmp = NULL; 

      if(strcmp(Left->genre, Right->genre) <= 0) 
      { 
       Result = Left; 
       Left = Left->next; 
      } 
      else 
      { 
       Result = Right; 
       Right = Right->next; 
      } 
      Tmp = Result; 

     while(Left != NULL && Right != NULL) 
     { 
       if(Left != NULL && Right!= NULL)  
       { 
         if (strcmp(Left->genre, Right->genre) <= 0) 
         { 
          Tmp->next = Left; 
          Left = Left->next; 
         } 
         else 
         { 
          Tmp->next = Right; 
          Right = Right->next; 
         } 
       Tmp = Tmp->next; 
       } 
      } 
     return Result; 
    } 
    /* Count_List() 
    * Count the number of elements in a linked list 
    */ 
    int 
    Count_List(Library *Head) 
    { 
      Library *Tmp = Head; 
      int count = 0; 

     while(Tmp->next != NULL) 
      { 
       count++; 
       Tmp = Tmp->next; 
      } 

    } 
+0

당신은 머리를 유지 찾을 수 있습니다, 당신의 메시지는, 대신에 필요 2의 충분히

if(argc < 2) { printf("Not enough arguments.\n"); return 0; } 

을하지 말합니다 그리고 그 가장 큰 문제를 해결/꼬리 포인터 쌍을 사용하여 목록의 요소를 계산하면 유용합니다 – ChuckCottrill

+0

Delete_Genre에서 malloc 입력 메모리를 free'ing하지 않습니다 – ChuckCottrill

답변

1

관찰,

Count_List() 버전은 목록의 두 번째 항목에서 시작하여 수, 목록에있는 각 요소를 계산해야한다. 그리고 그것은 항상 당신이 Create_List (항목, 헤드), 그러나 Create_List (헤드, 항목)에 대한 함수 서명 전화),

int 
Count_List(Library *Head) 
{ 
    int count = 0; 
    Library *Tmp = Head; 
    if(!Tmp) return(count); 

    while(Tmp != NULL) 
    { 
     count++; 
     Tmp = Tmp->next; 
    } 
    return(count); 
} 

내부 Read_File을 (int를 반환해야합니다; 너는 어떤 의도로? 아마도 (헤드, 엔트리).

Library * 
Read_File(FILE *fp) 
{ 
    Library *Head, *Entry; 
    Head = Entry = NULL; 
    char genre[100], band[100], album[100]; 
    float rating; 
    char line[100]; 

    while(fgets(line,sizeof(line),fp) 
    { 
     sscanf(line,"%s %s %s %f", genre, band, album, &rating); 
     Entry = Create_Album(genre, band, album, rating); 
     Head = Create_List(Head,Entry); 
    } 
    return Head; 
} 

Create_List()를 보면

, 당신은 스택으로 목록을 구현하는 것 같다, Read_File로는 fgets와 sscanf를 사용) (

Library * 
Create_List(Library *Head, Library *Entry) 
{ 
    if(!Head) 
     return Entry; 

    Entry->next = Head; 
    return Entry; 
} 

Create_Album 요구를 (목록의 머리에 항목을 밀어)

Library *Entry=NULL; 
    if(!(Entry=(Library*)malloc(sizeof(Library)))) 
    { 
     printf("error creating album\n");fflush(stdout); 
     return Entry; 
    } 

라이브러리 구조체의 말하기, 멤버 변수에 값을 할당하기 전에 성공적으로 malloc을 확인하기 위해, 당신은 포인터로 멤버 장르, 밴드, 앨범을 선언,하지만 당신은 메모를 복사 할 공간이 필요 예,

typedef struct library 
{ 
char genre[50]; 
char band[50]; 
char album[50]; 
float rating; 
struct library *next; 
}Library; 

내 제안은 생성자 및 소멸자 함수 LibraryNew, LibraryDel을 작성하는 것입니다.

확인을위한 (는 argc < 2) 인수 (

./library music.x 2 
line:Rock Antrax Party 1.2 

Rock,Antrax,Party,1.200000 
Rock,Antrax,Party,1.200000 
added: Rock,Antrax,Party,1.200000 
      Rock    Antrax    Party     1.20 
      Rock    Antrax    Party     1.20 
Which genre would you like to delete? 
+0

Free_Entry에 전달 된 검사 포인터가 NULL이 아닌 경우 if (! Entry) return; – ChuckCottrill

+0

깨끗한 필요 빈 (empty)에 대한 다른 검사? (! Head)가 NULL을 반환하면; – ChuckCottrill

1

함수가 숫자를 반환하지 않습니다 (따라서 일부 예상치 못한 값이 실제로 호출자에게 반환됩니다). return 문을 추가해야합니다.

int Count_List(Library *Head) 
    { 
      Library *Tmp = Head; 
      int count = 0; 

     while(Tmp->next != NULL) 
      { 
       count++; 
       Tmp = Tmp->next; 
      } 

    } 

다른 문제를 당신이 당신의 컴파일러의 경고 옵션을 설정하면 당신이 얻을 것이다 : 반환에게 당신은 잊었

0

이없는 깨끗한

if(Current = Head) would you expect == ? 

fscanf(fp, "%s %s %s %f", &genre, &band, &album, &rating); 

should be 
fscanf(fp, "%s %s %s %f", genre, band, album, &rating); 

if(count = 1) // == ? 

Delete_Genre() /() 실제로 Count_List에서 무엇인가를 반환합니다.

int Count_List(Library *Head) 
{ 
    Library *Tmp = Head; 
    int count = 0; 

    while(Tmp->next != NULL) 
    { 
     count++; 
     Tmp = Tmp->next; 
    } 
    return count; 
} 
관련 문제