c语言FILE结构和字符串读取

来源:互联网 发布:如何更改淘宝店铺名 编辑:程序博客网 时间:2024/05/16 18:07

c语言FILE结构和字符串读取

软件:gcc 版本 4.4.6 20120305 (Red Hat 4.4.6-4) (GCC)

本文通过FILE结构stdio.h中的定义, 解析c语言对标准输入和文件输入的实现,有助于深入理解和使用stdio.h 中的函数。

1 FILE结构


1.1 /usr/include/stdio.h

49行

typedef struct _IO_FILE FILE;

75行

#include <libio.h>

164-167行

/* Standard streams.  */extern struct _IO_FILE *stdin;          /* Standard input stream.  */extern struct _IO_FILE *stdout;         /* Standard output stream.  */extern struct _IO_FILE *stderr;         /* Standard error output stream.  */

stdio.h文件的49行和164-167行显示:标准输入stdin、标准输出stdout和标准错误stderr,均为FILE结构的指针。

FILE结构的具体定义在文件libio.h中。

1.2 /usr/include/libio.h

123-138行

#define _IO_USER_BUF 1 /* User owns buffer; don't delete it on close. */#define _IO_UNBUFFERED 2#define _IO_NO_READS 4 /* Reading not allowed */#define _IO_NO_WRITES 8 /* Writing not allowd */#define _IO_EOF_SEEN 0x10#define _IO_ERR_SEEN 0x20#define _IO_DELETE_DONT_CLOSE 0x40 /* Don't call close(_fileno) on cleanup. */#define _IO_LINKED 0x80 /* Set if linked (using _chain) to streambuf::_list_all.*/#define _IO_IN_BACKUP 0x100#define _IO_LINE_BUF 0x200#define _IO_TIED_PUT_GET 0x400 /* Set if put and get pointer logicly tied. */#define _IO_CURRENTLY_PUTTING 0x800#define _IO_IS_APPENDING 0x1000#define _IO_IS_FILEBUF 0x2000#define _IO_BAD_SEEN 0x4000#define _IO_USER_LOCK 0x8000

271-312行

struct _IO_FILE {  int _flags;/* High-order word is _IO_MAGIC; rest is flags. */#define _IO_file_flags _flags  /* The following pointers correspond to the C++ streambuf protocol. */  /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */  char* _IO_read_ptr;/* Current read pointer */  char* _IO_read_end;/* End of get area. */  char* _IO_read_base;/* Start of putback+get area. */  char* _IO_write_base;/* Start of put area. */  char* _IO_write_ptr;/* Current put pointer. */  char* _IO_write_end;/* End of put area. */  char* _IO_buf_base;/* Start of reserve area. */  char* _IO_buf_end;/* End of reserve area. */  /* The following fields are used to support backing up and undo. */  char *_IO_save_base; /* Pointer to start of non-current get area. */  char *_IO_backup_base;  /* Pointer to first valid character of backup area */  char *_IO_save_end; /* Pointer to end of non-current get area. */  struct _IO_marker *_markers;  struct _IO_FILE *_chain;  int _fileno;#if 0  int _blksize;#else  int _flags2;#endif  _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */#define __HAVE_COLUMN /* temporary */  /* 1+column number of pbase(); 0 is unknown. */  unsigned short _cur_column;  signed char _vtable_offset;  char _shortbuf[1];  /*  char* _save_gptr;  char* _save_egptr; */  _IO_lock_t *_lock;#ifdef _IO_USE_OLD_IO_FILE};

libio.h中271-312行定义了FILE结构, 123-138行定义了FILE结构中_flags状态标志的各个位的含义, 如_IO_EOF_SEEN对应的位标志文件是否结束。

FILE结构默认的输出缓冲区大小为4096个字符,缓冲区对应的指针作用如下:

缓冲区指针作用_IO_read_base指向从文件中载入到输入缓冲区的所有字符中的第一个;_IO_read_ptr指向当前缓冲区中第一个未被读取的字符,当ptr==end时, 表示输入缓冲区已为空,此时再对文件进行读取, EOF标志会被设置,并且这六个指针全部置为base指针的值;_IO_read_end指向从文件中载入到输入缓冲区的 所有字符中的最后一个的下一个位置;_IO_write_base指向输出缓冲区的基地址;_IO_write_ptr指向当前输出缓冲区最后一个字符的下一个位置, ptr==end时进行写入,会把缓冲区的数据输出到文件, 然后ptr=base,再将字符写到ptr位置;_IO_write_end指向当前输出缓冲区的最后一个位置。

2 字符串读取

函数原形注意点int fgetc ( FILE * stream );返回值为int类型,读取成功,返回读取字符;
当文件流已置EOF标志时,返回EOF(-1);
遇到读取错误时,置错误标志,返回EOF。int getc ( FILE * stream );功能与fgetc相同,但在一些实现里,getc为一个宏。int getchar ( void );功能与getc(stdin)相同。int fputc ( int character, FILE * stream );写入成功时,返回character;
遇到写入错误时,置错误标志,返回EOF。int putc ( int character, FILE * stream );功能与fputc相同,但在一些实现里,putc为一个宏。int putchar ( int character );功能与putc(character, stdout)相同。char * fgets ( char * str, int num, FILE * stream );读取num-1个字符,或者遇到newline字符,或者遇到文件结束时停止读取。
newline会作为有效字符存入str中。str以NULL结束。
读取成功返回str;
当一开始就遇到文件结束,返回NULL,str内容不变;
当遇到error,返回NULL,str会被改变。char * gets ( char * str );读取时遇到newline字符,或者遇到文件结束时停止读取。gets可能会溢出,一个bug。
newline被抛弃,不会被作为有效字符存取str中,str以NULL结束。
返回与fgets相同。int fputs ( const char * str, FILE * stream );将字符串str写入stream,直到遇到NULL,NULL不会被写入stream。与puts不同。
写入成功返回非负数;写入错误时,置错误标志,返回EOF。int puts ( const char * str );在fputs基础上,puts会多写入一个newline。
0 0