0

嘿,伙计们,我正在做一个项目,我不断收到“库为空”,然后出现段错误,通过 gdb 运行它告诉我错误在我的 count_list 函数中。但我似乎无法弄清楚为什么?任何提示将不胜感激,因为它让我如此接近完成并挂断了电话。

#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;
            }

    }
4

3 回答 3

1

你的函数没有返回一个数字(所以一些意想不到的值会真正返回给调用者)。您需要添加返回语句。

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

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

    }

如果您打开编译器的警告选项,您会遇到一些其他问题:

  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() /Clean() 没有回报

于 2013-10-16T02:27:11.903 回答
1

观察,

Count_List() 应该计算列表中的每个元素,您的版本仅从列表中的第二项开始计算。它应该总是返回一个int,

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() 中,您调用 Create_List(Entry,Head),但您的函数签名为 Create_List(Head,Entry); 你打算哪一个?可能(头,条目)。使用 fgets 和 sscanf 来读取文件,

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(),您似乎将 List 实现为堆栈(将 Entry 推到列表的头部),

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

    Entry->next = Head;
    return Entry;
}

Create_Album() 需要在给成员变量赋值之前检查 malloc 是否成功,

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

说到图书馆结构,您将成员流派、乐队、专辑声明为指针,但您需要空间来复制内存,例如,

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

我的建议是构建构造函数和析构函数 LibraryNew、LibraryDel。

检查 (argc<2) 参数(您的消息说不够,而不是需要 2,

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

这解决了最大的问题,

./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?
于 2013-10-16T02:35:31.257 回答
0

您忘记从 Count_List 实际返回一些内容。

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

    while(Tmp->next != NULL)
    {
        count++;
        Tmp = Tmp->next;
    }
    return count;
}
于 2013-10-16T02:29:43.863 回答