您好,欢迎访问三七文档
标准IO•标准IO是指进程的标准输入、标准输出、标准输出。针对标准IO的读取和写入linux做了一定的封装,采取了一定的策略,介于我们将一直与标准IO打交道,有必要搞清楚这些策略。•因为不仅在UNIX而且在很多操作系统上都实现此库,所以它由ANSIC标准说明。标准I/O库处理很多细节,例如缓存分配,以优化长度执行I/O等。这样使用户不必担心如何选择使用正确的块长度。标准I/O库是在系统调用函数基础上构造的,它便于用户使用,但是如果不较深入地了解库的操作,也会带来一些问题。•标准I/O库是由DennisRitchie在1975年左右编写的。它是由MikeLesk编写的可移植I/O库的主要修改版本。令人惊异的是,15年后制订的标I/O库对它只作了极小的修改。•对一个进程预定义了三个流,它们自动地可为进程使用:标准输入、标准输出和标准出错。•我们曾用文件描述符STDIN_FILENO,STDOUT_FILENO和STDERR_FILENO分别表示它们。•这三个标准I/O流通过预定义文件指针stdin,stdout和stderr加以引用。这三个文件指针同样定义在头文件stdio.h中。练习•写一个带标准输入和标准输出的函数。•每当从标准输入读入一行字符串,则从标准输入打印之。如果标准输入的字符串是exit就退出。•1,重定向其标准输入到一个文件,查看结果•2,在其中使用关闭标准输入,查看结果•3,在其中使用关闭标准输出,查看结果标准IO的缓存机制•标准I/O提供了三种类型的缓存:•(1)全缓存。在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。•(2)行缓存。在这种情况下,当在输入和输出中遇到新行符时,标准I/O库执行I/O操作。•(3)不带缓存。标准I/O库不对字符进行缓存。•ANSIC要求下列缓存特征:•(1)当且仅当标准输入和标准输出并不涉及交互作用设备时,它们才是全缓存的。•(2)标准出错决不会是全缓存的•但是一般来说•*标准出错是不带缓存的。•*如若是涉及终端设备的其他流,则它们是行缓存的;否则是全缓存的•强制刷新一个流。•#includestdio.h•intfflush(FILE*fp);打开流•#includestdio.h•FILE*fopen(constchar*pathname,constchar*type);•FILE*freopen(constchar*pathname,constchar*type,FILE*fp);•FILE*fdopen(intfiledes,constchar*type);•三个函数的返回:若成功则为文件指针,若出错则为NULL打开标准I/O流的type参数•r或rb为读而打开•w或wb使文件成为0长,或为写而创建•a或ab添加;为在文件尾写而打开,或为•r+或r+b或rb+为读和写而打开•w+或w+b或wb+使文件为0长,或为读和写而打开•a+或a+b或ab+为在文件尾读和写而打开或创建•当以读和写类型打开一文件时(type中+号),具有下列限制:•*如果中间没有fflush、fseek、fsetpos或rewind,则在输出的后面不能直接跟随输入。•*如果中间没有fseek、fsetpos或rewind,或者一个输出操作没有到达文件尾端,则在输入操作之后不能直接跟随输出。练习•写一个函数,负责打开一个可读写的文件,如果文件存在,则不清空方式打开,不存在则创建之。•要求用带缓存方式实现之•要求用不带缓存的io实现之关闭文件•#includestdio.h•intfclose(FILE*fp);•在该文件被关闭之前,刷新缓存中的输出数据。缓存中的输入数据被丢弃。如果标准I/O库已•经为该流自动分配了一个缓存,则释放此缓存。•当一个进程正常终止时(直接调用exit函数,或从main函数返回),则所有带未写缓存数据•的标准I/O流都被刷新,所有打开的标准I/O流都被关闭。读和写流•(1)每次一个字符的I/O。一次读或写一个字符,如果流是带缓存的,则标准I/O函数处理所有缓存。•(2)每次一行的I/O。使用fgets和fputs一次读或写一行。每行都以一个新行符终止。当调用fgets时,应说明能处理的最大行长。5.7节将说明这两个函数。•(3)直接I/O。fread和fwrite函数支持这种类型的I/O。每次I/O操作读或写某种数量的对象,而每个对象具有指定的长度。这两个函数常用于从二进制文件中读或写一个结构。每次一个字符的I/O•#includestdio.h•intgetc(FILE*fp);•intfgetc(FILE*fp);•intgetchar(void);•三个函数的返回:若成功则为下一个字符,若已处文件尾端或出错则为EOF•函数getchar等同于getc(stdin)。前两个函数的区别是getc可被实现为宏,而fgetc则不能实现为宏区别返回的错误值和清除错误•#includestdio.h•intferror(FILE*fp);•intfeof(FILE*fp);•两个函数返回:若条件为真则为非0(真),否则为0(假)•voidclearerr(FILE*fp);送回一个字符•#includestdio.h•intungetc(intc,FILE*fp);•返回:若成功则为C,若出错则为EOF•回送的字符,不一定必须是上一次读到的字符。EOF不能回送。但是当已经到达文件尾端时,仍可以回送一字符。下次读将返回该字符,再次读则返回EOF。之所以能这样做的原因是一次成功的ungetc调用会清除该流的文件结束指示。输出函数•#includestdio.h•intputc(intc,FILE*fp);•intfputc(intc,FILE*fp);•intputchar(intc);•三个函数返回:若成功则为C,若出错则为EOF•与输入函数一样,putchar(c)等同于putc(c,stdout),putc可被实现为宏,而fputc则不能实现为宏。每次一行I/O•#includestdio.h•char*fgets(char*buf,intn,FILE*fp);•char*gets(char*buf);•两个函数返回:若成功则为buf,若已处文件尾端或出错则为NULL•对于fgets,必须指定缓存的长度n。此函数一直读到下一个新行符为止,但是不超过n-1个字符,读入的字符被送入缓存。该缓存以null字符结尾。如若该行,包括最后一个新行符的字符数超过n-1,则只返回一个不完整的行,而且缓存总是以null字符结尾。对fgets的下一次调用会继续读该行。•fputs和puts提供每次输出一行的功能。•#includestdio.h•intfputs(constchar*str,FILE*fp);•intputs(constchar*str);•两个函数返回:若成功则为非负值,若出错则为EOF•函数fputs将一个以null符终止的字符串写到指定的流,终止符null不写出。注意,这并不一定是每次输出一行,因为它并不要求在null符之前一定是新行符。通常,在null符之前是一个新行符,但并不要求总是如此。•puts将一个以null符终止的字符串写到标准输出,终止符不写出。但是,puts然后又将一个•新行符写到标准输出。4个行IO的区别•puts并不像它所对应的gets那样不安全。但是我们还是应避免使用它,以免需要记住它在最后又加上了一个新行符。如果总是使用fgets和fputs,那么就会熟知在每行终止处我们必须自己加一个新行符。练习•用每次一个的io实现每次一行的io•包括行输入和行输出io。二进制I/O•#includestdio.h•size_tfread(void*ptr,size_tsize,size_tnobj,FILE*fp);•size_tfwrite(constvoid*ptr,size_tsize,size_tnobj,FILE*fp);•两个函数的返回:读或写的对象数•fread和fwrite返回读或写的对象数。对于读,如果出错或到达文件尾端,则此数字可以少于nobj。在这种情况,应调用ferror或feof以判断究竟是那一种情况。对于写,如果返回值少于所要求的nobj,则出错。定位流•#includestdio.h•longftell(FILE*fp);•返回:若成功则为当前文件位置指示,若出错则为-1L•intfseek(FILE*fp,longoffset,intwhence);•返回:若成功则为0,若出错则为非0•voidrewind(FILE*fp);•#includestdio.h•intfgetpos(FILE*fp,fpos_t*pos);•intfsetpos(FILE*fp,constfpos_t*pos);•两个函数返回:若成功则为0,若出错则为非0•(1)ftell和fseek。这两个函数自V7以来就存在了,但是它们都假定文件的位置可以存放在一个长整型中。•(2)fgetpos和fsetpos。这两个函数是新由ANSIC引入的。它们引进了一个新的抽象数据类型fpos_t,它记录文件的位置。在非UNIX系统中,这种数据类型可以定义为记录一个文件的位置所需的长度。格式化I/O•#includestdio.h•intprintf(constchar*format,...);•intfprintf(FILE*fp,constchar*format,...);•两个函数返回:若成功则为输出字符数,若输出出错则为负值•intsprintf(char*buf,constchar*format,...);•返回:存入数组的字符数不定长的变种输出•#includestdarg.h•#includestdio.h•intvprintf(constchar*format,va_listarg);•intvfprintf(FILE*fp,constchar*format,va_listarg);•两个函数返回:若成功则为输出字符数,若输出出错则为负值•intvsprintf(char*buf,constchar*format,va_listarg);•返回:存入数组的字符数练习•实现不定长格式化输出函数。•例如实现一个不定长输出函数格式化输入•#includestdio.h•intscanf(constchar*format,...);•intfscanf(FILE*fp,constchar*format,...);•intsscanf(constchar*buf,constchar*format,...);•三个函数返回:指定的输入项数,若输入出错,或在任意变换前已至文件尾端则为EOF有file*到fd•#includestdio.h•intfileno(FILE*fp);•返回:与该流相关联的文件描述符练习•实现一种算法,能够循环对文件进行写入,实现类似日志的操作•1,文件的大小不得超过100k•2,可以不断接受输入并写入文件,保持最新的输入在文件内,文件写满的时候从旧的内容开始清除和覆盖。•3,可以读出当前文件内的所有记录。
本文标题:标准IO
链接地址:https://www.777doc.com/doc-3167439 .html