一种奇怪现象
#include <stdio.h>
#include <stdlib.h>
#include<windows.h>
int main(void){
int i;
printf("hello\n");
fflush(stdout); //当没有这部刷新,hello会和end等到时间一起输出
Sleep(2000); //windowsa.h中的Sleep,表示暂停2s
printf("end\n");
return 0;
}
没有fflush刷新标准输出流,hello和end将最后同时输出,导致这种情况的原因是缓存
刷新缓存的情况
三种缓冲方式:无缓冲,行缓冲(遇到换行符执行),全换成冲(缓冲区满执行)
1. 内存满时
2. 换行符“\n”
3. 调用fflush
4. 程序结束
fgets缓存空间问题
其中默认读取n-1个字符和自动添加字符串结束符号\0
char *fgets(char *str, int n, FILE *stream)
str:字符数组指针,用于存放读取的字符;n:读取n-1个字符;stream:文件流指针
下面主要测试存放的缓存字符数组和字符个数关系导致的输出不同情况,设缓存字符数组大小为m,字符流文本是1到9字符
当m>=n时,都可以正常读取和显示
根据测试发现m=n-1时也是正常执行,相当于读取了m个字符将缓存填满,但按照解释应该有一个“\0”的字符在最后一位填充,
FILE *fp;
char buffer[5];
fgets(buffer,4,fp);
printf("fgets: %s\n",f_gets); //这里的m=5,n=4,所以正常读取,显示123
printf("erro :%d\n",ferror(fp)); //这里错误检测是0
当m=n-1时,可以显示,但并不正确,会影响后来对文件流读取
第一种:fgets函数不进行赋值,文件流中的缓存被清空(个人通过猜测,不知道有没有大神能够解释),后面若想读入字符,需要从键盘输入读取
FILE *fp;
char buffer[5],re_gets[5];
fgets(buffer,7,fp);
printf("fgets: %s\n",f_gets); //这里的m=5,n=7,所以正常读取,显示12346
printf("erro :%d\n",ferror(fp)); //这里错误检测是0
fseek(fp,2,0); //文件流指针指向第三个字符
fgets(re_gets,5,fp); //这时候仿佛这个文件流fp被清空,若在cmd窗口,需要键盘输入才能执行
printf("fgets: %s\n",re_gets);
第二种:fgets函数进行赋值,文件流不被清空,后面的取得数据仍可以从文件流读取
FILE *fp;
char buffer[5],re_gets[5],*ret_gets; //添加ret_gets做为fgets的返回值
fgets(buffer,7,fp);
printf("fgets: %s\n",f_gets); //这里的m=5,n=7,所以正常读取,显示12346
printf("erro :%d\n",ferror(fp)); //这里错误检测是0
fseek(fp,2,0);
ret_gets = fgets(re_gets,5,fp); //!!!和上面的不同
printf("re_gets: %s\n",re_gets); //这里显示3456
当m<=n-2时,fgets执行的语句直接报错
这时候程序不能向下执行,直接跳过后面的程序
fread读取需要注意的地方
printf输出字符串需要注意的地方:结尾是否有"\0",
#include <stdio.h>
#include <stdlib.h>
int main(void){
char a[5]={'1','2','3','4','5'};
char b[5]={'1','2','3','4','5'};
printf("%p\n",a); //000000000061FE1B
printf("%p\n",b); //000000000061FE16
printf("%s\n",b); //1234512345p
return 0;
}
所以下面的程序中就出现了这种显示问题
#include <stdio.h>
#include <stdlib.h>
int main(void){
FILE *fp;
char f_getc,f_gets[5],*f_gets_return,f_read[4];
fp = fopen("file.txt","r");
rewind(fp); //重移动文件指针到最开始
f_gets_return=fgets(f_gets,6,fp); //这里不用赋值语句,文件流会清空,这里的“一定”要是一个字符串数组
printf("fgets: %s\n",f_gets); //得到n-1个字符,最后一个自动填充\0
rewind(fp);
fread(f_read,sizeof(char),4,fp);
printf("fread: %s\n",f_read);
fclose(fp);
return 0;
}
对读取的字符个数调整,fread(f_read,sizeof(char),3,fp);
,就得到下面的结果
结果分析
fgets的函数调用中,读取的数据会比第二个参数少1,而fread读取的字符数量和第三个参数的数量一样。通过这些判断缓存中是否存放了字符结束符。