1.   fgets()与gets()

1.1  char * fgets (char * str, int num, FILE *stream);  

     //从流stream中读入最多num个字符到字符数组str中,当遇到换行符时、或读到num-1个字符时停止。                 

     //自动加上'\0'空字符结尾 

1.2   char * gets ( char * str ); 

读字符串函数 fgets

函数的功能是从指定的文件中读一个字符串到字符数组中

函数调用的形式为  

 fgets(字符数组名n文件指针)   其中的n是一个正整数。表示从文件中读出的字符串不超过 n-1个字符。

在读入最后一个字符后加上串结束标志'\0'。

例如fgets(str,n,fp);的意义是从fp所指的文件中读出n-1个字符送入 字符数组str中。

//从标准输入stdin读取一个字符串,遇到换行或结束时候终止。                 

//不同于fgets,他没有指定num,所以需要注意字符数组str的大小。

1. 在读出n-1个字符之前如遇到了换行符或EOF则读出结束。 

 2. fgets函数也有返回值其返回值是字符数组的首地址

    说明: fgets和gets之间没有宏定义的关系,彼此各自有自己的实现。蠕虫病毒的实现就是函数gets的“功劳”。gets函数的任务是从流中读入一个字符串。它的调用者会告诉它把读入的字符串放在什么地方。但是,gets()函数并不检查缓冲区大小,如果调用者提供了一个指向堆栈的指针,并且get()函数读入的字符数量超过了超过了缓冲区的空间大小,get()会愉快地将多出来的字符继续写入到堆栈中,这就覆盖了堆栈中原来的内容。

   如: main()

   char line[512];   

//在程序的堆栈上分配512个字符的空间 ...

   gets(line);      //蠕虫病毒的入口,可以将恶意代码通过多出来的数据写入堆栈

}  

1.3 fgetc()

读字符函数fgetc 

     fgetc函数的功能是从指定的文件中读一个字符   函数调用的形式为   字符变量=fgetc(文件指针)

    例如ch=fgetc(fp); 

    其意义是从打开的文件fp中读取一个字符并送入ch中。 

 对于fgetc函数的使用有以下几点说明 

 1) 在fgetc函数调用中读取的文件必须是以读或读写方式打开的。 

 2) 读取字符的结果也可以不向字符变量赋值

 3) 在文件内部有一个位置指针。用来指向文件的当前读写字节。在文件打开时,该指针总是指向文件的第一个字节。使用fgetc 函数后该位置指针将向后移动一个字节。 因此可连续多次使用fgetc函数,读取多个字符。应注意文件指针和文件内部的位置指针不是一回事。文件指针是指向整个文件的,须在程序中定义说明,只要不重新赋值文件指针的值是不变的。文件内部的位置指针用以指示文件内部的当前读写位置,每读写一次,该指针均向后移动它不需在程序中定义说明,而是由系统自动设置的。

1.4 写字符函数fputc 

 fputc函数的功能是从指定的文件中写入一个字符函数调用的形式为   

   fputc(字符常量或变量文件指量或变量) 

例如  fputc('a',fp);  其意putc函数的使用也要说明几点 

1) 被写入的文件可以用写、读写、追加方式打开用写或读写方式??写入字符从文件首开始。如需保留原有文件内容希望写入的字??被写入的文件若不存在则创建该文件。 

2) 每写入一个字符文件内部位置指针向后移动一个字节。 

3) fputc函数有一个返回值如写入成功则返回写入的字符否则返回一个EOF。可用此来判断写符写入一个文件再把该文件内容读出显示在屏幕上。

建议用fgets函数彻底替代gets函数。 另外,绝大多数的这些get函数,都有对应的put版本。

 int fputc ( int character, FILE * stream );

int putc ( int character, FILE * stream ); //通过宏定义和fputc实现 int putchar ( int character );        

//通过宏定义实现:

#define putchar(c) fputc(c, stdout)  

int fputs ( const char * str, FILE * stream );

int puts ( const char * str );

说明:两者之间无宏定义实现关系。puts(const char *str)近似等效于fputs(cosnt char *str, stdout),不同点是前者还输出一个'\n' 最后,

1.5 格式化读写函数fscanf和fprinf fscanf函数

fprintf函数与前面使用的scanf和printf 函数的功能相似都是格式化读写函数。

 两者的区别在于 fscanf 函数和fprintf函数的读写对象不是键盘和显示器而是磁盘文件。

这两个函数的调用格式为

fscanf(文件指针格式字符串输入表列)

 fprintf(文件指针格式字符串输出表列)

例如 fscanf(fp,"%d%s",&i,s);//从文件写出

fprintf(fp,"%d%c",j,ch); //写入

2.1   EOF

    EOF是在stdio.h文件中定义的符号常量,值为-1。如, fputc函数返回一个值:如果输出成功则返回值就是输出的字符;如果输出失败,则返回一个EOF。

  fgetc函数读字符时遇到文件结束符,函数返回一个文件结束标记EOF。如果想从一个磁盘文件顺序读入字符并在屏幕上显示,

可以: ch = fgetc(fp);while(ch != EOF)

 putchar(ch); 

 ch = fgetc(fp);

}  

注意,EOF不是可输出字符,因此不能在屏幕上显示。由于ASCII码不可能出现-1,因此EOF定义为-1是合适的。

当读入的字符值等于-1(即EOF)时,表示读入的已不是正常的字符,而是文件结束符。

但以上只适用于读取文本文件的情况。

现在ANSI C 已经允许用缓冲文件系统处理二进制文件,而读入某一个字节中的二进制数据的值有可能是-1,而这又恰好是EOF的值。这就出现了需要读入有用数据,却处理为“文件结束”。

2.2   feof(fp)

用来测试fp所指向的文件当前状态是否是“文件结束”。

如果想顺序读入一个二进制文件数据,可以:

while(!feof(fp))

    c = fgetc(fp);  

    ...

正确的写法应该是:
char c;
c = fgetc(fp);
while(!feof(fp))
{
printf("%X/n", c);
c = fgetc(fp);
}

 原因就是在读完最后一个字符后,fp->flag仍然没有被置为_IOEOF,因而feof()仍然没有探测到文件结尾。直到再次调用fgetc()执行读操作,feof()才能探测到文件结尾。