之前出过的文件FILE函数的小白篇,现在出一个全面一些的
以下讲解直接分为函数原型+函数作用+测试用例
让大家真真正正的理解和感受这几个FILE函数的作用
二话不说,开冲!
额…先来个小表格:
在这里再重复一下上一篇讲述过的几个基本的FILE函数,由于这几个函数在上一个博客都有讲过,而且比较基础简单在这里就没有测试用例啦,直接简单看函数原型和作用☺☺☺
★fopen()函数
✿、函数原型:FILEfopen(charfilename,char*type);
✿、函数作用:
打开一个“流“
★fclose()函数
✿、函数原型:
int fclose(char*filename);
✿、函数作用:
关闭一个“流“
★fprintf()函数
✿、函数原型:
int fprintf(charfilename,charformat[,argument,…])(format就是要写入的参数)
✿、函数作用:
传送格式化文本形式输出到一个流中
好了,结束了上面几个在小白篇出现的三个常用FILE函数,让我们进入正题:
首先,在这里回答一个问题:
在开始接触FILE函数这一个模块的时候,先了解一下文件的类型,常见的有二进制类的,还有文本形式类的,怎么区分呢?
简记:一个是看不懂的文字,而一个是你看得懂的
个人认为,言简意赅,十分易记
演示一波
二进制文件:
文本文件:
简单理解了之后,细细想想这两个到底有什么区别和差异,在这里我不多加赘述,这一篇是讲述FILE函数的,所以以下内容主要对我怎么写二进制文件、怎么写文本文件等等一系列操作进行函数剖析和演示,具体这两个形式有什么具体区别,我会在下一篇出♥♥♥♥♥
feof()函数
✿、函数原型:
int feof(FILE*stream);额…和前面区别一下嘛
✿、功能:
检测流上的文件结束符
没有什么特别意思,就是检测到你的文件到末尾了,后面没有东西了♞
✿、程序用例:
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main() {
FILE* fp;
fp = fopen("test.txt","r");
char c = '0';//初始化中间变量
if (fp == NULL)
{
printf("打开文件失败!\n");
exit(0);
}
while (!feof(fp))//feof(fp)==NULL,代表已经结束,这句话非常常用
{
c=fgetc(fp);
printf("%c\n",c);
}
if (feof(fp))
{
printf("We have reached the end!\n");
}
fclose(fp);
return 0;
}
test.txt文件内容:
结果:
之前有些人有问到关于”空格“的问题,在这里大家可以放心,feof()函数它就是可以检测到这个文件到底有没有结束,就像这里我空了几个空格,它也会算进去的,不得不说,酷
fgetc()函数
在上面的代码中,相信眼尖的小伙伴看到了这一句:
c=fgetc();
✿、函数原型:
int fgetc(FILE*stream);
✿、作用:
从流中读取字符(就是一个一个去读,及其好用)
✿、程序用例:
额…我写到这里我发现,咦?上面那个程序测试用例好像已经说明了这个函数的意思了
咳咳,那好吧,就再来其他的组合好了
fgetchar ()、fputchar()、freopen()函数登场
✿、函数原型
int fgetchar(void);
int fputchar(char ch);
FILE *freopen(char *filename, char *type, FILE *stream);
✿、函数功能:
**fgetchar:从流中读取字符,fgetchar()其实它等价于fgetc(stdin),而且使用VS的朋友,怎么说呢,我记得好像在V C++2005年开始,fgetchar()这个函数已经被废弃了,要使用_fgetchar()代替使用,包括下面的fputchar也是前面要修改,具体看下案例代码
**fputchar:送一个字符到标准输出流(stdout)中
**freopen:将一个新的名为filename与给定的打开流stream关联,同时关闭流中的旧文件,在函数定义时的stream–它指的就是指向FILE对象的指针,该指针对象标识了要被重新打开的流
★stream常用三个值:
stdout(Standardoutput)标准输出
stdin(Standardinput)标准输入
stderr(Standarderror)标准错误
根据官网的解释就是:只是方便操作输出,比如传给一个函数等等。这时函数的输出就不是输出到文件,而是传进来的stdout文件指针,即标准输出。(stdout为例)
具体的用法如下:
✿、程序案例:
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main(void)
{
int c;
FILE* fp;
fp = freopen("test.txt","r",stdin);
if (fp != NULL)
{
while ((c = _fgetchar()) != EOF)//输入功能
{
_fputchar(c);//输出功能
}
}
fclose(fp);
return 0;
}
test文件:
结果:
现在不改变test文本内容,让我们看一看freopen()函数的“关联”特性,我们执行以下代码:
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main(void)
{
FILE* fp;
printf("----让文本重定向到 stdout测试---\n");
fp = freopen("test.txt", "a+", stdout);
printf("该文本重新定位到到 test.txt\n");
printf("测试结束啦啦啦!");//输出变成到文件输出去了,控制台没有这一句输出了
fclose(fp);
return 0;
}
结果:
test.txt文件变成:
会发现只要使用了这个函数,它的意思就是你将你的输出就比如printf,大家都知道这个是直接输出到控制台的,可是会发现它在你的文件中输出了,有种重新指定的意味,它关联了你所指定的文件,这也是这个函数最重要的功能之一
fscanf()函数
✿、函数原型
int fscanf(FILE *stream, char *format[,argument…]);
✿、功能
从一个流中执行格式化输入
✿、程序案例:
额…先重现让test.txt文件恢复原样:
ok,继续
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main(void)
{
FILE* fp;
char c = '0';
fp = fopen("test.txt", "r");
while (!feof(fp))
{
fscanf_s(fp,"%c",&c,1);//1为缓冲区大小,就跟你用scanf_()一样
printf("%c",c);
}
fclose(fp);
return 0;
}
这个函数的作用就是跟scanf非常的像,就是简单的一个赋值的操作,也非常的常用
结果:
将文件中的东西通过赋值给c输出,这个函数较为简单,过过过
fwrite()函数和fread()函数姐妹花组合
前面讲的大部分用于文本文件,就比如fprintf()就是以格式化的数据写进去,fscanf_()也是一般用于文本的读取,那么对于二进制文件我们应该怎么处理呢?这两个函数便是主要用于处理二进制读写的函数
除此之外呢,这两个函数主要是读取“数据块”,看它的函数原型
✿、函数原型
int fread(void *ptr, int size, int nitems, FILE *stream);
int fwrite(void *ptr, int size, int nitems, FILE *stream);
解释一下:
ptr指的就是表示存放输入数据的首地址(一般会用数组)
size是指数据块的字节数,nitems是指读取的数据块的个数
比如说:fread(arr,4,5,fp)意义就是从fp所指的文件中,每次读入4个字节送入到arr数组中,连续读五次
✿、功能
这两个函数相信大家字面意思也能懂了,就是一个读、一个写,就是这么狠
具体看下
而且而且大家一定要注意的是:在读写二进制文件时候,必须确保文件的打开形式是以二进制读写的形式打开的,即类似“rb”,"wb"等
✿、程序案例:
举一个非常简单的例子
fwrite():
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main()
{
FILE* fp;
fp = fopen("test_1.data","rb+");
int buf[40];
char arr[40] = "\0";
char c = '\0';
int i = 0;
if (fp == NULL)
{
printf("faile open the file\n");
exit(0);
}
for (int i = 0; i < 5; i++)
{
scanf_s("%d",&buf[i]);
}
fwrite(buf,sizeof(int),5,fp);
fclose(fp);
return 0;
}
测试输入:10100
结果:
乱码(字节大小:20(int是4,5个4=20))
就着上面已经有的这个二进制文件,我们用fread()函数去解读它:
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main()
{
FILE* fp;
fp = fopen("test_1.data","rb+");
int buf[40];
int arr[40];
char c = '\0';
int i = 0;
fseek(fp,SEEK_SET,0);//从文本开头开始读取
fread(arr,20,1,fp);
for (int i = 0; i < 5; i++)
{
printf("%d",arr[i]);
}
fclose(fp);
return 0;
}
结果:
不得不说,强大
fseek()函数
这个函数比较简单理解,就是规定文件指针位置,比如你不想每次都从文件首部开始,想从一个特定的位置开始,那么这个函数就是起到这样一个作用的
✿、函数原型
int fseek(FILE *stream, long offset, int fromwhere);
✿、功能
重新定义流上的文件指针
offset:相对于fromwhere的偏移,以字节为单位
fromwhere:偏移的位置
一般指定为下列三个常量之一:
SEEK_SET 文件的开头
SEEK_CUR 文件指针的当前位置
SEEK_END 文件的末尾
✿、程序案例
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main()
{
FILE* fp;
fp = fopen("test.txt","r");
char c = '0';
if (fp == NULL)
{
printf("fail open the file!\n");
exit(0);
}
printf("现在从距离起点4个字节位置开始读取:\n");
fseek(fp,4,SEEK_SET);
while (!feof(fp))
{
fscanf_s(fp,"%c",&c,1);
printf("%c",c);
}
fclose(fp);
return 0;
}
结果:
基于这个函数比较简单,大家可以自己去玩一玩,在这里不赘述更多的测试用例了
ftell()函数
✿、函数原型:
long ftell(FILE *stream);
✿、功能:
返回当前文件的指针(额…就是文件字节数啦)
✿、程序测试用例:
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main()
{
FILE* stream;
stream = fopen("test.txt", "w+");
fprintf(stream, "This is a test");
printf("The file pointer is at byte % ld\n", ftell(stream));
fclose(stream);
return 0;
}
结果:
fgets()函数
前面讲了fgetc()函数,现在来一个它的兄弟
✿、函数原型:
char *fgets(char *string, int n, FILE *stream);
✿、功能
从流中读取字符串
✿、程序案例:
#define _CRT_SECURE_NO_WARNINGS
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
int main()
{
FILE* stream;
char string[] = "I am X BIG MONSTER";
char msg[20];
stream = fopen("test.txt", "w");
fwrite(string, strlen(string), 1, stream);
fseek(stream, 0, SEEK_SET);
fgets(msg, strlen(string) + 1, stream);
fclose(stream);
return 0;
}
结果:
总结
还是那句话,自己多动手,就会发现奥妙之处
可能不够完善,我会努力更哒