21天C语言代码训练营(第十六天)

作者: 天花板 | 来源:发表于2016-03-03 23:19 被阅读1073次

    上一篇中,我们讲了如何自己定义一个负责文件操作的功能集合,今天我们就利用这一组功能完成保存记录的动作。

    文件读写操作

    在上一篇的基础上,我们稍作修改加入到我们的通讯录工程中来。代码如下:

    • MyFile.h

        #ifndef __MY_FILE_H__
        #define __MY_FILE_H__
        
        #include <stdio.h>
        
        #define FOR_READ        0
        #define FOR_WRITE       1
        
        FILE* fp;
        
        extern int OpenFile(char* pFileName, int nOperate);
        extern void CloseFile();
        
        extern char* ReadLine();
        extern int WriteLine(char* pLine);
        
        #endif
      
    • MyFile.c

        #include "MyFile.h"
        
        #include "string.h"
        
        #define BUF_SIZE 100
        char pBuf[BUF_SIZE];
        
        int OpenFile(char* pFileName, int nOperate)
        {
            switch (nOperate)
            {
            case FOR_READ:
                fp = fopen(pFileName, "r");
                break;
            case FOR_WRITE:
                fp = fopen(pFileName, "w+");
                break;
            default:
                break;
            }
        
            if (fp == NULL)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        }
        
        void CloseFile()
        {
            fflush(fp);
            fclose(fp);
        }
        
        char* ReadLine()
        {
            pBuf[0] = 0;
        
            if(feof(fp))
            {
                return NULL;
            }
            else
            {
                if (NULL == fgets(pBuf, BUF_SIZE, fp))
                {
                    return NULL;
                }
                else
                {
                    pBuf[strlen(pBuf) - 1] = 0;
                }
                
            }
        
            return pBuf;
        }
        
        int WriteLine(char* pLine)
        {
            fwrite(pLine, sizeof(char), strlen(pLine), fp);
            fwrite("\n", sizeof(char), 1, fp);
        
            return 1;
        }
      

    注意,这段代码和上一篇中的有所不同,主要是我们在ReadLine()函数的实现中采用了fgets()这个函数。这个函数的特点是读取字符串时遇到换行符会自动停止,与我们的需求比较类似。

    数据保存功能

    当我们在程序中录入了一些通讯录条目之后,我们需要在退出前将这些数据保存在文件中。在main.c文件中,我们添加一个函数调用,函数名是SavedRecords()。

    这个函数实现如下:

    void SavedRecords()
    {
        if (OpenFile("book.txt", FOR_WRITE) != 1)
        {
            return;
        }
    
        ListNode* pNode;
        for (pNode = g_pL; pNode->_pR != NULL; pNode = pNode->_pNext)
        {
            pNode->_pR;
            WriteLine(pNode->_pR->_pStrName->pBuf);
            WriteLine(pNode->_pR->_pStrTel->pBuf);
            WriteLine(pNode->_pR->_pStrPS->pBuf);
            WriteLine("----------");
        }
    
        CloseFile();
    }
    

    这个函数主要执行三个动作:

    • 打开一个名为book.txt的文件,注意使用写模式打开
    • 遍历链表,之后调用WriteLine()函数把每条记录的每个条目写入book.txt文件
    • 关闭文件

    在文件中保存数据时,我们用“-----”来分隔不同的记录。就这样,数据保存功能实现了。

    数据恢复功能

    保存了数据之后,在每次启动程序时,需要重新把这些数据读取出来保存进数据链表中。我们用一个函数LoadRecords()来实现。

    在图中程序启动的位置,加入这个函数的调用。具体代码如下:

    void LoadRecords()
    {
        Record* pR = NULL;
    
        if (OpenFile("book.txt", FOR_READ) != 1)
        {
            return;
        }
    
        char* pLine = NULL;
        while ((pLine = ReadLine()) != NULL)
        {
            if (pLine[0] == 0)
            {
                break;
            }
            
            RecordInit(&pR);
    
            RecordSetName(pR, pLine);
    
            pLine = ReadLine();
            RecordSetTel(pR, pLine);
    
            pLine = ReadLine();
            RecordSetPS(pR, pLine);
            
            pLine = ReadLine();
    
            ListAdd(pR);
        }
    
        CloseFile();
    }
    

    这段代码也很简单,通过文件操作接口把book.txt文件中的数据读出,填进Record数据结构,之后添加到数据链表中。此时,执行查找方法打印出全部的数据,看看是不是之前的数据都被恢复了呢?

    这样,我们一个完整的项目就完成了。

    完整的代码请在下面这个路径中获取:https://github.com/breakerthb/TelBook.git

    我是天花板,让我们一起在软件开发中自我迭代。
    如有任何问题,欢迎与我联系。


    上一篇:21天C语言代码训练营(第十五天)
    下一篇:21天C语言代码训练营(第十七天)

    相关文章

      网友评论

      • 9bde52cf824f:请教一下,如果程序窗口被关闭而非0键退出,是否意味着内存的释放要交给操作系统来完成?
        另外,此时也无法完成通讯录保存的功能了。这个有什么办法解决?
        9bde52cf824f:@天花板 好的,谢
        天花板:@Glory_D 这个的确是交给系统去回收资源。至于通讯录的保存,可以通过响应程序退出的事件去完成。或是在程序运行中随时保存。
      • 96eb34f36142:请问?readline函数里 pBuf[0] = 0; 和pBuf[strlen(pBuf) - 1] = 0;是什么意思?
        天花板:@幼杀_ 字符串必须以'\0'结尾
      • 54d8264f38ac:版主,很久没有见到你更新了!你更新的,很适合那些大一学习C语言的小屁孩用
      • e186cec644d1:可以,已关注

      本文标题:21天C语言代码训练营(第十六天)

      本文链接:https://www.haomeiwen.com/subject/rminkttx.html