为啥从文件流中读取数据到新链表,要求返回头指针head,需要定义多一个临时指针p ?

book结构体定义如下:

struct book //定义book结构体
{
    int number;     //编号
    char name[30];  //书名
    char category[10];  //类别
    char lentuser[12];  //借书人的usernum
    int lent;       //是否借出(已借为1,未借为0)                            
    int year;       //借出时间——年
    int month;      //借出时间——月
    int day;        //借出时间——日
    struct book *next; //一个指向book类型对象的指针 
};

library.txt截图如下:
图片描述

有疑问的make_linklist()函数的代码如下:

//从library.txt中读取数据至链表
struct book *make_linklist()   //这货是条指针函数,本质就是段函数(在汇编程序里面函数就是code segment哈哈和 data segment并列的存在)
                                //所以函数和数组都是差不多的东西,声明函数或数组之后默认会分配给他们一个指向他们首地址的指针
                                //而且这个指针的名字跟函数名/数组名一样 
                                //make_linklist()的返回值是(struct book *)    //(struct book *)就是指向类型为book的结构体的指针 
{
    struct book *head;  //指针head现在可以指向任何类型为book的结构体 
    head = (struct book *)malloc(sizeof(struct book));  //分配book结构体大小的内存,
                                                        //并将这块内存按照book结构体的大小划分单元, 
                                                        //然后将这块内存的首地址赋值给指针变量head,即head为头指针 
    head->next = NULL; //将头节点的指针域赋值为null,即初始化一个带头结点的单链表 
 
    
          
    FILE *fp;  //定义fp,一个指向文件类型的文件指针(FILE *) 
    fp = fopen("library.txt", "r+");  //告诉fp要指向的文件是library.txt     (r+表示允许读写文件)      
    
    //如果library.txt文件不存在
    if (fp == NULL)  
        fp = fopen("library.txt", "w+");  // w+ ,如果文件已经存在,将建立一个新文件覆盖原文件(很缺德啊……),并且支持读取。
                                           //此处用于创建library.txt文件 
    
    //如果检测到library.txt为空                                                    
    if (check_void_file() == 0)  
    {
        printf("图书数据库为空!");
        return head;  //返回创建链表的头指针,即返回整个链表,这样就可以被其他地方所用了 
    }
    
    //library.txt不为空 
    struct book *p;
    p = head;  //给p赋值为头指针,即让p指向头节点 
    char ch;
    while(!feof(fp))  //当文件指针fp没有到达末尾,循环执行从library.txt读取数据到链表 
                      //(feof()用于检测文件是否结束,如果没有结束,返回值是0,结束了是1) 
    {
        struct book *new_book_init;   //指针new_book_init现在可以指向类型为book的任何结构体 
        new_book_init = (struct book *)malloc(sizeof(struct book));  //分配book结构体大小的内存,并将这块内存按照book结构体的大小划分单元, 
                                                                    //然后将这块内存的首地址赋值给指针变量new_book_init,
                                                                    //即new_book_init为头指针 
        
        /*依序从fp指向的文件流中赋值给new_book_init指针指向的结构体的成员,开始*/

            //第一行
            fscanf(fp, "%d", &new_book_init->number);  
            ch = fgetc(fp); 
            fscanf(fp, "%[^\n]%*c", new_book_init->name); 

            //第二行
            fscanf(fp, "%[^\n]%*c", new_book_init->category); 

            //第三行
            fscanf(fp, "%[^\n]%*c", new_book_init->buser);

            //第四行
            fscanf(fp, "%d", &new_book_init->lent); 
            ch = fgetc(fp);   //吃空格,让fp下移 
            fscanf(fp, "%d", &new_book_init->year); 
            ch = fgetc(fp);   //吃空格,让fp下移
            fscanf(fp, "%d", &new_book_init->month);
            ch = fgetc(fp);   //吃空格,让fp下移
            fscanf(fp, "%d", &new_book_init->day);
            ch = fgetc(fp);   //吃换行,让fp下移

            //不要忘了给结构体内的成员next指针赋值为null,不要让next成为野指针
            new_book_init->next = NULL;  

        /*依序从fp指向的文件流中赋值给new_book_init指针指向的结构体的成员,结束*/


        p->next = new_book_init; 
        p = p->next;
    }
    fclose(fp);

    return head;
}

为啥需要定义指针p呢?直接将head = new_book_init不可以吗?

阅读 3.6k
1 个回答

你创造的是單向連結串列。
如果没有p,用head = new_book_init。那经过while循环之后,head实际指向連結串列的尾部,然后return head。
这样做的问题是之后你不能遍历串列,因为尾部没有指针指向前面的node。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进