按照300字/min,本文阅读大约要17min 左右
所有读写字符的函数
为了保证你们能够和之前的文件操作连接起来,我们重新展示了一下所有的读写函数 可以不看,这个是复习用的
函数名 | 返回值 | 参数 |
---|
fgetc | int(读取失败是 EOF,成功返回读取的字符的asc码) | (FILE* stream) | fputc | int(写入失败是 EOF,成功返回读取的字符的asc码) | ( int character, FILE * stream ) | fgets | char *(成功返回 字符串, 失败返回NULL) | ( char * str, int num, FILE * stream ) | fputs | 成功返回非负数,失败返回 EOF) | ( const char * str, FILE * stream ) | fscanf | 成功会返回应该读取的元素个数,失败会返回小于应该读取的元素的个数 | ( FILE * stream, const char * format, … ) | fprintf | 成功会返回应该写入的元素个数,失败会返回负数 | ( FILE * stream, const char * format, … ) | fread | 成功返回读取的元素个数,失败返回个数小于 count | ( void * ptr, size_t size, size_t count, FILE * stream ); | fwrite | 成功返回读取的元素个数 | ( const void * ptr, size_t size, size_t count, FILE * stream ) |
字符以外的读写
一行字符的读写
主要是这两个函数
函数 | 功能 |
---|
fgets | 一次读取一个字符串 | fputs | 一次输入一个字符串 |
char * fgets ( char * str, int num, FILE * stream );
int fputs ( const char * str, FILE * stream );
fgets 会让第 num 个值设置为 \0,所以要读 num 个字符的字符串,实际显示只有 num - 1 个字符
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main() {
char str[10] = { 0 };
FILE* pF = fopen("example.txt","r");
if (pF == NULL)
{
perror("fopen");
return;
}
fgets(str,4,pF);
fclose(pF);
pF = NULL;
printf("%s\n", str);
return 0;
}
在 This is 的文件中只能拿出 Thi
通过一定的想象能力,我们可以知道
fputs(str,pF);
带格式的读写
但是,许多情况下,文件不是读写字符就可以完成全部的工作的,C语言有丰富的数据类型,比如 int ,double 等,他们有应该能够被我们放进文件中,为了完成这个任务,我们可以使用带格式的读写
我们可以使用这两个函数
函数 | 功能 |
---|
fscanf | 从文件中带格式读取 | fprintf | 带格式地写入到文件中 |
他们两兄弟很像 printf 和 scanf 两兄弟 他们的使用也几乎是一样的
int a = 0;
FILE* pF = fopen("test.txt","r");
scanf("%d",&a);
fscanf(pF,"%d",&a);
printf("%d",a);
fprintf(pF,"%d",a);
如果我们要向文件写一个数组 到 test.txt 然后再读取出来,应该如何做
通过循环一个个写入,然后一个个读取出来就可以了 代码如下
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a[10] = {2,5,4,6,9,7,8,3,1};
int i = 0;
FILE* pF = fopen("test.txt","w");
if (pF == NULL)
{
perror("fopen");
return 1;
}
for (i = 0; i < 10; i++)
{
fprintf(pF,"%d ", a[i]);
}
fclose(pF);
pF = NULL;
return 0;
}
当我们运行完,文件里面就有我们的数组了 然后读取出来 代码如下
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a[10] = {0};
int i = 0;
FILE* pF = fopen("test.txt","r");
if (pF == NULL)
{
perror("fopen");
return 1;
}
for (i = 0; i < 10; i++)
{
fscanf(pF, "%d", a + i);
}
fclose(pF);
pF = NULL;
for (i= 0;i<10;i++)
{
printf("%d ",a[i]);
}
return 0;
}
运行打印得到 这两兄弟和 printf 和 scanf 很相似,我们合理猜测一下,我们能不能把我们键盘的输入直接通过 fscanf 和 fprintf 来进行输出呢? 结论是可以的
标准输入输出
对于程序来说,有三种标准流, 标准输出流叫做stdout,是我们的屏幕 标准输入叫做stdin,是我们的键盘 标准错误流叫做stdout,是我们的屏幕 这个时候,我们可以将标准流看成文件 直接通过 fscanf 和 fprintf 从键盘读取数据后写到我们的屏幕上 代码如下
int main()
{
int a = 0;
fscanf(stdin,"%d",&a);
fprintf(stdout,"%d",a);
return 0;
}
右下角为输入输出
printf 和 scnaf 族
scanf/fscanf/sscanf
函数 | 功能 |
---|
scanf | 从标准输入(键盘)有格式地读取 | fscnaf | 从任意输入(文件或键盘)有格式地读取 | sscanf | 从字符串中有格式地读取 |
printf/fprintf/sprintf
函数 | 功能 |
---|
printf | 从标准输入(键盘)有格式地打印 | fprintf | 从任意输入(文件或键盘)有格式地写入 | sprintf | 从字符串中有格式地写入 |
二进制的读写
C语言 是允许我们自定义数据类型的,比如 struct,union 等等 这些长度可变的东西 , 单独的格式读取就满足不了我们了,C语言允许我们将内存一样对待文件,直接按照字节来直接把内容放到文件里面 但是前提是 我们是以二进制的方式来打开,关闭,读取和写入文件(打开方式是 wb 与 rb )
二进制文件和文本文件
二进制文件的相对概念就是文本文件 文本文件就是我们看到的文件内容,他是以字符的形式展示出来,我们能够认得的 比如上一个例子中的格式数组写入和读取,他的文件我们可以直接看得明白,内容是对应的 asc码放在文件中,这个就是文本文件 但是 有一种文件,程序不会将要写入或者读取的数据转换为 asc 码,而是直接按照机器的二进制写入和读取 这个时候那个文件就是二进制文件 区别就是 同一个内容的储存方式是二进制或者是 asc 码
如果之前的这个数组 我们通过二进制的方式写到文件中,显示出来时什么样子呢、 得到一群乱码,但是计算机读的明白就可以了,这个无所谓 我们通过二进制读取,打印得到的结果是一样的
二进制读写函数
有两个函数用来帮助我们按照字节一般帮我们把内容从文件中拿出,或者放到文件里面
函数 | 功能 |
---|
fread | 按照二进制方式读取文件 | fwrite | 按照二进制方式写入文件 |
如果我们要写入一个书架,这个书架中有 好多本书,每一本书有书名,书的价格等 那应该如何写入呢? 假设三本书分别叫 “peace and war”,“C++ prime”,dead" 代码如下
int main()
{
struct Book bookshe[3] = { {"peace and war",40},{"C++ prime",35},{"dead",25}};
FILE* pF = fopen("my_book.txt","wb");
if (pF == NULL)
{
perror("fopen");
return 1;
}
fwrite(bookshe,sizeof(struct Book),3,pF);
fclose(pF);
pF = NULL;
return 0;
}
里面文件是这样的
我们读取出来,然后分别打印
int main()
{
struct Book bookshe[3] = { 0};
FILE* pF = fopen("my_book.txt","rb");
if (pF == NULL)
{
perror("fopen");
return 1;
}
fread(bookshe,sizeof(struct Book),3,pF);
fclose(pF);
pF = NULL;
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%s\n",bookshe[i].name);
}
return 0;
}
结果是这样的
文件和系统的关系
之前 我们读取文件时使用的是"文件缓冲系统",这个系统在对文件进行操作的时候会自动为正在使用的文件开辟一个文件缓冲区 这个缓冲能够提高文件操作的效率,当缓冲区满的时候,才进行下一步操作 举个例子,我要是有问题,一想到直接问老师,还是存一会再去问老师效率高呢? 第二种是不是老师也能做些别的事情?
比如把数据写到硬盘里头,把数据读取到内存数据区中 通过 fclose 和 fflash 能够对缓冲区强制刷新,缓冲区的内容直接强制下一步执行
在这里我们可以想到 getchar 这些从键盘读取的函数也有缓冲区的概念 限于篇幅就不讲了
总结
C语言提供了字符串读写,格式化读写和二进制读写,我们把重点放在了格式化读写和 scanf 和printf 族的比对上,同时也见识到了 二进制读写直接无视格式,按照长度直接读写的强大功能,最后我们也看到了为了快速性,缓存区的概念也运用到了文件当中
|