输入输出函数(C和指针第15章)

输入输出函数(C和指针第15章)

1错误报告

函数:void perror(char const*message)

用于打印错误信息,相当于C++中的cerror,如下例:

If (fclose(filename)!= 0)

{

            perror("fclose error");

};

如果文件读取失败就会打印上述字符串,然后跟一个分号和一个空格,最后打印相关错误的系统信息。

2 打开流

函数:FILE *fopen(char const*filename,char const *mode)

对于打开模式(mode)有:

 

读取

写入

添加

文本

r

w

a

二进制

rb

wb

ab

1)    以读的模式打开文件,那么文件必须存在;

2)    以写的模式打开的话,若文件不存在则新建;若文件存在则清空;

3)    以添加的模式打开文件,若不存在新建;若存在则从文件末尾开始添加;

4)    若以“a+”模式打开文件,那么表示可读写,当你写完一些数据之后想读数据,或者读完数据想写一些数据时,你一般必须借助(fseek,fsetpos,rewind)重新定位文件读写的当前位置。

5)    你总应该检查文件打开是否成功。

 

函数:FILE * freopen ( const char *filename, const char * mode, FILE * stream )

功能:实现重定向,把流stream重定向到filename,一般流stream会用stdin,stdout或者stderr。

 

使用方法:因为文件指针使用的是标准流文件,因此我们可以不定义文件指针。

接下来我们使用freopen()函数以只读方式r(read)打开输入文件slyar.in

freopen("slyar.in","r", stdin);

然后使用freopen()函数以写入方式w(write)打开输出文件slyar.out

freopen("slyar.out","w", stdout);

接下来的事情就是使用freopen()函数的优点了,我们不再需要修改scanf和printf,而是维持代码的原样就可以了。因为freopen()函数重定向了标准流,使其指向前面指定的文件。

最后只要使用fclose关闭输入文件和输出文件即可。

fclose(stdin);

fclose(stdout);

若要恢复句柄,可以重新打开标准控制台设备文件,只是这个设备文件的名字是与操作系统相关的。

DOS/Windows:

freopen("CON","r", stdin);

Linux:

freopen("/dev/console","r", stdin);

 

下面看一个例子,标准输入stdin 重定向到in.txt,标准输出重定向到out.txt中:


#include<stdio.h>

int main()

{

     freopen("out.txt","r",stdin);

     freopen("in.txt","w",stdout);

    

     char c;

    

     while(scanf("%c",&c) != EOF)

     {

          printf("%c",c);

     }
}

该函数的功能就相当于把文件out.txt的内容复制到in.txt中。

顺带提下int fclose(FILE *stream),就不细讲了。

 

3 字符I/O

函数:

1)       int getchar(void)         

2)       int getc(FILE *stream)

3)       int fgetc(FILE *stream)

三个函数都是从流中读取字符,但是3)只能从标准输入中读取。读取失败返回EOF 。1)2)本质上是宏。

 

函数

1)       int  putchar(int c)

2)       int  putc(int c,FILE*stream)

3)       int  fputc(int c,FILE*stream)

与上面的函数基本同理。1)2)本质上是宏

 

一个小工具:

函数:int  ungetc(int c,FILE *stream)

把一个先前读取的字符退回到流中,这样它可以在以后被重新读入。退回并不影响流指针所指向的文件内容,而是改变读取的当前位置。

 

4 未格式化的行I/O

       行I/O可以用两种方式执行——未格式化的或者格式化的。这两种形式都用于操纵字符串。区别在于未格式化的I/O简单读取或写入字符串,而格式化的I/O则执行数字和其它变量的内部和外部表示直接的转换。

1 gets &&  puts家族

1)       char  *fgets(char *buffer,int buffer_size,FILE*stream)

2)       char  *gets(char *buffer)

3)       int   *fputs(char const *buffer,FILE *stream)

4)       int   *puts(char const *buffer)

 

1) fgets函数读取流的一行到缓冲区buffer中(包括换行符‘\n‘),若超出buffer_size的大小,则读取行的一部分,下次继续读取剩余部分。返回值为指向buffer的指针,且在buffer指向缓冲区末尾添加‘\0‘使其成为一个字符串。若达到文件末尾则返回NULL。

2) fputs中buffer不能为空,必须要包含字符串,buffer必须以NUL(\0)结尾,可以一次读入一行的一部分,可以一次一行,也可以一次多行。若写入错误,fputs返回常量值EOF。

3) gets和puts函数几乎同fgets与fputs相同。区别在于,他们的流是标准输入输出流。其次gets读取一行时并不在缓冲区存储换行符。Puts函数写入时他在字符串写入标准输出后,再添加一个换行符。

4) 由于gets函数没有缓冲区大小,很容易造成缓冲区溢出,导致写入写入溢出,可能会破坏一个或多个相关变量的值,所以一般不推荐使用。

 

5 格式化的行I/O  

“格式化的行I/O”这个名字从某种意义上来讲是不准确的,因为scanf和printf家族并不局限于单行,他们同样可以在行的一部分或者多行上进行I/O操作。  

 1 scanf家族

1)    int fscanf(FILE *stream,char const*format,...)

2)     intscanf(char const *format,...)

3)    int sscanf(char const *string,charconst *format,...)

与2)用法基本一致,1)是从指定流读取,2)是从标准输入读取,3)是从字符串读入。

2printf家族

1)   int fprintf(FILE *stream,char const*format,...)

2)   int printf(char const *format,...)

3)   int sprintf(char *buffer,char const*format,...)

 

6 二进制I/O

  把数据写到文件效率最高的方法是用二进制形式写入。二进制数出可避免在数值转换过程中所涉及的开销和精度损失。但二进制数据并非人眼所能阅读,所以这个技巧只有当数据将被另一个程序按顺序读取时才能使用。

  fread函数用于读取二进制数据,fwrite函数用于写入二进制数据。原型如下:

size_t fread(void *buffer,size_t size,size_t count,FILE *stream) 

size_t fwrite(void *buffer,size_t size,size_tcount,FILE *stream)

解释:

buffer是一个用于保存数据的缓冲区,size是缓冲区中每个元素所占字节数,count是读取或写入的元素个数,stream是数据读取或写入的流。

 

 

7刷新和定位函数

  无论是输入还是输出都不会是立即执行,它们都会向文件立即写入,而是先存入缓冲区中,到一定时机再进行写入。有时我们可以借助fflush函数进行缓冲区强行刷新,同时将内容写入流中。

int fflush(FILE *stream);

 

一般我们读取文件或写入文件都是顺序的(线性的),但有的时候我们也需要随机访问,这时候我们可以使用下面的工具函数:

long ftell(FILE *stream);

int fseek(FILE *stream,long offset,int from);

1) ftell返回文件读写的当前位置。fseek允许定位到文件中的指定位置,具体有一些其它影响,此不赘述。

另外还有三个额外的函数,用一些限制更加严格的方式执行相同任务。它们的原型如下:

void rewind(FILE *stream)

int fgetpos(FILE *stream,fpos_t *position)

int fsetpos(FILE *stream,fpos_t const *position)

  rewind函数将读/写指针设置回指定流的起始位置。它同时清除流的错误提示标志。Fgetpos和fsetpos函数分别是ftell和fseek函数的替代方案。

  它们的主要区别在于这对函数接受一个指向fpos_t的指针作为参数。fgetpos在这个位置存储文件的当前位置,fsetpos把文件设置为存储在这个位置的值。

  用fpos_t表示一个文件位置的方式并不是由标准定义的。它可能是文件中的一个字节偏移量,也可能不是。因此,使用一个从fgetpos函数返回的fpos_t类型的值是唯一安全的用法是把它作为参数传递给后续的fsetpos函数。

 

8改变缓冲方式

void  setbuf(FILE*stream,char *buf)

int  setvbuf(FILE *stream,char *buf,int mode,size_t size)

 

9 流错误函数

下面这些函数用于判断流的状态:

int  feof(FILE*stream)

int ferror(FILE *stream)

void clearerr(FILE *stream)

  如果流当前处于文件尾,那么feof函数返回真。若文件出现任何读写错误,ferror返回真,其实用来报告流错误的状态的。最后,clearerr是用来对指定流的错误标志进行重置的。

 

10 临时文件&&文件操作

FILE  *tmpfile(void)

该函数创建一个临时文件并返回指向它的指针,当文件被关闭或者程序终止时这个文件便自动删除。该文件以wb+模式打开,可用于二进制和文本数据。

char *tmpnam(char *name)

用于产生临时文件名。

int  remove(charconst *filename);

int rename(char const *oldname,char const *newname);

remove函数删除一个指定的文件,当被remove的文件处于打开状态时,那么结果取决编译器。

rename函数用于改变一个文件的名字,如果已经有一个newname存在的话,那么结果取决于编译器。

 

                                                                           

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值