深圳市华胄科技有限公司 >> MCU专题 >> 单片机编程


单片机c语言,10小时学会C 语言 (九)



提交者 电子007  在  2008-3-17 15:46:51 

上一篇 下一篇
单片机c语言,10小时学会C 语言 (九)


第九章 档案存取


前面几章所写的程序,都是将结果直接显示在屏幕上,若有输入的数值,则利用键盘输入,想要知道程序执行的结果,就要再执行一次。 本章则是将程序执行的结果存成档案,存好的档案,你可以直接显示出来看,或者是由程序直接读取数据文件,当作是输入的数值,经运算后,再另存档案。


◎ 档案的观念


我们的数据及程序,都是以档案的型式存在磁盘驱动器中。每一种应用程序通常会使用自定的格式来存取它的数据文件,应用程序之间如果没有互相支持,就不能读取对方所产生的数据文件,例如:PEII 这个 DOS 下的文书处理器,就不能读取 WORD 所编辑出来的档案。


在磁盘驱动器中的档案可能很多,在使用时,我们必须先指定要处理档案的名称,作「开启档案」的动作,再依程序设计的格式存取档案内的数据,处理完后,则要「关闭档案」。


为什么要这么麻烦呢?因为,我们在作档案存取时,是去呼叫系统程序所提供的程序模块,在「开启档案」后,系统会预置一些内存空间来存这个开启的档案。你在做档案数据的处理时,系统并不一定会马上将结果存回磁盘,它等预置的记忆体内的数据都处理完时,才会将数据存入磁盘。所以在使用完档案之后,就要作「关闭档案」的动作,这样,系统才知道你已经不再使用这个档案了,而将预置内存内尚未储存的数据,存入磁盘,再收回预置的内存,供其它程序使用。如果,你不作「关闭档案」的动作,那程序就会一直占用住那一块内存,形成内存的浪费,此外,处理档案不正常的结束,可能使新增的数据流失,还可能使磁盘驱动器的档案位置配置表(FAT,File Allocation Table)发生失去链接(Lost Chain) 或是交错连结(Cross Link)的状况。所以,要养成好习惯:在程序中,只要有「开启档案」,就要有对应的「关闭档案」。


◎ 档案的开启和关闭


要开启档案时,可以用 fopen 。其格式如下:
┌────────────────────────────────────────────────────────┐
│ FILE *fp; │
│ fp=fopen("文件名称","存取模式"); │
└────────────────────────────────────────────────────────┘


在这里,fp 是一个指针,它指向 FILE 结构变量。FILE 结构内存着一些关于档案的信息,如:档案位置指示,数据传输缓冲区的长度及其在内存中的地址等等,通常我们可以不用去理会这些数值,只要会使用 C 所提供的档案处理函式,就可以了。FILE *fp; 中的 fp 通常称为档案指标。在使用 C 所提供的档案处理函式时,只要指定好档案指标,就是对那个已开启的档案做相对应的处理。fopen() 函式的两个参数,第一个是"文件名称",也就是要处理的文件名称,如果不在所执行的目录,就要指定档案的全名,也就是要包含路径。


第二个参数是"存取模式",有下列字符串可供选择:
存取模式 意 义
==== ============================
r 开启一存在档案仅供读取使用。当档案不存在时,将传回错误。
w 开启档案仅供写入。当档案不存在时,会产生新档。
a 开启一个档案仅供增添数据。当档案不存在时,会产生新档。
r+ 开启一存在档案供读/写使用。当档案不存在时,将传回错误。
w+ 开启一档案供读/写使用。当档案不存在时,会产生新档。
a+ 开启一档案供读取及增添数据。当档案不存在时,会产生新档。
==== ============================


另外,还可以再加上 b ,表示以二进制的模式来存取数据文件。例如:
fp1 = fopen("letter.txt","w");
fp2 = fopen("c:\\work\\test.txt","a+");
fp3 = fopen("score.dat","r");
fp4 = fopen("database.dat","w+b");


要开启档案在使用完毕后,可以用 fclose 来关闭 。其格式如下:
┌──────────────────────────────────────────────────────┐
│ fclose( 已开启的档案指标 ); │
└──────────────────────────────────────────────────────┘
如: fclose( fp );


对于已经关闭的档案,如果还要再使用,则必须重新开启。


◎ 档案的写入


要将数据输出到档案时,可以用 fprintf 。其格式如下:
┌───────────────────────────────────────────────────────┐
│ fprintf( fp, "控制字符串", 表达式1, 表达式2, ...); │
└───────────────────────────────────────────────────────┘
fprintf() 的格式如同 printf() ,只是输入参数中的第一个参数必须是档案指标,也就是指定出 fprintf() 要输出到那一个档案。有关 printf() 请参考第四章。


以下是课本的范例:将使用者输入的交易数据,编排成一份报表档案。
┌────────────────────────────────────────────────────────────────┐
│record.c │
├────────────────────────────────────────────────────────────────┤
1│#include /* 宣告 printf, scanf, fopen,fprintf...*/ │
2│#include /* 宣告 strcmp() 的原型 */ │
3│ │
4│void line(FILE *fp) /* 列出分隔线 */ │
5│{ │
6│ int i; │
7│ for( i=0 ; i<60 ; i++ ) │
8│ fprintf( fp, "-" ); │
9│ fprintf( fp, "\n" ); │
10│} │
11│ │
12│void main(void) │
13│{ │
14│ FILE *fp; /* 档案指标 */ │
15│ char filename[20]; /* 输出报表的文件名 */ │
16│ char client[40]; /* 交易对象名称 */ │
17│ float amount; /* 交易金额 */ │
18│ float total=0; /* 总金额 */ │
19│ │
20│ printf("File to record the amount : "); │
21│ scanf("%19s", filename ); /* 读取输出报表文件名 */ │
22│ fp = fopen( filename, "w"); /* 开启报表文件 */ │
23│ if( fp == NULL ) /* 判断是否开启成功 */ │
24│ printf("\aCannot open %s for output!\n",filename); │
25│ else │
26│ { /* 开启成功 */ │
27│ line( fp ); │
28│ printf("Client : "); │
29│ scanf("%39s", client); │
30│ for( ; strcmp(client, "end") != 0 ; ) /* clinet=="end" */ │
31│ { /* 时,循环结束 */ │
32│ printf("Amount = "); │
33│ scanf("%f", &amount); │
34│ total = total + amount ; │
35│ fprintf( fp, "%-40s $%f\n", client, amount); │
36│ │
37│ printf("Client : "); │
38│ scanf("%39s", client); │
39│ } │
40│ line( fp ); │
41│ fprintf( fp, "%-40s $%f\n", "***** Total", total ); │
42│ line( fp ); │
43│ } │
44│ fclose(fp); /* 关闭报表文件 */ │
45│} │
├────────────────────────────────────────────────────────────────┤
│File to record the amount : test │
│Client : Nanya_College │
│Amount = 9876.54 │
│Client : ABC_Company │
│Amount = 1234.56 │
│Client : IJK_lmn_... │
│Amount = 2323.23 │
│Client : Xyz.... │
│Amount = 2222.20 │
│Client : zzzzzz │
│Amount = 1111.10 │
│Client : end │
└────────────────────────────────────────────────────────────────┘
test 档案内容
┌────────────────────────────────────────────────────────────────┐
│------------------------------------------------------------ │
│Nanya_College $9876.540039 │
│ABC_Company $1234.560059 │
│IJK_lmn_... $2323.229980 │
│Xyz.... $2222.199951 │
│zzzzzz $1111.099976 │
│------------------------------------------------------------ │
│***** Total $16767.630859 │
└────────────────────────────────────────────────────────────────┘
因为我们是用 scanf() 来读取字符串的,而 scanf() 会把空格符当成是数据的分隔,所以在输入客户名称时以底线代替空白。(这也是 scanf() 的缺点之一)第 30 行,循环以 strcmp(client, "end") != 0 作为结束的条件判断。其中,strcmp 是 TC 的内建函式,可用来比较两个字符串是否相等,若相等,则传回 0 ,否则传回非 0 值。所以当使用者输入客户名称为 "end" 时, strcmp 会传回 0,而结束 for 循环。


◎ 档案的读取


要读取档案内的资料时,可以用 fscanf 。其格式如下:
┌──────────────────────────────────────────────────────┐
│ fscanf( fp, "控制字符串", &变量1, &变量2, ...); │
└──────────────────────────────────────────────────────┘
fscanf() 的格式如同 scanf() ,只是输入参数中的第一个参数必须是档案指标,也就是指定出 fscanf() 要读取那一个数据文件。有关 scanf() 请参考第四章。


以下的范例:读取档案内容,将各个字符与ASCII值一起显示。
┌────────────────────────────────────────────────────────────────┐
│ftoascii.c │
├────────────────────────────────────────────────────────────────┤
1│#include /* 宣告 printf, scanf, fopen,fprintf...*/ │
2│ │
3│void main(void) │
4│{ │
5│ FILE *fp; /* 档案指标 */ │
6│ char filename[20]; /* 读取的文件名称 */ │
7│ char ch=0; │
8│ │
9│ printf("File name : "); │
10│ scanf("%19s", filename ); /* 读取输入档名 */ │
11│ fp = fopen( filename, "r"); │
12│ if( fp == NULL ) /* 判断是否开启成功 */ │
13│ printf("\aCannot open %s !\n",filename); │
14│ else │
15│ for( ; ch != EOF ; ) /* ch == EOF 时,循环结束 */ │
16│ { │
17│ fscanf( fp, "%c", &ch); /* 读取一个字符 */ │
18│ printf("%c = %d\n", ch, ch); │
19│ } │
20│ fclose(fp); │
21│} │
├────────────────────────────────────────────────────────────────┤
│File name : ftoascii.c │
│# = 35 │
│i = 105 │
│n = 110 │
│... ... (省略) │
│} = 125 │
│= -1 │
└────────────────────────────────────────────────────────────────┘


第 15 行,循环以 ch != EOF 作为结束的条件判断。其中,EOF 是一个字符,表示档案结束(End Of File)的字符。所以当 fscanf 读取到档案结束字符时,循环就会结束执行。


以下是课本的范例:读取档案内容,并将档案行距加倍后,另存新档。
┌────────────────────────────────────────────────────────────────┐
│2space.c │
├────────────────────────────────────────────────────────────────┤
1│#include /* 宣告 printf, scanf, fopen,fprintf...*/ │
2│ │
3│void main(void) │
4│{ │
5│ FILE *fpi, *fpo; /* 档案指标 */ │
6│ char filename[20]; /* 读取的文件名称 */ │
7│ char ch=0; │
8│ │
9│ printf("File to be read : "); │
10│ scanf("%19s", filename ); /* 读取输入档名 */ │
11│ fpi = fopen( filename, "r"); /* 开启输入档案 */ │
12│ if( fpi == NULL ) /* 判断是否开启成功 */ │
13│ { │
14│ printf("\aCannot open %s !\n",filename); │
15│ return ; /* 结束 main() 函式 */ │
16│ } │
17│ │
18│ printf("File to be written : "); │
19│ scanf("%19s", filename ); /* 读取输出档名 */ │
20│ fpo = fopen( filename, "w"); /* 开启输出档案 */ │
21│ if( fpo == NULL ) /* 判断是否开启成功 */ │
22│ { │
23│ printf("\aCannot open %s for output!\n",filename); │
24│ fclose(fpi); /* 已开的 fpi 在结束前要先关闭 */ │
25│ return ; /* 结束 main() 函式 */ │
26│ } │
27│ │
28│ for( ; ch != EOF ; ) │
29│ { │
30│ fscanf( fpi, "%c", &ch); /* 读取一个字符 */ │
31│ fprintf( fpo, "%c", ch); /* 写入一个字符 */ │
32│ if( ch == '\n') /* 如果读到跳行字符 */ │
33│ fprinf( fpo, "\n"); /* 就再跳一行 */ │
34│ } │
35│ │
36│ fclose(fpo); /* 关闭输出档(后开先关) */ │
37│ fclose(fpi); /* 关闭输入档(先开后关) */ │
38│} │
├────────────────────────────────────────────────────────────────┤
│File to be read : test │
│File to be written : doubled │
└────────────────────────────────────────────────────────────────┘
double 档案内容
┌────────────────────────────────────────────────────────────────┐
│------------------------------------------------------------ │
│ │
│Nanya_College $9876.540039 │
│ │
│ABC_Company $1234.560059 │
│ │
│IJK_lmn_... $2323.229980 │
│ │
│Xyz.... $2222.199951 │
│ │
│zzzzzz $1111.099976 │
│ │
│------------------------------------------------------------ │
│ │
│***** Total $16767.630859 │
│ │
└────────────────────────────────────────────────────────────────┘
┌──────────────────── Help ──────────────────────┐
│ fopen: opens a stream │开启一个「档案流」。
│ │
│ FILE *fopen(const char *filename, │fopen 的语法
│ const char *mode); │
│ │
│ Prototype in stdio.h │必须 #include
│ │
│ Returns a pointer to the newly open stream if │若成功则传回开启档案的指标
│ successful; else it returns NULL. │否则传回 NULL (空指标)
│ │
│ See also fclose creat open │相关指令
│ dup ferror _fmode │
│ rewind setbuf setmode │
└────────────────────────────────────────────────┘
┌────────────────── Help ────────────────────────┐
│ fclose: closes a stream │关闭一个「档案流」。
│ │
│ int fclose(FILE *fp); │fclose 的语法
│ │
│ Prototype in stdio.h │必须 #include
│ │
│ Returns 0 on success; it returns EOF if any │若关闭成功则传回 0 ,
│ errors are detected. │发生错误则传回 EOF 字符。
│ │
│ See also fflush flushall │相关指令
│ fopen close fcloseall │
└────────────────────────────────────────────────┘
┌─────────────────── Help ───────────────────────┐
│ fprintf: sends formatted output to a stream │将格式化的数据输出到档案流
│ │
│ int fprintf(FILE *fp, const char *format, ...);│fprintf 的语法
│ │
│ Prototype in stdio.h │必须 #include
│ │
│ Uses the same format specifiers as printf, │使用方法同 printf(),
│ but fprintf sends output to the specified │只是将结果输出到指定的
│ stream fp. fprintf returns the number of bytes │档案指标 fp 。
│ output. In event of error, it returns EOF. │
│ │
│ See also putc fscanf │相关指令
└────────────────────────────────────────────────┘
┌──────────────────── Help ──────────────────────┐
│ fscanf: performs formatted input from a stream │由档案流读取格式化的数据
│ │
│ int fscanf(FILE *fp, const char *format, ...); │fscanf 的语法
│ │
│ Prototype in stdio.h │必须 #include
│ │
│ Returns the number of input fields success- │使用方法同 printf(),
│ fully scanned, converted, and stored; the │只是由指定的档案流 fp 读入
│ return value does not include unstored │格式化的数据。
│ scanned fields. │
│ │
│ See also getc fprintf scanf │相关指令
└────────────────────────────────────────────────┘
┌─────────────────── Help ───────────────────────┐
│ strcmp: compares s2 to s1 │比较两个字符串
│ │
│ int strcmp(const char *s1, const char *s2); │strcmp 的语法
│ │
│ Prototype in string.h │必须 #include
│ │
│ Returns a value that is < 0 if s1 is less than │如果 s1 < s2 则传回值 < 0
│ s2; == 0 if s1 is the same as s2; > 0 if s1 is │如果 s1 = s2 则传回值 = 0
│ greater than s2. Performs a signed comparison. │如果 s1 > s2 则传回值 > 0
└────────────────────────────────────────────────┘
┌────────────────── Help ────────────────────────┐
│ gets: gets a string from stdin │由 stdin 读取字符串
│ │
│ char *gets(char *string); │gets 的语法
│ │
│ Prototype in stdio.h │必须 #include
│ │
│ Collects input from stdin until a newline │由 stdin 读取字符串,直到遇到
│ character (\n) is found. The \n is not │跳行字符 \n 。
│ placed in the string. │\n 不包含在所读入的字符串中。
│ │
│ Returns a pointer to the argument string. │所传回的指针指向参数字符串。
│ │
│ See also ferror getc │相关指令
│ fopen puts │
│ fread scanf │
└────────────────────────────────────────────────┘



单片机教程,五系列(55讲)电子书全集下载

论坛精选:
■ 单片机c语言,10小时学会C 语言 (一)
第一章 C 语言简介与Turbo C 的使用
■ 单片机c语言,10小时学会C 语言 (二)
第二章 C 程序的结构
■ 单片机c语言,10小时学会C 语言 (三)
第三章 常数与变数
■ 单片机c语言,10小时学会C 语言 (四)
第四章 基本输出入函式
■ 单片机c语言,10小时学会C 语言 (五)
第五章 流程图与抉择指令
■ 单片机c语言,10小时学会C 语言 (六)
第六章 循环与自动重复
■ 单片机c语言,10小时学会C 语言 (七)
第七章 数组与指针
■ 单片机c语言,10小时学会C 语言 (八)
第八章 函数与呼叫
■ 单片机c语言,10小时学会C 语言 (九)
第九章 档案存取

1 楼  提交者:Guest 在 2008-3-17 18:52:27
asdasdasd
2 楼  提交者:king 在 2008-3-18 15:55:31
ok
3 楼  提交者:Guest 在 2008-3-18 17:44:02
3ks
4 楼  提交者:浪人 在 2008-3-18 20:55:49
辛苦了
5 楼  提交者:卫立 在 2008-3-18 22:51:55
卡们
6 楼  提交者:木木林 在 2008-3-19 10:19:32
FF
7 楼  提交者:Guest 在 2008-3-19 10:33:40
还好
8 楼  提交者:han2002asd 在 2008-3-19 12:46:47
bv
9 楼  提交者:anny2008 在 2008-3-19 16:59:16
10 楼  提交者:中山盈亮 在 2008-3-20 11:25:03
不错
11 楼  提交者:Guest 在 2008-3-20 18:22:50
休息
12 楼  提交者:goldskin 在 2008-3-20 21:49:44
gan
13 楼  提交者:梦蝶秋 在 2008-3-21 11:48:26
看看 
14 楼  提交者:shw0320 在 2008-3-21 17:25:11
15 楼  提交者:youminbuluo 在 2008-3-21 21:26:09
谢谢分享
16 楼  提交者:理工朱仕勇 在 2008-3-21 22:05:40
17 楼  提交者:理工朱仕勇 在 2008-3-21 22:05:46
18 楼  提交者:高臣 在 2008-3-22 13:20:26
学习
19 楼  提交者:luxs 在 2008-3-22 13:59:10
谢谢分享
20 楼  提交者:liuyiqiangqq 在 2008-3-22 21:55:03
21 楼  提交者:Guest 在 2008-3-22 23:39:41
good hao
22 楼  提交者:Guest 在 2008-3-23 0:29:20
23 楼  提交者:Guest 在 2008-3-23 23:11:42
dftretr
24 楼  提交者:Guest 在 2008-3-25 11:39:41
好东东
25 楼  提交者:有点意思 在 2008-3-26 17:07:00
hao`
26 楼  提交者:Guest 在 2008-3-27 11:37:10
27 楼  提交者:小雷圣 在 2008-3-27 23:53:46
28 楼  提交者:dalianshide 在 2008-3-28 0:40:45
sdf
29 楼  提交者:sjf_5566 在 2008-3-29 11:07:12
回帖是一种美德
30 楼  提交者:frank 在 2008-3-29 14:18:52
无内容
上一篇 下一篇
当前第〖1〗页 共有23页 转到第 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23