由于在老式打印机里面每打下一行都要进行回车和换行,在windows系统里面也延续了这个惯例,但是c语言是只有换行,但是为了兼容,会自动进行转换;比如,它在写入文件的时候换行会自动转换为回车加换行,而读取文件的时候则是将回车将换行读取为回车;这时候编译器是把文件当作文本处理,如果不想把它们当作文本处理,这时候就可以把操作模式写成rb或者wb(binary意为二进制的),这里是把他们当作二进制处理(这样就不会有自动转换了)(但是不建议,虽然写入的时候好像没什么差错,但是读取的时候会有缺陷,暂时不明白原因);
下面再介绍fscanf函数:它的参数除了文件指针其他的和scanf函数没什么区别,它是读取文件里的内容的,这里举个例子:
#include<stdio.h>
int main()
{
FILE* fp = fopen("D:\\文件\\ww.txt","rb");
if (!fp)return -1;
//char bu[10];
/*while (fgets(bu, 10, fp) != NULL)
{
printf("%s", bu);
}*/
int f;
fscanf(fp, "%d", &f);
printf("%d", f);
fclose(fp);
return 0;
}
用这个代码可以读取刚刚的文本1234567相当于一个数字且在int范围内。但是要注意,在这个里面要记得把模式换位只读模式,而不是只写模式,否则就会读取错误;(这个w也就是只写操作的用法是真的要注意);
#include<stdio.h>
int main()
{
FILE* fp = fopen("D:\\文件\\ww.txt","r");
if (!fp)return -1;
//char bu[10];
/*while (fgets(bu, 10, fp) != NULL)
{
printf("%s", bu);
}*/
int f;
char a;
fscanf(fp, "%d%c", &f,&a);
printf("%d", f);
printf("%c", a);
fclose(fp);
return 0;
}
但是在这段代码里面结果是这样的:
也就是文本里面的换行也会被当作一个字符处理这时候就要注意了,有时候我们读取的是下一行的字符,就会不小心读成换行,所以这时候可以用一个函数fgetc(可以这么记:在getchar函数前加了一个f并省略了后面的)函数,这个函数的原型是这样的:int fgetc(文件类型的指针)它的原理:如果读取字符成功,返回这个字符的ASCII码,读取失败或到了文件结尾则返回EOF,先来介绍一下end of file 也就是EOF 它的宏定义是这样的:
#define EOF (-1)
在stdio.h头文件里面;可以用两外两个函数测试它们是那种错误:
feof用于文件是否结尾,ferror用于文件读取是否出错,(这里怎么样才算读取出错呢?也就是要去读取该文件的时,该文件却是不可读的,这就会读取失败);他们的函数原型差不多:
int feof(文件类型的指针);
int ferror(文件类型的指针);
如果是它们对应的错误就是返回非零也就是真,否则为0即假;来看这段代码:
#include<stdio.h>
int main()
{
FILE* fp = fopen("D:\\文件\\ww.txt","r");
if (!fp)return -1;
//char bu[10];
/*while (fgets(bu, 10, fp) != NULL)
{
printf("%s", bu);
}*/
int f;
char a;
fscanf(fp, "%d", &f);
fgetc(fp);
a = fgetc(fp);//这里发现了一个特点就是每次对了的都不会再读了
if (a == EOF)
{
if (feof(fp))printf("end of file\n");
if (ferror(fp))printf("file acess error\n");
}
printf("%d", f);
fclose(fp);
return 0;
}
这里可以发现读取文本时,在同一个程序里面,自从打开了某个文件,在同一个指针下是会有记录的,也就是说当用fscanf在这个文件里面读取完数字后,这个后面的fgetc是会接着往后读,而不是从头开始读,下面后有一个例子和这个不一样,上面的这个代码就是用来判断读完那个换行之后再读发生错误是什么错误,这里是读完了,里面没有了,如果把上面的代码里面的模式换成w模式,就是第二种读取失败,因为w是只写模式(如果没有该文件夹则创建,如果有,则清空该文件夹),是不可以读取的,就算可以也被清空了,就算清空之后在打印在文件里面,但是只要是w模式就是无法读取;因为我尝试过了;
#include<stdio.h>
int main()
{
FILE* fp = fopen("D:\\文件\\ww.txt","w");
if (!fp)return -1;
//char bu[10];
/*while (fgets(bu, 10, fp) != NULL)
{
printf("%s", bu);
}*/
int f;
char a;
fprintf(fp, "123456\n");
fscanf(fp, "%d", &f);
fgetc(fp);fclose(fp);
FILE* fpp = fopen("D:\\文件\\ww.txt", "r");
a = fgetc(fpp);//这里发现了一个特点就是每次对了的都不会再读了
if (a == EOF)
{
if (feof(fpp))printf("end of file\n");
if (ferror(fpp))printf("file acess error\n");
}
printf("%d\n", f);
printf("%c", a);
fclose(fpp);
return 0;
}
只要关闭了文件再重新打开它并且用另一个新的指针来,它就会要从头开始读取;
还有一个函数叫做fgets函数,它的参数有三个一个是读取的字符数组的首地址,还有就是该数组的最大容量,最后一个就是文件类型的指针,原理是这样的,读取成功返回数组首地址,不管是否遇到结尾,只要读取到了数据,就都是返回这个,如果知道结束后都没有读到数据,则返回空指针;读取错误也是返回空指针,这样之前的一段代码就很好说了;(我每次这么做的前提都是在这个文件里面有数据123456,记得每次操作都去看一下)
#include<stdio.h>
int main()
{
FILE* fp = fopen("D:\\文件\\ww.txt", "r");
if (!fp)return -1;
char bu[10];
while (fgets(bu, 10, fp) != NULL)
{
printf("%s", bu);
}
fclose(fp);
return 0;
}
这儿的意思是,每次fgetc-函数读取十个字符,知道读完为止,每读完十个都答应出来。(这里有一个要提醒的是,我们在文件里面读取数据就和在控制踏上读取我们输入的数据是一个性质,所以可以完全按照那个逻辑来);
-------------------------------------------------------------------------------------------------------------------------------------------