标准的I/O函数

来源:互联网 发布:足不出户而知天下事 编辑:程序博客网 时间:2024/06/05 05:47
标准的I/O函数


1.打开/关闭
  #include<stdio.h>
  FILE *fopen( const char *path, const char *mode);
功能:打开一个文件.
参数:path文件的路径名,mode表示打开的方式.
返回:如果文件打开成功,返回一个FILE *文件指针来标识这个文件,出错返回NULL并设置errno.


关于path,要了解"绝对路径"和"相对路径"的概念.
mode参数有6种:
"r",只读,文件必须已存在.
"w",只写,文件存在,则替换(文件长度从0开始),如果不存在就创建.
"a",追加,文件不存在就创建.
"r+",读和写,文件必须已存在.
"w+",允许读和写,如果文件不存在则创建,如果存在,则从0字节处开始写.
"a+",允许读写追加,如果文件不存在就创建.


  #include<stdio.h>
  int fclose( FILE *fp);
功能:关闭一个文件.
参数:fp是fopen返回的文件指针.
返回:成功返回0,出错返回EOF并设置errno
注意,fclose成功之后,fp就无效了.文件打开,要记得关闭.


2.出错
  #include<stdio.h>
  void perror( const char *s)
功能:perror 函数将错误信息打印到标准错误输出,首先打印参数s 所指的字符串,然后打印: 号,然后根据当前errno的值打印错误原因。
注意,使用errno的时候,要#include<errno.h>


  #include<string.h>
  char *strerror( int errnum)
功能:根据错误号返回错误原因字符串。这个函数返回指向静态内存的指针。线程库时我们会看到,有些函数的错误码并不保存在errno中,而是通过返回值返回,就不能调用perror 打印错误原因了,这时strerror 就派上了用场.


3.以字节为单位的I/O函数
3.1 读入
  #include<stdio.h>
  int fgetc( FILE *stream)
  int getchar(void)
功能:fgetc要读一个文件,该文件必须是可读的.文件打开时,偏移量为0,每次调用fgetc时,会向后移动一个字节.读到一个字节后应该是unsigned char型的,但返回是int型,所以要转换再返回.那为什么要规定返回值是int 型呢?因为出错或读到文件末尾时fgetc将返回EOF ,即-1 ,保存在int 型的返回值中是0xffffffff,如果读到字节0xff ,由unsigned char 型转换为int 型是0x000000ff ,只有规定返回值是int 型才能把这两种情况区分开,如果规定返回值是unsigned char 型,那么当返回值是0xff 时无法区分到底是EOF 还是字节0xff 。如果需要保存fgetc的返回值,一定要保存在int 型变量中,如果写成unsigned char c = fgetc(fp); ,那么根据c 的值又无法区分EOF 和0xff 字节了。注意,fgetc读到文件末尾时返回EOF ,只是用这个返回值表示已读到文件末尾,并不是说每个文件末尾都有一个字节是EOF (根据上面的分析,EOF并不是一个字节)。


3.2 输出
  #include<stdio.h>
  int fputc( int c, FILE *stream)
  int putchar( int c);
功能:fputc函数向指定的文件写一个字节,putchar向标准输出写一个字节,调用putchar(c)相当于调用fputc(c, stdout) .写一个文件必须是可写的.调用一次,读写位置向后移动一个字节.当调用getchar()或fgetc(stdin)时,如果用户没有输入字符,getchar函数就阻塞等待,所谓阻塞是指这个函数调用不返回,也就不能执行后面的代码,这个进程阻塞了,操作系统可以调度别的进程执行。从终端设备读还有一个特点,用户输入一般字符并不会使getchar函数返回,仍然阻塞着,只有当用户输入回车或者到达文件末尾时getchar才返回。


4.位置操作
  #include<stdio.h>
  int fseek( FILE *stream, long offset, int whence)
功能:给文件指针定位.
参数:stream文件指针,offset偏移量,whence相对于文件的部位.
返回:成功返回0,出错返回-1并设置errno
fseek的whence 和offset 参数共同决定了读写位置移动到何处,whence 参数的含义如下:
SEEK_SET 从文件开头移动offset 个字节
SEEK_CUR 从当前位置移动offset 个字节
SEEK_END 从文件末尾移动offset 个字节

offset,可正可负,负值表示向前(向文件开头的方向)移动,正值表示向后(向文件末尾的方向)移动,如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了文件末尾,再次写入时将增大文件尺寸,从原来的文件末尾到fseek移动之后的读写位置之间的字节都是0 。


  long ftell( FILE *stream),成功返回当前读写位置,出错返回-1并设置errno
  void rewind(FILE *stream),把读写位置移动到文件开头


5.以字符串为单位的I/O函数
5.1 读入
  #include<stdio.h>
  char *fgets(char *s, int size, FILE *stream)
  char *gets(char *s)
功能:从指定的文件中读一行字符到缓冲中
参加:s缓冲区的地址,size缓冲区大小,stream文件指针
返回:成功返回s指针,出错或者读到文件未必返回NULL
注意:永远不要用gets()
以'\n'表示一行结束,如果文件中的一行太长,fgets从文件中读了size-1 个字符还没有读到'\n',就把已经读到的


size-1 个字符和一个'\0'字符存入缓冲区,文件中剩下的半行可以在下次调用fgets时继续读。


5.2 输出
  #include<stdio.h>
  int fputs( const char *s, FILE *stream)
  int puts( const char *s)
功能:向指定的文件写入一串字符
返回:成功返回一个非负整数,出错返回EOF(-1)
注意:缓冲区是以'\0'结尾的字符串,但并不把'\0'写入文件


6.以记录为单位的I/O函数
  #include<stdio.h>
  size_t fread( void *ptr, size_t size, size_t nmemb, FILE *stream)
  size_t fwrite( const void *ptr, size_t size, size_t nmemb, FILE *stream)
功能:用于读写记录,这里的记录是指一串固定长度的字节,比如一个int,一个结构体,或者一个定长数据.
参数:size指出一条记录的长度,nmemb指出要读的多少条记录,这些记录在ptr所指的内存空间中连续存放,共占size x nmemb个字节.
返回:读或写的记录数,成功时返回记录数等于nmemb,出错或者读到文件末尾时返回记录数小于nmemb


7.格式化I/O函数
#include <stdio.h>
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
#include <stdarg.h>
int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list
printf 格式化打印到标准输出,而fprintf打印到指定的文件stream 中。sprintf并不打印到文件,而是打印到用户提供的缓冲区str 中并在末尾加'\0',由于格式化后的字符串长度很难预计,所以很可能造成缓冲区溢出,用snprintf 更好一些,参数size指定了缓冲区长度,如果格式化后的字符串长度超过缓冲区长度,snprintf 就把字符串截断到size-1 字节,再加上一个'\0'写入缓冲区,也就是说snprintf 保证字符串以'\0'结尾。snprintf 的返回值是格式化后的字符串长度(不包括结尾的'\0'),如果字符串被截断,返回的是截断之前的长度,把它和实际缓冲区中的字符串长度相比较就可以知道是否发生了截断。上面列出的后四个函数在前四个函数名的前面多了个v ,表示可变参数不是以... 的形式传进来,而是以va_list类型传进来。下面我们用vsnprintf包装出一个类似printf 的带格式化字符串和可变参数的函数。

#include <stdio.h>
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
#include <stdarg.h>
int vscanf(const char *format, va_list ap);
int vsscanf(const char *str, const char *format, va_list ap);
int vfscanf(FILE *stream, const char *format, va_list ap);
返回值:返回成功匹配和赋值的参数个数,成功匹配的参数可能少于所提供的赋值参数,返回0 表示一个都不匹配,出错或者读到文件或字符串末尾时返回EOF 并设置errno
scanf从标准输入读字符,按格式化字符串format 中的转换说明解释这些字符,转换后赋给后面的参数,后面的参数都是传出参数,因此必须传地址而不能传值。fscanf 从指定的文件stream 中读字符,而sscanf 从指定的字符串str 中读字符。后面三个以v 开头的函数的可变参数不是以... 的形式传进来,而是以va_list类型传进来。