已阅读5页,还剩23页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第9章 标准输入输出 输入输出是指基于标准输入输出库实现的系统调 用。由于用户经常需要进行这方面开发,系统提 供了丰富的函数,并封装成库。使用该库,可以 解决大部分输入输出问题。本章将详细讲解标准 输入输出的基本操作、非格式化输入输出和格式 化输入输出。 9.1 标准输入输出的基本操作 与上一章中介绍的输入输出函数不同,标准输入 输出操作是通过文件控制结构FILE进行的。文 件控制结构中包含处理文件所需的全部信息,例 如文件名、文件当前的读写位置、用于该文件读 写的内存缓冲区位置等。打开文件时,系统会在 内存中自动建立该文件的控制结构。关闭文件时 ,文件控制结构被释放。在对文件进行操作之前 ,要首先获取文件的指针,即指向文件控制结构 的指针,后续操作都通过该指针进行。 9.1.1 打开文件 操作文件之前要打开文件,打开文件的函数为fopen ,其一般形式为: FILE *fopen(const char *filename, const char *modes); 其中,filename表示要打开的文件名,可以是文件名 字符串的首地址,也可以是双引号引起来的文件名 字符串;modes表示打开方式,取值如表所示。 参数说明 r只读,文件必须已存在 w只写,如果文件不存在则创 建新文件,如果文件已存在则替换文件原有内容 a在文件末尾追加,如果文件不存在则创 建新文件 r+读和写,文件必须已存在 w+ 读和写,如果文件不存在则创 建新文件,如果文件已存在则替换文件原有内 容 a+读和追加,如果文件不存在则创 建新文件 9.1.1 打开文件 如果文件成功打开,则fopen函数返回一个文件 指针;如果文件不存在或由于其他原因而没有成 功打开,则返回NULL,并将错误码存在errno之 中。errno是一个整型变量,后面将会详细介 绍。 例如打开当前目录下的hello.c文件。 FILE * fp; fp = fopen(“./hello.c“, “r“); 上面的代码中首先定义了一个文件指针,然后以 只读方式打开文件。如果文件打开成功,文件的 指针存在变量fp之中。 9.1.2 关闭文件 对文件操作完成后,应该关闭文件,这样可以释放所占用的资源。 关闭文件的函数为fclose,其一般形式为: int fclose(FILE *fp); 其中,参数fp为要关闭文件的指针。如果文件成功关闭,则fclose函 数返回0。在该函数返回前,系统会将缓冲区内的数据全部写入文件 中;如果文件关闭时出错,如传给它的为一个无效文件指针,则返 回EOF,并将错误码存在errno之中。EOF的定义在头文件stdio.h之 中,如下所示: 132 /* End of file character. 133 Some things throughout the library rely on this being -1. */ 134#ifndef EOF 135 # define EOF (-1) 136 #endif 注意:132表示该代码在stdio.h中的位置。 可以看到,EOF的值为-1。 【实例9-1】下面编写一个程序,来说明文件打开与关闭函数的使用 方法。( example1.c ) 9.1.3 清空缓冲区 刷新缓冲区用于将缓冲区中的数据清除,Linux 提供fflush和fpurge来完成该工作,他们的一般形 式为: int fflush(FILE *fp); int fpurge(FILE *fp); fflush函数将缓冲区中的数据写入到磁盘文件或 输出到用户终端,同时清空缓冲区;fpurge函数 将缓冲区中的数据直接清除,包括尚未读取或写 入的数据。 9.1.4 设置缓冲区属性 根据缓冲区操作时机,缓冲区的类型有下面三种: 全缓冲:缓冲区被填满后才执行输入输出操作,将 数据写入到磁盘文件或输出到用户终端; 行缓冲:缓冲区中填入换行符时,执行输入输出操 作; 无缓冲:不对数据进行缓存,标准错误输出stderr一 般就是无缓冲的,这可以使错误信息尽快地显示出 来。 缓冲区的大小和类型等都可以通过函数来设置。打 开文件后,用户可以使用下面的函数来设置自己的 文件缓冲区,而不使用fopen函数打开文件设定的默 认缓冲区。 9.1.4 设置缓冲区属性 int setvbuf(FILE *fp, char *buf, int mode, size_t size); 其中,参数fp指向已经打开的文件;buf为用户设定的缓冲区;mode为缓冲 区的类型,可以取为_IOFBF、_IOLBF或_IONBF,分别表示全缓冲、行缓 冲或无缓冲;size为缓冲区的大小。 除setvbuf函数外,还有如下三个函数: int setbuf(FILE *fp, char *buf); int setbuffer(FILE *fp, char *buf, size_t size); int setlinebuf(FILE *fp); setbuf函数中,如果buf设为NULL,缓冲区将被设为无缓冲,否则设置全缓 冲,缓冲区的大小由头文件stdio.h中的常量BUFSIZE决定,默认情况下为 512字节。该函数等价于: setvbuf(FILE *fp, char *buf, buf?_IOFBF:_IONBF, BUFSIZE); setbuffer函数中,如果buf设为NULL,缓冲区将被设为无缓冲,否则设置全 缓冲,缓冲区的大小由参数size决定。该函数等价于: setvbuf(FILE *fp, char *buf, buf?_IOFBF:_IONBF, size_t size); setlinebuf函数将缓冲区设为行缓冲,它等价于: setvbuf(FILE *fp, NULL, _IOLBF, 0); 9.2 非格式化输入输出 非格式化输入输出是指输入或者输出的时候,不 指定数据的格式,只是单纯的读取或者写入数 据。根据读取数据的多少,可以分为单字节、字 符串、数据块三种类型。下面分别介绍这三种类 型的输入输出。 9.2.1 单字节输入输出 单字节输入输出是指从缓冲区读取或者写入一个 字符。Linux提供了fgetc和fputc函数来完成这项 工作。下面依次进行讲解。 1.单字节读取fgetc函数 从文件中读取单个字节可以使用fgetc函数,它的一般形式为: int fgetc(FILE *fp); 该函数的功能是从指定的文件中读一个字节。如果操作成功,函数 返回读到字节,如果出错或读到文件末尾时则返回EOF。文件的控 制结构中记录着当前的读写位置,也称为偏移量(Offset),即读写 位置距离文件开头的字节数。当文件打开时,读写位置为0,每调用 一次fgetc函数,读写位置向后移动一个字节,因此可以连续多次调 用fgetc函数来依次读取多个字节。 注意,函数原型中的返回值为int型,即将字节转换为整型之后返回 的,这主要是为了区分EOF和0xff字节。如果需要保存fgetc的返回 值,一定要保存在int型变量中。 除了上面介绍fgetc函数外,还有一个getchar函数,它是从标准输入 读一个字节,一般形式为: int getchar(); 该函数等价于: int fgetc(stdin); 2.单字节写入fputc函数 向指定的文件写一个字节可以使用fputc函数,它的一般 形式为: int fputc(int c, FILE *fp); 使用该函数时,文件的打开方式必须是可写或可追加 的。每调用一次fputc函数,读写位置向后移动一个字节 ,因此可以连续多次调用fputc函数来依次写入多个字 节。如果文件是以追加方式打开的,每次调用fputc函数 总是将读写位置移到文件末尾,然后将要写入的字节追 加到后面。 同样,函数putchar可以向标准输出写一个字节,一般形 式为: int putchar(int c); 该函数等价于: int fputc(c, stdout); 2.单字节写入fputc函数 【实例9-2】下面编写一个程序,从键盘读入一串字符写到一个文件之中,然后再从文件读 出这些字符输出到屏幕上。( example2.c ) 此时,可以查看文件test的内容: $ cat ./test 在上面的程序中,我们使用了rewind函数,它的作用是将文件的读写位置移至文件的开头 ,其一般形式为: void rewind(FILE * fp); 除了rewind函数外,还有两个函数可以操作文件的读写位置,它们是fseek函数和ftell函 数。fseek函数的原型为: int fseek(FILE *fp, long offset, int whence); 该函数的功能是移动文件的读写位置。其中参数fp为已打开的文件指针;参数offset为移动 的字节数;参数whence的值可以为0、1或2,分别表示从文件开头移动、从当前位置移 动、或从文件末尾移动,这些值也可以使用SEEK_SET、SEEK_CUR、以及SEEK_END来 表示。 例如将读写位置移动到文件的开头: fseek(fp, 0, SEEK_SET); 将读写位置移动到文件的末尾: fseek(fp, 0, SEEK_END); fseek函数调用成功时,返回值为0,如果出错则返回EOF,并将错误码存在errno之中。 ftell函数可以返回当前的读写位置,一般形式为: long ftell(FILE *fp); 如果函数调用成功,则返回当前读写位置,出错则返回EOF,并将错误码存在errno之中。 2.单字节写入fputc函数 【实例9-3】下面编写一个程序,读取文件开头 的第1、3、5、7字节并输出到屏幕。( example3.c ) 9.2.2 字符串输入输出 字符串输入输出是指从缓冲区读取或者写入多个 字符。Linux提供了fgets和fputs函数来完成这项 工作。下面依次进行讲解。 1.字符串读取fgets函数 fgets函数可以从指定的文件中读一行字符到缓冲区中,一般形式为: char *fgets(char *s, int n, FILE *fp); 其中,参数s为缓冲区的首地址,n为读取字符的个数。该函数从文件中读 取字符时,达到以下任何一个条件时,函数将返回。 已经读取到了n-1个字符; 读取到回车符; 读到了文件末尾。 其中读取到回车符时,该字符也会被送入参数s指向的缓冲区之中。读取结 束后,fgets函数会再向缓冲区送入一个NULL字符,以作为字符串结尾。从 上面的可以看到,虽然参数n指定了读取字符的个数,但实际读到得字符串 长度往往比指定的长度要短,这主要是由于读到回车符就结束的缘故。 对于fgets函数来说,回车符是一个特殊字符,但NULL属于普通字符。也就 是说,如果在文件中存在NULL字符,调用该函数之后会作为普通字符读入 ,这样,缓冲区中的NULL字符无法判断是从文件中读取的字符还是自动添 加的结束符,所以该函数只适合读取文本文件,并且文本文件中的所有字 符都应该是可见字符。 【实例9-4】下面编写一个程序,显示文件内容并同时输出行号。 (example4.c ) 2.字符串写入fputs函数 fputs函数可以向指定的文件写入一个字符串,一般形式为: int fputs(const char *s, FILE *fp); 其中,参数s为指向字符数组的指针,或为字符串常量。将字 符串写入到文件时,并不写入字符串结尾的NULL字符。与前 面的fgets函数不同,fputs函数不关心字符串中是否存在回车 符。 【实例9-5】下面使用fgets函数和fputs函数来逐行复制一个文 本文件。( example5.c ) 上面的程序中,使用了feof函数来测试读写位置是否到达文件 末尾,该函数的一般形式为: int feof (FILE *fp); 如果读写位置已经到达文件末尾,则返回1,否则返回0。该 函数在处理二进制文件时特别有用,因为在二进制文件中 EOF为一个合法的数据。 9.2.3 数据块输入输出 数据块,是指一串固定长度的字节,例如一个整型数据、一个结构体,或 一个固定长度的数组等。对文件进行输入输出操作,也可以以数据块为单 位进行。 从文件中读取数据块可以使用fread函数,它的一般形式为: size_t fread(void *ptr, size_t size, size_t n, FILE *fp); 其中,参数ptr为缓冲区的首地址,size为要读取的数据项的长度,n为要读 取的数据项的个数,fp为已经打开的文件的指针。fread函数的功能就是从 文件fp中读取size*n个字节,并保存到缓冲区ptr之中。该函数的返回值为实 际读取的数据项个数。由于读取过程中可能会出错或文件结束,实际读取 的数据项个数小于等于参数n。 注意:如果fp指向的文件以文本方式打开的,则该函数会将回车换+行符转 换为换行符,而如果是以二进制方式打开的,则不进行任何转换。 向文件中写入数据块可以使用fwrite函数,它的一般形式为: size_t fwrite(void *ptr, size_t size, size_t n, FILE *fp); 该函数将ptr指向的缓冲区中的数据写入到由fp指向的文件中,写入的长度 由size和n决定。函数的返回值为实际写入的数据项个数,如果写入过程中 出错,返回值小于n。 9.2.3 数据块输入输出 【实例9-6】下面的例子由两个程序组成,一个 程序将数据保存到文件之中,另一个程序和从文 件中读取数据。( example6.c ) 这样,三个学生的学号和成绩就被保存到了文件 之中。 【实例9-7】下面编写程序,从文件中读取数据 并输出到屏幕。( example7.c ) 可以看到,三个学生的学号和成绩被从文件中读 出并输出到了屏幕上。 9.3 格式化输入输出 格式化输入输出就是将输入或者输出的字符按照规定的格式进行格 式化后再进行输入或者输出。格式化输出可以使用函数fprintf和 printf。 fprintf函数的一般形式为: int fprintf(FILE *fp, const char *format, . ); 其中参数fp为输出文件的指针,format为输出的格式,后面跟输出项 ,该函数的功能是按照指定的格式向文件fp中输出信息。 printf函数的一般形式为: int printf(const char *format, . ); 该函数等价于: int fprintf(stdout, const char *format, . ); 下面对函数中的输出格式进行详细介绍,如下所示: % +/- 0 m.n l 转换字符 输出格式以%号开头,以转换字符结尾,前面使用时都是%号后直 接加转换字符,例如%d、%s等,其实在这两个字符之间还可以插 入一些可选项。 1转换字符 转换字符用来指定输出项的输出形式,如表所 示。 字母输出形式示例 d十进制整数16 o八进制整数77 x十六进制整数0xF u无符号十进制整数10 c单个字符A s字符串ABC e指数形式的浮点数1.230000e-01 f小数形式的浮点数0.123000 ge和f中较短的一种0.123 %百分号本身% 2指定输出精度 在字母d、u、e、f以及g等的前面加字母l,例如 %ld、%le,表示输出长整型(long)或双精度浮 点型(double)。 3指定输出长度 通过m.n的形式可以指定输出数据的长度,其中字母m为输出数据的总字符长度,n为输出数据小数部分 的字符长度。 【实例9-8】输出一个浮点数,要求整个数据占6个字符位置,其中小数部分占4个字符位置。 double x=0.123; printf(“%6.4fn“, x); 输出结果为: 0.1230 【实例9-9】输出一个整数,要求整个数据占8个字符位置。 int x=1234; printf(“%8dn“, x); 输出结果为: 1234 说明:输出结果前面有4个空格。 输出字符串时,也可以使用m.n来指定输出长度,这时字母m为字符串占用的总字符长度,n为实际输出 的字符个数。 【实例9-10】输出一个字符串的前3个字符,但整个字符串占5个字符位置。 char ch=”ABCD”; printf(“%5.3sn“, ch); 输出结果为: ABC 说明:输出结果前面有2个空格。 4空位填零 这一项只在输出数值时有效,当指定时,不使用 的输出位置自动填0;不指定时,这些位置空 白。因为前面我们都没有指定,所以输出结果前 面有空格。 【实例9-11】输出一个整数,在空位处填零。 int x=123; printf(“%06dn“, x); 输出结果为: 000123 5指定输出位置 这一项设置输出结果的对齐方式,默认(+)为右对齐,如果指定为减号时,左对齐。 【实例9-12】使用左对齐和右对齐两种方式输出一个字符串。 char ch=”ABCD”; printf(“%-5.3sn“, ch); printf(“%+5.3sn“, ch); 输出结果为: ABC ABC 格式化输入的函数为scanf,其一般形式为: int fscanf(FILE *fp, const char *format, . ); 该函数的功能是从指定的文件读字符,按照指定的格式转换并赋给后面的参数,后面的参 数一般为地址。 前面使用的scanf函数的一般形式为: int scanf(const char *format, . ); 该函数等价于: int fscanf(stdin, const char *format, . ); 该函数用读入的字符去匹配格式说明中的转换字符,如果成功匹配,就给后面的参数赋值 ,否则就返回,例如转换字符是%d,但读到的却是C。如果遇到不匹配的地方而停止,函 数的返回值会小于赋值参数的个数。 5指定输出位置 关于输入格式下面给出几点说明: (1)格式说明中的空白字符会使scanf函数在读操作时略去输入中的一个或多个空白字符,如下所示: int x, y; scanf(“%d %d“, 参数之间的分隔符为空格,输入数据之间可以用一个或多个空格、TAB或回车进行间隔。 如果格式说明中有非格式字符,则输入时也要输入该非格式字符,如下所示: int x, y; scanf(“%d, %d“, 程序运行时,scanf函数首先读入一个整数,然后将后面输入的逗号剔除,最后读入另一个整数。如果没 有读到逗号,则函数立即返回。 (2)在输入字符数据时,如果格式说明中没有非格式字符,则认为所有输入的字符均为有效字符,如 下所示: char a, b, c; scanf(“%c%c%c“, 输入如下字符: d e f scanf函数会将字母d赋给变量a,空格赋给变量b,字母e赋给变量c。 (3)可以在格式说明中的%和转换字符之间加入一个整数,表示读操作最大位数,如下所示: char str11; scanf(“%10s“, str);/* 只能输入10个字符给字符数组str */ 程序运行时,一旦输入字符个数大于10时,scanf函数就停止读入。 (4)格式化输入时没有精度控制。 5指定输出位置 【实例9-13】下面编写一个程序,对输入的整数进行累加。(example13.c) 上面列出的四个格式化输入输出函数有对应的可变参数函数,即参数不是以“.”的形式传 进入,而是通过va_list类型传递,函数的一般形式为: int vfprintf
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 【正版授权】 IEC 60061-1:1969/AMD65:2025 EN-FR Amendment 65 - Lamp caps and holders together with gauges for the control of interchangeability and safety - Part 1: Lamp caps
- 【正版授权】 IEC 62849:2025 EN Performance evaluation methods of robots for household and similar use
- 古代波斯帝国的兴衰与历史影响
- 床位预订协议书模板
- 工厂土地转租协议书
- 差额补偿协议书范本
- 工地饭堂合同协议书
- 工程总包价合同范本
- 工程队用工合同范本
- 小区围墙改造协议书
- 药剂证书考试题库及答案
- 前庭大腺囊肿课件
- 四川美术学院2025年设计考研《64中外设计史》真题与试题解析及答案
- 江苏省2026年普通高中学业水平合格性考试英语仿真模拟卷01(春季高考适用)(全解全析)
- 2025年中铁党建考试试题及答案
- 雨课堂学堂云在线《医患沟通与调适(广州医大 )》单元测试考核答案
- 专科会计职业生涯规划
- 2025届高三八省联考(四川)政治试题及答案
- 制药行业质量意识培训
- 2025贵州毕节织金县公安局面向社会招聘警务辅助人员140人考试笔试备考试题及答案解析
- 购物中心招商调整汇报
评论
0/150
提交评论