版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
程序设计基础第9章文件目
录9.1文件处理需要解决的问题及相关概念
9.1.1文件基础知识
9.1.2缓冲文件系统和非缓冲文件系统9.2打开与关闭文件9.3读写文件内容9.1文件需要解决的问题和相关概念文件是存储在外存上的数据集合,文件中的数据能永久保存。操作系统以文件的形式管理数据,怎么用程序读写文件内容呢?例如,要修改文件内容。先把文件打开,将文件内容输入到内存变量中,在变量中修改后,再从变量输出到文件,最后把打开的文件关闭。这就涉及到一些概念及问题,最基本的概念是读和写。文件数据到内存叫”读”,也叫”读入”或”输入”,文件所在地方,例如磁盘,是外设,是”外”,内存是”内”,数据的流向是从外到内。读对应的关键词有get、scanf、read,相对应的读文件函数有fgetc、fgets、fsanf、fread等。内存数据到文件叫”写”,也叫”写出”或”输出”,数据的流向是从内到外。写对应的关键词有put、printf、write,相对应的写文件函数有fputc、fputs、fprintf、fwrite等。文件执行的通用操作是:
打开文件——调用读写相关函数——关闭文件常见应用软件中的”新建”和”打开”命令,都含有这里”打开”的意义。9.1文件需要解决的问题和相关概念其他相关问题有:①
文件基础知识有哪些?②
放在外设上的文件和内存怎么关联?③
文件怎么打开和关闭?④
什么是文件缓冲区?⑤
什么是文件指针?⑥
二进制文件和文本文件的差别是什么?⑦
怎么定位文件读写位置,能前后跳跃读写还是只能从头读写到尾?⑧
顺序文件和随机文件的区别是什么?⑨
标准输入/标准输出(键盘/显示器)怎么对待?⑩
文件读写过程中,哪些步骤是自动进行的,哪些是编程者需要处理的?涉及到哪些函数和数据结构等等。9.1.1文件基础知识1文件和文件名操作系统以树形目录结构(文件夹)管理文件,无论编程读或写文件,首先考虑的是这个文件存储在哪个位置、叫什么名字,这就是文件定位方式——文件标识。下图以Windows操作系统为例,解释文件标识。图中三部分合在一起是文件标识,也叫文件名,路径中目录也叫文件夹9.1.1文件基础知识2程序文件和数据文件从程序设计的角度,文件归类为程序文件和数据文件。(1)程序文件程序文件包括目标文件(文件后缀为.obj或.o)、可执行文件(文件后缀为.exe)等。这类文件的内容是程序代码,一般不在C源文件中打开处理程序文件,除非复制文件等少数情况。(2)数据文件文字、图像、声音、表格等都是数据,程序运行时键盘输入的数据、输出到屏幕的数据、程序处理的中间结果等也是数据,都可以用文件保存。数据文件扩展名说明文件系统下,纯文本文件(文件后缀.txt)、word文件(.doc、.docx)、图像文件(.bmp、.png、.jpg等)、声音文件(.mp3、.wav等)都是数据文件。数据文件必须用一个程序打开处理它,这些现有的文件类型若关联了已安装到操作系统下的程序,当双击文件时,自动运行关联的程序并把对应的数据文件打开,数据内容导入内存,至于数据到内存后怎么处理,就是程序的事。程序文件菜单中”新建”和”打开”命令,都是打开一个数据文件。9.1.1文件基础知识C语言源文件中指定的文件名举例:①
"D:\\temp\\ch09\\file01.dat",带绝对路径的文件名。若文件名中带路径,路径分隔符'\'要变成"\\",因为单斜杠'\'还有一个含义是转义字符,双斜杠"\\"才能转义成单斜杠'\'。尽量不用带绝对路径的文件名,程序是要给最终用户使用而不是给程序员用的,最终用户把程序文件和对应要处理的数据文件放在什么地方应该是用户决定。②
".\\..\\a.txt",带相对路径的文件名。1个点表示当前文件夹,2个点表示上一级文件夹。这个文件名意思是:当前文件夹的上一级文件夹下的a.txt文件。③
"file2.dat",不带路径的文件名。本章例题涉及文件名的时候,要处理的文件都与C源文件放在同一个文件夹下(当前文件夹下)。9.1.1文件基础知识C语言源文件中指定的文件名可以不带扩展名C语言打开的文件既可以是程序文件也可以是数据文件9.1.1文件基础知识3文本文件和二进制文件根据文件内数据内容,可将文件分为两大类:文本文件和二进制文件。(1)文本文件文本文件内部都是字符。字符包含数字、不可打印字符、英文字母、简体汉字、繁体汉字、其他国家文字等,字符在计算机内部是编码的,1个字符对应1~4字节整数,编码方式不同,对应的字节数也不同,编码方式又叫字符集。下面介绍一下常见编码方式。ASCII编码:美国标准信息交换码,单字节编码,包含数字、不可打印字符、英文字母,编码值在0~255之间。(1)文本文件(续)汉字国标码(GB开头)是双字节(或可变多字节,1~4字节)编码,有3个编码方案。GB2312编码:双字节编码,1980年颁布,收录简体汉字6763个和非汉字图形字符682个,兼容ASCII编码。GBK编码:双字节编码,1995年颁布,兼容GB2312,共收录了21003个汉字(包括中日韩汉字及台湾香港使用的繁体字)。GB18030编码:2000年第1次颁布,2005年第1次修订,2022年修订后成为国家强制标准(GB18030-2022),2023年8月强制实施。新版标准共收录汉字88115个,包括近年来群众反映较多的典型人名、地名生僻字等。它是不定长多字节(1~4字节)编码,兼容GBK编码。(1)文本文件(续)BIG5编码:中国台湾香港的繁体字编码。ANSI编码:ANSI的字面意思是美国国家标准学会(AmericanNationalStandardsInstitute),这个组织为字符编码做了很多标准制定工作,后来大家习惯把这类混乱的多字节编码叫ANSI编码。ANSI编码是一个通称,不是确定的某一种编码方式,例如在中文Window操作系统里,ANSI编码默认GB(国标)编码,在中国香港台湾ANSI编码指的是Big5编码,在韩国ANSI编码指的是EUC-KR编码。(1)文本文件(续)Unicode编码:也叫万国码,包括字符集、编码方案等,是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案,不再是各自国家的编码。它为每种语言中的每个字符设定了统一并且唯一的二进制编码,它有四种编码实现方案:UTF-7、UTF-8、UTF-16、UTF-32,最初采用双字节定长编码的UTF-16,但是推广不了,最后可变长的UTF-8出来被广泛接受,Windows下扩展名为txt的文本文件默认编码方式通常是UTF-8。UTF-8编码英文使用1个字节表示,中文3个字节编码。(1)文本文件(续)当包含中文的文本文件向显示器输出,可能由于编码方式不匹配,出现乱码问题。后续在【例题9-3】中给出了处理方案。字符型数据在C语言中并不单指char型,若是ASCII编码的字符,使用char型是对的,char型可以保存单字节字符,也可以保存1个字节整数。用来处理中文这样的多字节字符就不合适了,单个中文字符可以用char型数组保存,scanf和printf中输入输出单个中文字符用%s格式,而不是%c格式,否则会出错。很多字符输入输出函数用int型作为字符型,可以保存4字节编码。例如,fputc和fgetc函数中,字符类型用int型,getchar函数返回字符类型也是int。int类型作为字符型参见9.3.2节。9.1.1文件基础知识3文本文件和二进制文件(2)二进制文件非纯文本文件就是二进制文件。文件内任何数据类型都有,包含字符型、整型、浮点型、自定义数据类型,只要把数据按其在内存中的存储形式,原样存储到文件中,就叫做二进制文件。文本文件和二进制文件的分类跟扩展名无关,若文件内容都是都是字符,无论自定义什么扩展名,它还是纯文本文件。9.1.2缓冲文件系统和非缓冲文件系统C语言中有两种处理文件的系统:缓冲文件系统和非缓冲文件系统。在编译环境提供的标准输入输出头文件stdio.h中,包含了文件处理涉及的宏定义(符号常量)、类型定义、全局变量、函数等,缓冲文件系统和非缓冲文件系统涉及的函数都在内。但是ANSIC标准决定仅采用缓冲文件系统来处理文件。9.1.2缓冲文件系统和非缓冲文件系统1非缓冲文件系统非缓冲文件系统也叫非标准文件系统,依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出。对应的文件函数有open、close、read、write等,都是操作系统下的函数,与C语言本身无关,用它们编写的程序很难跨平台(操作系统)移植。ANSIC标准不再包括非缓冲文件系统。9.1.2缓冲文件系统和非缓冲文件系统2缓冲文件系统缓冲文件系统也叫标准文件系统。ANSIC标准把操作系统下的open、close、read、write等函数封装起来变成C语言的库函数fopen、fclose、fread、fwrite等。只要调用这些f开头的文件处理函数,默认就是应用缓冲文件系统。用缓冲文件系统下的宏定义、类型、函数等编写程序可以跨平台移植。9.1.2缓冲文件系统和非缓冲文件系统在缓冲文件系统中,自动开辟一块内存区,作为文件和变量之间的跳板,叫做文件缓冲区如果只能从文件读数据到变量,文件缓冲区可以叫做输入缓冲区。如果只能从变量写数据到文件,文件缓冲区可以叫做输出缓冲区。如果既可以从文件读数据到变量,也可以将变量中数据写到文件,那么文件缓冲区既是输入缓冲区又是输出缓冲区。9.1.2缓冲文件系统和非缓冲文件系统键盘和显示器也是文件,归类为设备文件。键盘叫做标准输入文件,显示器叫做标准输出文件。Windows操作系统下,键盘输入时用到标准输入缓冲区。从变量输出数据直接显示到屏幕,没有标准输出缓冲区Linux操作系统下,有标准输出缓冲区9.1.2缓冲文件系统和非缓冲文件系统为什么要设置缓冲区呢?
文件在外设上,如磁盘,它是慢速设备,内存是高速设备,如果读写操作每次都直接在文件和变量之间进行,每次都要等待外设打开慢慢传输,效率太低。磁盘文件缓冲系统思路是:读文件时,打开一次外设,从磁盘文件里读入一批数据一次性充满缓冲区,然后从缓冲区中读一定字节到变量。后续每次读文件时,都从缓冲区中读数据到变量,缓冲区中数据慢慢减少,直到缓冲区空,如果文件中还有剩余数据,再去打开磁盘,从文件中读下一批数据充满缓冲区,然后再多次从缓冲区读数据到变量。以此类推,直到文件中内容都读入变量完毕。写文件时,从变量到缓冲区进行多次写操作,等缓冲区写满,一次性将缓冲区数据写入磁盘上的文件。文件缓冲区是文件在内存的替代品,缓冲区代替文件和变量读写,会加快读写速度。缓冲区和文件之间的读写以缓冲区满为标准时,缓冲区刷新方式为满缓冲(全缓冲),读写一次,速度慢,数据量大,所以尽量减少两者之间读写次数。缓冲区和变量之间读写,都在内存,速度快,两者之间可以多次读写。9.1.2缓冲文件系统和非缓冲文件系统缓冲文件系统中,定义了一个结构体数据类型FILE(文件类型)FILE(文件类型)在stdio.h文件中(位于安装目录下的include文件夹)。缓冲区首地址、缓冲区大小、文件读写到哪个位置、文件读写模式、缓冲区剩余多少字节未读、怎么关联文件等等数据需要保存。保存这些信息的变量是FILE类型变量,它所占的内存区叫做文件信息区,需要一个”FILE*”类型指针变量保存文件信息区首地址。这个指针变量或指针变量的值叫文件指针。9.1.2缓冲文件系统和非缓冲文件系统(1)文件类型及文件指针说明typedef
struct_iobuf{
char*_ptr; /*文件读写指针,值在缓冲区首地址和尾地址之间变化*/int_cnt; /*输入时表示文件中剩余未读入变量的字节
=文件大小-离开缓冲区字节*/
/*输出时有缓冲区=缓冲区大小-从变量写到缓冲区的字节*/
/*输出时无缓冲区=0*/char*_base;
/*缓冲区首地址*/int_flag; /*文件状态标志(包括打开、读写模式、关闭、出错等)*/int_file;
/*文件描述符(文件号),关联文件*/int_charbuf;
/*缓冲区是否可读取*/int_bufsiz;
/*缓冲区大小*/char*_tmpfname;
/*临时文件名*/}FILE;
/*提示:库文件中的标识符命名常带下划线开头*/不同的C编译环境提供的文件类型都叫做FILE,其内部成员的名字、个数、作用等细节方面可能不相同,但功能类似。例如,CodeBlocks编译环境里,FILE类型定义如下:9.1.2缓冲文件系统和非缓冲文件系统(1)文件类型及文件指针说明(续)声明一个”FILE*”类型的指针变量,接收文件信息区首地址的方法:FILE*fp=fopen(文件名,…);/*调用fopen函数打开文件,具体见9.2节*/fopen函数调用成功后返回文件信息区的首地址,赋给变量fp之后,fp的值就指向文件信息区,fp的值就是文件指针,指针是地址的形象说法。指针变量名和指针变量的值表达方式一致,所以”FILE*”类型指针变量和它的值都可以叫做文件指针。typedef
struct_iobuf{
char*_ptr; int_cnt;
char*_base;
int_flag;
int_file;
int_charbuf;
int_bufsiz;
char*_tmpfname;
}FILE;
文件类型FILE文件读写时,文件、文件指针、文件信息区、文件缓冲区、变量所占内存区如图9-2所示(每个变量或内存区地址是假想的模拟地址)。如图所示,指针变量fp的值指向文件信息区,信息区成员_base的值是缓冲区的首地址。信息区成员_ptr是文件读写指针,值在缓冲区首地址和尾地址之间变化,初值一般默认是缓冲区首地址。成员_file关联外设上的文件,也叫文件号,是个整数。9.1.2缓冲文件系统和非缓冲文件系统(2)常用库函数缓冲文件系统下的相关函数都是ANSIC标准重新定义的库函数,文件信息区和文件缓冲区的创建也封装在相应库函数内。针对不同操作系统的相关函数封装在一起,重新给个类似的名,绝大部分都是f开头。类型函数名功能打开fopen打开文件读/写fgetc按字符读数据,从缓冲区取1字符数据到变量所在内存区fputc按字符写数据,从变量所在内存取1字符数据到缓冲区fgets按字符串读文件,从缓冲区取1个字符串到变量fputs按字符串写文件,从变量取1个字符串到缓冲区fscanf按格式化方式读文本文件,类似scanffprintf按格式化方式写文本文件,类似printffread按数据块(按指定字节数)读文件fwrite按数据块(按指定字节数)写文件关闭fclose文件关闭刷新缓冲区fflush强制刷新缓冲区移动读写指针,随机读写fseek移动读写指针ftell计算当前读写指针到文件头之间的字节数rewind读写指针回到文件头
读文件结束feof检测是否读文件结束错误处理perror输出错误信息ferror检测是否出错clearerr清除错误信息其他rename文件改名更多……9.1.2缓冲文件系统和非缓冲文件系统(3)文件流和文件指针C语言把所有文件都看作流式文件,即一个个字节(字符),流的基本含义是字节输入输出(文件流、数据流),数据流是队列,无论读或写,只处理一次,不像变量的值可以多次读取。但是,在读写文件时更多的是用流的引申义。文件打开后,获得文件指针,文件指针(文件信息区首地址)相当于数据流的管理员,调用读写函数时,只要指定文件指针和变量,就可以实现两者之间数据读写。文件指针的另一个名字也叫做文件流,简称流。它是流对象,管理数据流,辐射范围包括文件、文件信息区、文件缓冲区,记录读写时数据流中数据变化等信息。流在不同场合含义变化,自己体会。简单点,关于流,要明白这几件事:①
流的本义——数据流。②
流的引申义——文件指针(流对象),是数据流的管理员,也叫流。
③
流的范围——就是文件指针管理范围,也可以想象成数据流的活动范围。9.1.2缓冲文件系统和非缓冲文件系统流的常见说法:①
打开文件,例如,FILE*fp=fopen(文件名,…);这叫做打开一个流(返回一个流),流初始化。9.1.2缓冲文件系统和非缓冲文件系统流的常见说法(续):②
调用读文件函数,如fgetc、fgets、fscanf、fread等,叫做把变量中的数据读入流中。读文件时,数据从流中送达变量,流中数据变化是流对象(文件指针)在操作,细节都被封装在读函数内部隐藏起来(流对象负责把文件来的数据送达缓冲区,并保证缓冲区中有数据与变量对接)。程序员只需知道:它相当于:9.1.2缓冲文件系统和非缓冲文件系统流的常见说法(续):③
调用写文件函数,如fputc、fputs、fprintf、fwrite等,叫做把变量中的数据写到流中。写文件时,数据从变量送达流中。流中数据变化是流对象(文件指针)在操作,细节都被封装在写函数内部隐藏起来(流对象负责接收变量来的数据,有缓冲区,数据先送缓冲区再根据不同情况送达文件,无缓冲区,直接送达文件),程序员只需知道:它相当于:9.1.2缓冲文件系统和非缓冲文件系统流的常见说法(续):④
关闭文件,叫做关闭流。细节同样隐藏在关闭函数内。⑤
读文件时,流对象和读函数内隐藏的细节揭露:如果是磁盘文件,流查看缓冲区,若缓冲区空,流对象负责打开磁盘,一次性从文件读数据充满缓冲区,啥时缓冲区空了,若文件中还有数据未读完,再次打开磁盘,将文件剩余数据充满缓冲区,这种缓冲区刷新方式叫满缓冲。如果文件是设备文件,用户从键盘输入数据,按【Enter】键后,流对象负责将输入数据送入缓冲区,缓冲区刷新方式是行缓冲,以换行结束输入。读文件,是直接从文件缓冲区读,还是打开文件读到缓冲区再从缓冲区读,何时读,怎么读,归文件流(文件指针)管理。9.1.2缓冲文件系统和非缓冲文件系统流的常见说法(续):⑥
写文件时,流对象和写函数隐藏的细节揭露:流对象检查缓冲区,如果是磁盘文件,当变量来的数据写满缓冲区,流对象负责打开磁盘,将缓冲区数据一次性写到文件,使缓冲区变空。如果是设备文件(显示器),Windows下,流对象负责把变量来的数据直接输出到屏幕,缓冲区刷新方式是无缓冲。Linux下,流对象负责把变量来的数据送到缓冲区,遇到换行符'\n',再从缓冲区输出到屏幕,缓冲区刷新方式是行缓冲。写文件,是写到缓冲区里就行,还是得从缓冲区继续写到文件里,何时写,怎么写,归文件流(文件指针)管理。目
录9.1文件处理需要解决的问题及相关概念9.2打开与关闭文件
9.2.1打开文件
9.2.2关闭文件9.3读写文件内容9.2打开文件与关闭文件文件读写的第1步,必须先打开文件。文件打开后必须关闭。文件执行的通用操作是:打开文件
——
调用读写相关函数
——
关闭文件打开有2种方式:第1种方式调用fopen函数打开,对应fclose关闭。第2种方式针对设备文件,自动打开,自动关闭。9.2.1打开文件1调用fopen函数打开ANSIC标准规定用fopen函数打开文件。调用fopen函数后,打开一个文件流,在这个函数的参数中,指定需要访问的文件以及访问方式(读、写、或者读写)。fopen函数和操作系统验证文件或者设备是否存在并初始化文件信息区(FILE类型结构体变量)。函数原型:FILE*fopen(char*filename,char*mode);调用方式举例:FILE*fp;/*声明文件类型指针变量fp*/fp=fopen("a.txt","r+");1调用fopen函数打开(续)说明:①
返回值:正常返回值是文件指针,即文件信息区的首地址,必须用”FILE*”类型指针变量接收,若出错,返回空指针NULL(NULL已经在stdio.h头文件中定义为0)。fopen函数内部用malloc分配了文件信息区并初始化,文件信息区是无名全局变量或静态变量。fopen打开的文件,在第一次调用读写函数时,在函数内部用malloc动态分配文件缓冲区内存块(通常512字节或它的倍数,无名全局变量或静态变量),并划归文件指针管理。完善的程序应该对fopen函数返回值进行检查并加以处理,例如:if((fp=fopen("test.c","r")==NULL){printf("filecannotbeopened!\n");exit(1);/*exit(1)表示退出程序,并返回1给操作系统。在stdlib.h中*/
/*该函数也将关闭所有打开的文件*/
/*exit(0)表示程序正常返回,参数非零如exit(1)表示出错返回*/}文件指针fp,也叫文件流fp,成功打开一个文件也叫打开一个流,fp本质上是数据流管理员,fopen方式打开的文件,读写时对应的文件缓冲区刷新方式是满缓冲(全缓冲)。1调用fopen函数打开(续)说明(续):②
参数1——filename:文件名。详情参见9.1.1节。③
参数2——mode:文件打开和读写模式。调用fopen时传入一个字符串常量,它是下列几个字符的组合:'r'、'w'、'b'、'a'、'+'('r'、'w'、'a'不可同时使用),任意一种组合,构成一种文件打开和读写模式。详细的模式组合及说明参见表9-2。在文件打开时就必须考虑后续调用读写函数时的读写模式(模式由文件信息区成员_flag来记录,_flag不仅仅记录读写模式,还记录其他状态如关闭、打开、错误等,int型表达)。'r':read,只读。'w':write,只写。'a':append,只能写数据并追加到文件末尾。'+':既可读又可写。'b':binary,字母组合带'b'是二进制方式打开文件。字母组合不带'b'是文本方式打开文件。两者区别不是二进制文件和文本文件的差别,区别是对文件中换行的处理(文本文件和二进制文件都可能含有换行符)。C语言用一个回车符'\n'实现换行,Windows操作系统必须同时用一个'\r'和一个'\n'实现换行。在Windows下,文本方式打开文件时,会进行"\r\n"↔'\n'转换,二进制方式不转换。Linux操作系统同C语言一样用一个回车符'\n'实现换行,无论文本方式还是二进制方式打开文件没有区别,都不进行换行转换。为了兼容Windows操作系统和Linux操作系统,还是考虑一下2种打开方式的区别。fopen("a.txt","r+")1调用fopen函数打开(续)说明:③
参数2——mode:文件打开和读写模式(续)fopen("a.txt","r+")参数mode含义若文件不存在"r"文本方式打开文件,文件必须存在,只能读数据。出错"w"文本方式打开文件,只能写数据,若文件存在,则删去旧文件,建立同名新文件。创建新文件"a"文本方式打开文件,文件必须存在,只能写数据并且追加在文件尾。出错"r+"文本方式打开文件,文件必须存在,可以读数据,也可以写数据。出错"w+"文本方式打开文件,可以读数据,也可以写数据,若文件存在,则删去旧文件,建立同名新文件。创建新文件"a+"文本方式打开文件,文件必须存在,可以读数据,只能写数据到文件尾。出错"rb"二进制方式打开文件,文件必须存在,只能读数据。出错"wb"二进制方式打开文件,只能写数据。若文件存在,则删去旧文件,建立同名新文件。创建新文件"ab"二进制方式打开文件,文件必须存在,只能写到文件尾。出错"rb+"二进制方式打开文件,文件必须存在,可以读数据,也可以写数据。出错"wb+"二进制方式打开文件,可以读数据,也可以写数据。若文件存在,则删去旧文件,建立同名新文件。创建新文件"ab+"二进制方式打开文件,文件必须存在,可以读数据,也可以写数据到文件尾。出错9.2.1打开文件2设备文件自动打开操作系统为了统一对输入输出设备的操作,简化接口,把相关设备映射成文件,对设备操作,等同于对外存上普通文件的操作,称为设备文件。程序一运行,自动打开3个设备文件,对应3个打开的流对象:标准输入流stdin、标准输出流stdout、标准错误流stderr,流对象就是文件指针。程序关闭时,自动关闭它们。std是标准standard的意思,in/out指的是输入/输出。设备文件打开,有缓冲区的,对应缓冲区刷新方式不是满缓冲,而是行缓冲——以'\n'为标志。设备文件关联的设备、文件指针、文件流和文件缓冲区说明参见表9-3。设备文件设备文件指针文件流文件缓冲区标准输入文件键盘stdin标准输入流stdin标准输入缓冲区标准输出文件显示器stdout标准输出流stdoutWindows无缓冲Linux标准输出缓冲区标准错误文件显示器stderr标准错误流stderr无缓冲9.2.1打开文件【例题】intmain(){inta,b;scanf("%d%d",&a,&b);printf("%d,%d\n",a,b);return0;}执行语句scanf("%d%d",&a,&b);,用户输入的数据读入标准输入流stdin,流中数据再读入变量a、b。详细情况是:先检查标准输入缓冲区,发现缓冲区空,程序暂停,等待用户从键盘输入一串字符,每个字符被按下后马上进入缓冲区,字符同时回显到屏幕,错了可改正,例如输入:"32-5",用户按下【Enter】键(【回车】键),这个键转换的'\n'也进入缓冲区,此时缓冲区中数据锁定,用户输入的数据全部进入流中。然后,按照格式字符串"%d%d"要求,从第1个字符开始分解数据到变量a、b,解读数据时自动把相应字符转换成对应的整数,两字符"32"转换成整数32,中间空格丢掉,两字符"-5"转换成整数-5,成功,则流中(实际缓冲区中)还剩下'\n'。这些输入细节被流对象stdin和输入函数隐藏,不管过程咋样,结果是,变量得到了需要的值。9.2.1打开文件
intmain(){inta,b;scanf("%d%d",&a,&b);printf("%d,%d\n",a,b);return0;}执行语句printf("%d,%d\n",a,b);,是把字符串输出到标准输出流stdout。详细情况是:先从变量中取出值32和-5,根据格式字符串"%d,%d\n"要求,转换数据类型成字符型,并构成完整的字符串"32,-5\n",写出到标准输出流stdout中,Windows下没有标准输出缓冲区,流对象stdout管理范围只包含显示器和标准输出信息区,输出字符串立即输出到屏幕(无论有没有'\n'),刷新方式为无缓冲。Linux操作系统有标准输出缓冲区,流对象stdout管理范围包含显示器、标准输出信息区和标准输出缓冲区,缓冲区刷新方式是行缓冲——输出字符串中若没有'\n',不会马上输出到显示器,遇到'\n',立即向显示器输出。这些输出细节被流对象stdout和输出函数隐藏,不管过程咋样,最终输出字符串都显示到屏幕上('\n'是不可打印字符,在屏幕上让光标自动换行)。另外:标准错误流stderr也是无缓冲的,流中不包含输出缓冲区,直接向显示器输出。输出错误也叫做错误信息输出到错误流stderr。9.2.1打开文件
intmain(){inta,b;
scanf("%d%d",&a,&b);printf("%d,%d\n",a,b);return0;}图9-3Windows操作系统下标准输入流stdin和标准输出流stdout(图中地址是模拟地址)输入:“32-5”(两数之间空格)用户按下【Enter】键,这个键转换的'\n'也进入缓冲区9.2.2关闭文件我们熟知的”保存”(save),在C语言代码中有下列3种方式:①调用写文件函数(fputc、fputs、fprintf、fwrite)时,输出缓冲区满,一次性将缓冲区内容写到文件,缓冲区变空。②
fclose关闭文件,缓冲区未满,也将缓冲区内容写到文件。③
强制刷新缓冲区,调用fflush函数。刷新fopen打开的文件,使用方式为fflush(fp),立即把缓冲区内容输出到文件,使缓冲区为空。fflush也可以清空输入缓冲区,但这就不是保存了,保存只针对输出。不建议对stdin和stdout使用fflush。9.2.2关闭文件fclose函数关闭由fopen打开的文件,并将文件缓冲区内容立即写到文件中。关闭文件也叫做关闭流。关闭一个流可以防止与它相关的文件被再次访问,保证任何存储于文件缓冲区中的数据被正确写到文件中。函数原型:intfclose(FILE*stream)调用方式举例:fclose(fp);/*关闭fopen打开的文件流fp,并立即将缓冲区数据写到文件*/
/*实参为执行fopen后获得的文件指针fp*/fp=NULL;/*关闭文件后,使指针fp指向空地址*/说明:①
参数——stream:类型”FILE*”,实参为执行fopen后获得的文件指针(文件流)。②
返回值:成功关闭文件流,则返回一个0值,否则返回一个非0值。
③
即使缓冲区未满,只要调用fclose,会立即打开磁盘,将缓冲区数据写到文件,这也归类为满缓冲(全缓冲)。标准输入流stdin和标准输出流stdout是不需要调用fclose关闭的。目
录9.1文件处理需要解决的问题及相关概念9.2打开与关闭文件9.3读写文件内容
9.3.1文件读写要考虑的问题
9.3.2按字符读写文件
9.3.3按字符串读写文件
9.3.4按格式化方式读写文本文件
9.3.5按数据块读写文件
9.3.6随机读写文件
9.3.7文件错误检测
9.3.8再次解读FILE类型、文件指针和文件流9.3读写文件内容文件执行的通用操作是:打开文件
——
调用读写相关函数
——
关闭文件文件和文件缓冲区是流对象管的,流对象就是文件指针,指挥操作文件和文件缓冲区之间的读写,细节就隐藏在读写函数内。所以调用读写函数需要指明文件指针和变量。确定数据从哪里来到哪里去。读文件:文件指针(文件流)
变量。
写文件:变量
文件指针(文件流)。类型函数名功能打开fopen打开文件读/写fgetc按字符读数据,从缓冲区取1字符数据到变量所在内存区fputc按字符写数据,从变量所在内存取1字符数据到缓冲区fgets按字符串读文件,从缓冲区取1个字符串到变量fputs按字符串写文件,从变量取1个字符串到缓冲区fscanf按格式化方式读文本文件,类似scanffprintf按格式化方式写文本文件,类似printffread按数据块(按指定字节数)读文件fwrite按数据块(按指定字节数)写文件关闭fclose文件关闭刷新缓冲区fflush强制刷新缓冲区移动读写指针,随机读写fseek移动读写指针ftell计算当前读写指针到文件头之间的字节数rewind读写指针回到文件头
读文件结束feof检测是否读文件结束错误处理perror输出错误信息ferror检测是否出错clearerr清除错误信息其他rename文件改名更多……9.3.1文件读写要考虑的问题1文件读写指针文件指针指向文件信息区(FILE类型结构体),信息区的成员_ptr就叫做文件读写位置指针,简称读写指针(见图9-2),也可以叫做文件内部指针或文件位置标记,类型”char*”,是字符/字节型指针,它的取值范围在缓冲区首地址和尾地址之间变化,缓冲区空了后,文件指针会指挥_ptr回到缓冲区首地址。调用读写函数后,默认读写指针的指向,向缓冲区尾部移动。详情参见9.1.2节和9.3.8节。1文件读写指针(续)typedef
struct_iobuf{
char*_ptr;
int_cnt;
char*_base;
int_flag;
int_file;
int_charbuf;
int_bufsiz;
char*_tmpfname;
}FILE;
文件类型FILE读写指针FILE*fp;fp=fopen(…);/*返回文件指针,文件读写指针fp->_ptr初始化00000000*/…fwrite(…);/*调用写函数fwrite写数据*/printf("%p\n",fp->_ptr);/*输出读写指针fp->_ptr指向的缓冲区地址*/调用读写函数后,读写指针值的详细变化,请参见9.3.8节。9.3.1文件读写要考虑的问题2顺序读写和随机读写若不主动调用函数来移动文件读写指针的指向,读写函数执行完毕,读写指针指向自动往缓冲区尾部方向移动——这叫做顺序读写,若调用函数改变读写指针的值,任意改变指针指向,指针指向缓冲区哪儿,就可以从哪儿读或写,这叫做随机读写,随机读写函数主要有ftell、fseek、rewind,也叫文件定位函数。顺序读写和随机读写有时也叫顺序文件和随机文件,但这种说法其实不准确。随机读写详情参见9.3.6节。9.3.1文件读写要考虑的问题3读文件结束的判定读文件函数主要有fgetc、fges、fscanf、fread,常用这些函数的返回值来判断读取是否结束,不同函数的返回值是不一样的。除了用返回值判断读取是否结束,通用的判定函数是feof函数(f-endoffile,文件结束)。函数原型:intfeof(FILE*stream);功能:判断文件读取是否结束。参数——stream:文件指针。返回值:返回非0值(逻辑真),读文件结束;返回0值(逻辑假),读文件没结束。注意:feof函数只能判断读文件是否结束,但不确定出错误结束还是到文件尾结束,若要确定是到文件尾,还应该应该配合错误处理函数排除错误。9.3.2按字符读写文件1fputc函数函数原型:intfputc(intch,FILE*stream);功能:将一个字符ch写到文件流stream。参数1——ch:需要写到文件流的字符或int型整数(字符类型用int,相当于扩展的char型,兼容多字节字符编码)。如果当作字符用,就是写文本文件,如果当作整数用,可以看作写二进制文件。参数2——stream:文件指针(文件流),关联文件和文件缓冲区。返回值:成功则返回刚写入文件中的字符(字符类型和整型都用int);失败则返回EOF。EOF是在<stdio.h>文件中定义的符号常量,其值为-1。一般调用格式:fputc(变量,文件指针);/*文件指针等价文件流*/9.3.2按字符读写文件1fputc函数(续)调用方式举例:FILE*fp;fp=fopen(…);
/*打开文件,返回文件流fp,自行补充完整*/…fputc('A',fp);
/*将字符'A'写到文件流fp*/
若正确写入,文件读写指针自动向缓冲区尾方向位移1字符*/printf("%p\n",fp->_ptr);/*检测当前读写指针指向的缓冲区地址*/函数原型:intfpetc(FILE*stream);成功则返回刚写入文件中的字符(字符类型和整型都用int)9.3.2按字符读写文件2fgetc函数函数原型:intfgetc(FILE*stream);功能:从文件流stream中读一个字符。返回值就是获得的字符。参数——stream:文件指针(文件流),关联文件和文件缓冲区。返回值:成功则返回读到的字符(字符类型int),失败则返回EOF(-1)。EOF可以当作fgetc函数读文本文件时是否读到文件尾的标志,文本文件中每个字节对应的字符编码都在0~255之间(单字节可能是多字节编码的一部分),不会出现-1,但是EOF不能当作读二进制文件的文件尾标志,因为二进制文件的字节中非常可能出现-1。一般调用格式:变量=fgetc(文件指针);/*文件指针等价文件流*/9.3.2按字符读写文件2fgetc函数(续)调用方式举例:FILE*fp;intch;
/*用int型保存字符,代替char型*/fp=fopen(…)/*打开文件,返回文件流fp,自行补充完整*/…ch=fgetc(fp);/*从文件流fp得到1字符返回给字符变量ch*/
若读入正确,文件读写指针自动后移1字符*/printf("%p\n",fp->_ptr);/*检测当前读写指针指向的缓冲区地址*/函数原型:intfgetc(FILE*stream);从文件流stream中读一个字符。返回值就是获得的字符(字符类型和整型都用int)9.3.2按字符读写文件【例题9-1】从键盘输入一串字符,”#”结束输入,写入当前文件夹下名为”9-1.txt”的文本文件中,再从这个文本文件中读出所有数据显示到显示器上。解题思路:①
既然键盘显示器都是标准输入输出文件并自动打开,且刚刚学习了文件读写函数fputc,fgetc,这里所有输入输出都尽量使用这两个函数。用fgetc从键盘输入一串字符,用fputc写入文本文件中,再用fgetc读到显示器上。键盘输入用ch=fgetc(stdin);输出到屏幕用fputc(ch,stdout);②
打开文本文件时,用"w+"模式,w方式可以创建新文件,w+可写可读,先写一个字符,文件读写指针顺序向文件缓冲区末尾方向移动,写完移动文件读写指针到开头,再循环读字符,直到文件尾EOF。9.3.2按字符读写文件
intmain(){FILE*fp;intch;/*可以用int型代替char型*/if((fp=fopen("9-1.txt","w+"))==NULL){
/*打开文件(文件流),若文件存在,除旧建新,
若不存在,创建新文件*/printf("filecannotopen!\n");exit(1);
}【例题9-1续】从键盘输入一串字符,”#”结束输入,写入当前文件夹下名为”9-1.txt”的文本文件中,再从这个文本文件中读出所有数据显示到显示器上。printf("请输入一个字符串,#结束:\n");while((ch=fgetc(stdin))!='#'){
/*循环从标准输入流stdin获得字符到ch*/fputc(ch,fp);
/*将ch中字符写到文件流fp*/}rewind(fp);/*文件读写指针移到文件头*/while((ch=fgetc(fp))!=EOF){/*循环从文件流fp得到字符送入ch,直到文件尾EOF*/
fputc(ch,stdout);/*字符输出到标准输出流stdout*/}printf("\n");fclose(fp);/*关闭文件流fp*/fp=NULL;return0;}请输入一个字符串,#结束:Hello!大家好!#Hello!大家好!
9.3.2按字符读写文件【例题9-2】打开Windows自带的画图软件,随意画点什么,文件命名”9-2原.png”,与本题源文件放在同一个文件夹下,编写程序将这个文件内容复制到同一文件夹的另一文件中,文件命名:”9-2目.png”解题思路:①
复制文件时一个文件按指定字节读,另一个文件按指定字节写,不考虑每个字节数据是什么,无论是文本文件还是二进制文件复制原理相同,这需要在fopen打开文件时,打开方式必须指定带'b',也就是二进制打开。②
函数fputc和fgetc读写数据是以字符为单位,字符类型用的int,也可以认为以sizeof(int)字节为单位读写,复制文件用这2个读写函数恰恰好。③
要复制的是图像文件,属于二进制文件,检测是否读到文件尾不能用EOF(-1),要用feof函数检测是否读取文件结束,这2个函数二进制文件和文本文件都能用。9.3.2按字符读写文件
intmain(){
FILE*fp_source,*fp_destination;
/*声明2个文件类型指针变量*/charcByte;/*也可以用int型*/
/*声明一个char型变量或int型变量*/if((fp_source=fopen("9-2原.png","rb"))==NULL){
/*二进制方式打开要复制的文件,
返回文件流fp_source,只读,文件必须存在*/printf("无法打开文件:9-2原.png");exit(1);}if((fp_destination=fopen("9-2目.png","wb"))==NULL){/*二进制方式打开目的文件,返回
文件流fp_destination,只写,删除旧文件
创建空文件*/printf("无法创建文件:9-2目.png");exit(1);}【例题9-2续】打开Windows自带的画图软件,随意画点什么,文件命名”9-2原.png”,与本题源文件放在同一个文件夹下,编写程序将这个文件内容复制到同一文件夹的另一文件中,文件命名:”9-2目.png”/*开始复制*/
cByte=fgetc(fp_source);/*从文件流fp_source读二进制数到cByte*/while(!feof(fp_source)){
fputc(cByte,fp_destination);/*cByte数据输出文件流fp_destination*/cByte=fgetc(fp_source);
/*再从文件流fp_source读二进制数到cByte*/}fclose(fp_source);/*关闭文件流fp_source*/fp_source=NULL;fclose(fp_destination);fp_destination=NULL;/*关闭文件流fp_destination*/printf("文件复制完毕!\n");return0;}9.3.3按字符串读写文件函数fgets/fputs按字符串读写文件,若字符串末尾有’\n’,就是按行读写。1写字符串函数fputs函数原型:intfputs(constchar*str,FILE*stream);功能:将str指向的字符串写到文件流stream中,字符串结束符'\0'丢掉。C语言用'\n'作为换行标志,若给字符串末尾附加'\n'就是按行写入文件。参数1——str:”char*”型指针,可以是存放字符串的字符数组首地址,也可以是指向动态分配的内存区域的”char*”型指针变量。。参数2——stream:文件指针(文件流),关联要输出的文件和文件缓冲区。返回值:成功返回0,否则返回EOF(-1)。9.3.3按字符串读写文件1写字符串函数fputs(续)一般调用格式:fputs(指向字符串的指针,文件指针);/*文件指针等价文件流*/调用方式举例:FILE*fp;fp=fopen(…);/*打开文件,返回文件流fp,请自行补充完整*/fputs("hello\n",fp);/*将字符串写到文件流fp*/printf("%p\n",fp->_ptr);/*输出当前读写指针指向的缓冲区地址*/9.3.3按字符串读写文件2读字符串函数fgets函数原型:char*fgets(char*str,intsize,FILE*stream);功能:从文件流stream读入字符序列,保存到字符指针str指向的内存区,直到出现'\n'字符、读到文件结尾或是已读了size-1个字符为止,最后会自动加上字符'\0'作为字符串结束。C语言用'\n'作为换行标志,若字符串中有'\n'就是按行读字符串('\n'也保存)。参数1——str:”char*”型指针,可以是存放字符串的字符数组首地址,也可以是指向动态分配的内存区域的”char*”型指针变量。参数2——size:指定最大读取字符串的长度为size-1。参数3——stream:文件指针(文件流),关联要输出的文件和文件缓冲区。返回值:读取成功,则返回str指向的字符串;否则返回NULL(0)。NULL可以作为fgets读文件结束标志。9.3.3按字符串读写文件2读字符串函数fgets(续)一般调用格式:fgets(指向字符串的指针,最大长度,文件指针);/*文件指针等价文件流*/调用方式举例:FILE*fp;charstr[20];/*最多存储19个字符+'\0'*/fp=fopen(…);/*打开文件,返回文件流fp,请自行补充完整*/while(fgets(str,20,fp)!=NULL)/*循环从文件流fp读入一行字符(最多19个)*/{printf("%p\n",fp->_ptr);/*输出当前读写指针指向的缓冲区地址*/…}注意:除了读写文本文件,fgets、fputs函数还可以用于处理二进制文件、网络传输等数据源。因为它们的第1个参数,类型是char*,就是字符型指针,指向变量所在内存区,C语言中char型既可以是单字节字符型,也可以是单字节整数类型(字节型)。9.3.3按字符串读写文件【例题9-3】读文件”table08_输入数据备份.txt”或”学生数据.txt”,并输出到显示器上。解题思路:①
文本文件以文本方式打开,即"r"方式打开,文件必须已经存在,这种方式将Windows换行符'\r'+'\n',换成C语言换行符'\n'。运行代码前别忘了先把文件复制粘贴到源文件所在文件夹。②
用fgets是按行读文件,遇到'\n'文件流读取停止,为防止多行自动换行才遇到一个'\n',将fgets第2个参数——最大字符串长度设为1024,接收字符串的字符数组大小也设为1024。③
用fputs将字符串输出到标准输出流stdout中。④
题目提供文件有中文,若输出到显示器中文乱码,解决办法阅读本题程序代码后面的程序说明部分。9.3.3按字符串读写文件【例题9-3续】
读文件”table08_输入数据备份.txt”或”学生数据.txt”,并输出到显示器上。intmain(){FILE*fp;charstr[1024];if((fp=fopen("table08_输入数据备份.txt","r"))==NULL){/*打开一个只读的文本文件,返回文件流fp*/printf("filecannotopen!\n");exit(1);}while(fgets(str,1024,fp)!=NULL){
/*从文件流fp按行读字符串存入数组str(遇'\n'停止,所以是按行)*/fputs(str,stdout);
/*str中的字符串输出到标准输出流stdout*/
/*Windows下,标准输流stdout中不包含标准输出缓冲区*/}fclose(fp);/*关闭文件流fp*/fp=NULL;return0;}9.3.3按字符串读写文件中文乱码问题是文件中的字符编码格式与控制台(键盘和显示器)编码格式不一致导致。文本文件默认编码是UTF-8。若用fgets读入的内容直接用fputs输出到文本文件,不用考虑编码,若用fputs向显示器输出,汉字可能显示乱码,因为显示器默认ANSI编码(中文编码方式是国标码GBK或GBK8030),ANSI兼容国标码,UTF-8编码不兼容国标码。显示器的编码方式改不了,可以改文件的编码方式。只要在Windows操作系统文件管理器下,打开给定的文本文件”table08_输入数据备份.txt”,单击”文件”—>”另存为”,将编码改为”ANSI”或”GB18030”,如图9-4所示。保存之后,再来运行一次本题代码。在【例题9-1】中,代码运行时,若键盘输入中文,生成的”9-1.txt”默认的编码方式是ANSI,不是UTF-8,这样文件编码和键盘显示器编码方式兼容,不会出现乱码问题。单个中文字符用char型单个变量保存也会出现乱码,要用int型或char数组保存单个汉字,格式化输入输出时用%s格式处理。9.3.4按格式化方式读写文本文件格式化方式读写文件函数为fscanf和fprintf。大家已经很熟悉scanf和printf的用法,它们是格式化从键盘输入、格式化向屏幕输出,fscanf和fprintf使用方式与这两个函数类似。fscanf和fprintf与scanf和printf的差异就是,fscanf是从任意文件中要数据输入,scanf只能从标准输入文件(键盘)要数据,fprintf是向任意文件输出,printf只能向标准输出文件(显示器)输出,标准输入输出文件指针stdin/stdout不需要在scanf和printf中指定,默认就是它们。fscanf和fprintf要指定文件指针。格式化输入输出都是字符流,数据类型自动转换。文件扩展名无论是什么,文件内容都是字符。9.3.4按格式化方式读写文本文件1fprintf函数一般调用格式:fprintf(文件指针,格式字符串,输出列表);printf(格式字符串,输出列表);
printf默认文件指针是stdout:调用方式举例:intx=5;doubley=3.0;FILE*fp;fp=fopen(…);/*打开文件,返回文件指针fp(文件流fp)请自行补充完整*/fprintf(fp,"%d%5.2f\n",x,y);
/*字符串向文件流fp输出*/printf("%d%5.2f\n",x,y);
/*向标准输出流stdout输出,
与fprintf(stdout,"%d%5.2f\n",x,y);等价*/9.3.4按格式化方式读写文本文件2fscanf函数调用格式:fscanf(文件指针,格式字符串,输入列表);scanf(格式字符串,输入列表);scanf默认文件指针是stdin:调用方式举例:intx;floaty;FILE*fp;fp=fopen(…);/*打开文件,返回文件指针fp(文件流fp)请自行补充完整*/fscanf(fp,"%d%f",&x,&y);/*从文件流fp读数据分解到变量*/scanf("%d%f\n",&x,&y);
/*从标准输入流stdin读数据分解到变量,
与fscanf(stdin,"%d%f",&x,&y);等价*/9.3.4按格式化方式读写文本文件【例题9-4】使用fscanf和fprintf函数,从键盘上输入一个学生数据到文件”9-4.dat”,然后再从这个文件中读入数据到内存并输出到显示器。学生数据参见第8章表8-1。解题思路:①
键盘输入用:fscanf(stdin,格式字符串,变量地址列表);。②
输出到文件”9-4.dat”,"wb+"或"w+"方式打开,创建新文件”9-4.dat”,然后调用:fprintf(文件指针,格式字符串,变量列表);③
再从文件中读入数据到内存,不关闭文件,直接移动文件读写指针到开头再读入数据,移动文件读写指针可以用rewind,也可以用fseek,不熟悉参见9.3.6节。④
从文件读数据调用:fscanf(文件指针,格式化字符串,变量地址列表);输出数据到屏幕用:fprintf(stdout,格式化字符串,变量列表);。⑤
这里的变量可以用第8章定义的结构体类型structStudent。【例题9-4】使用fscanf和fprintf函数,从键盘上输入一个学生数据到文件”9-4.dat”,然后再从这个文件中读入数据到内存并输出到显示器。学生数据参见第8章表8-1。typedefstructStudent{
charSNO[20];
charName[20];
charSex;
floatMath;
floatEnglish;}STUDENT;intmain(){STUDENTstu1;FILE*fp;printf("请输入1位学生数据:\n");printf("例如:200809410102AnemoneF9272\n");
fscanf(stdin,"%s%s%*1c%c%f%f",stu1.SNO,
stu1.Name,&stu1.Sex,&stu1.Math,&stu1.English);/*格式字符串中%*1c是虚读1字符,
详细解释看本题最后程序说明部分*/
/*打开文件,返回文件指针fp(文件流fp),可读可写*/
fp=fopen("9-4.dat","wb+");/*w方式,若文件
不存在,创建新的,若存在删除旧的*/
/*输出字符串到文件流fp*/fprintf(fp,"%s\t%s\t%c\t%.1f\t%.1f\n",stu1.SNO,stu1.Name,
stu1.Sex,stu1.Math,stu1.English);
rewind(fp);/*
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 贵州省遵义市桐梓县2025-2026学年七年级上学期期中地理试题(含答案)
- 船舶电气设备及系统大连海事大学电与磁
- 计算机组成与系统结构
- 肝脏疾病和心脏疾病相互影响
- 卒中后癫痫的诊断与治疗课件
- 见证、取样员培训砼、砂浆,土方工程部分
- 股票分析之18均线分析机会点错误案例
- 经济数学基础5第二十六讲
- 2026年贵州省赤水市高三数学下册期末考试模拟检测卷及参考答案【巩固】
- 2026年四川省康定市高三数学下册期末考试模拟试卷附参考答案【A卷】
- 2026-2027学年川教版(新教材)小学信息科技六年级上册(全册)教学设计(附目录p73)
- 2026年中国银行考试题目及答案
- 2026中国MEMS传感器产业技术创新与下游应用拓展专题报告
- 新轮机英语专业词汇(终极版适用于船员考证、机舱实操分类)
- 2026广东肇庆市高校毕业生基层公共就业创业服务岗位招募68人笔试参考题库及答案详解
- 火车司机考试题库及答案
- 教科版三年级上册科学第二单元《水》单元测试卷含答案A4打印版
- 2027年中国电信集团有限公司校园招聘考试参考试题及答案详解
- 上海市徐汇中学2027届物理高三第一学期期中联考试题含解析
- 2026统编版七年级历史期末知识点复习提纲
- 《江城子·乙卯正月二十日夜记梦》课件用
评论
0/150
提交评论