文档章节

第14章 结构和其他数据形式 14.8 把结构内容保存到文件中

idreamo
 idreamo
发布于 2017/03/25 07:08
字数 1202
阅读 18
收藏 0

由于结构能保存多种多样的信息,所以它是建立数据库的重要工具。一个结构中保存的整套信息用术语来说就是一个记录,单个的项目称为字段。

或许最显而易见也是最没效率的保存方法就是使用fprintf()。

一个更好的解决方法是使用fread( )和fwrite( )函数以结构的大小为单元进行读写。这些函数在读写时使用了与程序所使用的相同的二进制表示法。例如:

fwrite(&primer,sizeof(struct book),1,pbooks);

这个结构定位到结构primer的开始地址,将该结构的所有字节复制到与pbooks相关联的文件中。sizeof()告诉函数要复制的每一块有多大,1表示只需要复制1块。具有同样参数的fread()函数将把一个结构大小的数据从文件复制到&primer指向的位置。简单地说,这些函数一次性读写整个记录,而不是一个字段。

14.8.1  一个结构保存的实例

我们改写程序清单14.2中的程序,把书名保存到一个名为book.bat的文件中。如果该文件存在,程序显示文件当前内容,然后允许您向文件中添加内容。程序清单14.14即是新版本。

/*booksave.c  --把结构内容保存到文件中*/

#include <stdio.h>
#include <stdlib.h>
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 10
struct book {
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};

int main(void)
{
    struct book library[MAXBKS];  /*结构数组*/
    int count = 0;
    int index, filecount;
    FILE *pbooks;
    int size = sizeof(struct book);

    if((pbooks=fopen("book.bat","a+b"))==NULL)
    {
        fputs("Can't open book.bat file \n",stderr);
        exit(1);
    }

    rewind(pbooks);    /*定位到文件开始处*/

    while(count<MAXBKS && fread(&library[count],size,1,pbooks)==1)
    {
        if(count==0)
            puts("Current contents of book.dat: ");
        printf("%s by %s :$%.2f\n",library[count].title,library[count].author,library[count].value);
        count++;
    }

    filecount=count ;
    if(count==MAXBKS)
    {
        fputs("The book.dat file is full.",stderr);
        exit(2);
    }

    puts("Please add new book titles.");
    puts("Press [enter] at the start of a line to stop.");
    while(count < MAXBKS && gets(library[count].title != NULL && library[count].title[0]!='\0'))
    {
        puts("Now enter the author.");
        gets(library[count].author);
        puts("Now enter the value");
        scanf("%f",&library[count++].value);
        while(getchar()!='\n')
            continue;
        if(count<MAXBKS)
            puts("Enter the next title.");
    }
    if(count > 0)
    {
        puts("Here is the list of your books: ");
        for(index=0;index<count;index++)
            printf("%s by %s: $%.2f\n",library[count].title,library[count].author,library[count].value);
        fwrite(&library[filecount],size,count-filecount,pbooks);
    }
    else
        puts("No books? Too bad.\n");

    puts("Bye.\n");
    fclose(pbooks);

    return 0;
}

14.8.2  程序要点

首先,使用“a+b"模式打开文件。a+部分允许程序读入整个文件,并向文件末尾添加数据。b是ANSI表示程序要使用二进制文件格式的方法。

我们选择二进制模式是因为fread()和fwrite()要使用二进制文件。的确,结构中有些内容是文本,但value成员不是文本,如果使用文本编辑器来查看book.dat,文本部分会正确显示,但是数字部分不可读,甚至还可能导致文本编辑器显示乱码。

命令rewind()确保文件指针处于文件开始位置,为开始读取做好准备

最开始的那个while循环每次把一个结构读到结构数组中,当数组满或文件读完时停止。变量filecount用来保存已读结构的数目。

接下来的while循环提示并获取用户输入。当数组 满或用户在一行开始就按下enter,退出循环。注意,开始循环时,变量count具有前面那个循环之后的值。这将把新的输入项添加到数组 的末尾。

然后,for循环打印来自文件和来自用户的数据。因为文件是以追加模式打开的,所以将把新写入的内容追加到已有内容的后面。

我们本来可以使用一个循环每次把一个结构添加到文件末尾。但是我们决定使用fwrite()一次写入多个块的功能。表达式count-filecount得出要加入的新书的数目,函数调用fwrite()把这么多数目的book结构大小的块写入到文件中。表达式library[filecount]是数组中第一个新输入的结构的地址,因此复制就从这一点开始。

这个例子或许就是将结构写入文件和取回结构的最简单的方法。但是它浪费了空间,因为结构中没使用的部分也被保存了。这个结构的大小是2*40*sizeof(char)+sizeof(float),在我们的系统中占84字节,事实上,不是每一个输入都需要这么多的空间。但是每个数据块具有同样大小,会使取回数据时更加容易。

© 著作权归作者所有

idreamo
粉丝 17
博文 139
码字总数 224743
作品 0
青岛
产品经理
私信 提问
《Oracle数据库基础与应用教程》一本Oracle入门教材

《Oracle数据库基础与应用教程》书全面讲述了Oracle数据库的日常管理工作内容。全书共14章,包含Oracle简介和安装、Oracle客户端、管理Oracle环境、Oracle体系结构、管理Oracle存储结构、SQL...

airfish2000
2016/08/30
0
0
分享《Essential Linux Device Drivers》中文版高清电子版

新浪微博 @宋宝华Barry 在@微盘 分享了 Prentice.Hall出版社《Essential.Linux.Device.Drivers》中文版高清电子版 "宋宝华精通LINUX设备驱动开发.pdf" http://t.cn/zYjS7sh 目  录 第1章 ...

21cnbao
2013/02/28
0
0
盼望着,盼望着,快来吧。。我的新书。。。。

昨天刚刚发工资,又正好收到邮件说是那本《 庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术 》已经到货了,赶紧上china-pub下订单购买了,同时还买了另一本《ASP.NET 3.5从入门到精通:基于...

niunan
2009/04/15
0
0
每周一书《Oracle 12 c PL(SQL)程序设计终极指南》

本周为大家送出的书是《Oracle 12 c PL(SQL)程序设计终极指南》,此书由机械工业出版社出版, 孙风栋,王澜,郭晓惠 著。 内容简介: 《Oracle 12c PL/SQL程序设计终极指南》志在打造PL/SQL领...

zting科技
2017/12/11
0
0
好书推荐.flask.>

图书封面: 书籍简介: 1. 学习Flask应用的基本结构,编写示例应用; 使用必备的组件,包括模板,数据库,Web表单和电子邮件支持; 使用包和模块构建可伸缩的大型应用; 实现用户认证,角色和个人资...

满满李
2016/06/03
97
0

没有更多内容

加载失败,请刷新页面

加载更多

Proxmox VE技巧 移除PVE “没有有效订阅” 的弹窗提示

登陆的时候提示没有有效的订阅You do not have a valid subscription for this server. Please visit www.proxmox.com to get a list of available options. 用的是免费版的,所以每次都提示......

以谁为师
26分钟前
2
0
Java设计模式之外观模式(门面模式)

什么是外观模式   外观模式(Facade),他隐藏了系统的复杂性,并向客户端提供了一个可以访问系统的接口。这种类型的设计模式属于结构性模式。为子系统中的一组接口提供了一个统一的访问接口...

须臾之余
43分钟前
4
0
mysql免安装版,服务无法启动没有抱任何错误

1.解压 2.新建my.ini [mysqld]# Remove leading # and set to the amount of RAM for the most important data# cache in MySQL. Start at 70% of total RAM for dedicated server, e......

榴莲黑芝麻糊
今天
2
0
Qt编写安防视频监控系统3-通道交换

一、前言 最开始写通道交换的功能的时候,走了很多弯路,比如最开始用最初级的办法,触发交换的时候,先关闭视频,然后设置新的url重新打开视频,这样处理非常低级而且耗内存还卡还很慢,毕竟...

飞扬青云
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部