目录
- 例1:(使用字符输出函数fputc)
- 例2:(使用字符输入函数fgetc)
- 例3:(使用文本行输出函数fputs )
- 例4:(使用文本行输入函数fgets )
- 例5:(使用格式化输出函数fprintf)
- 例6:(使用格式化输入函数fscanf)
- 例7:(使用二进制输出函数fwrite)
- 例8:(使用二进制输入函数fread)
- 补充1:(sprintf函数)
- 补充2:(sscanf函数)
结构:
//主函数
int main()
{
//打开文件(写"w"/读"r")
FILE* pF = fopen("myfile.txt", "w");
//判断文件是否存在
if (pF == NULL)
{
perror("fopen");
return 1;
}
//进行写/读操作
//关闭文件
fclose(pF);
pF = NULL;
return 0;
}
stream
在此例中都为pF
,代表指向标识输出流的FILE
对象的指针
例1:(使用字符输出函数fputc)
FILE* pF = fopen("myfile.txt", "w");
//使用循环
int i = 0;
for (i = 0; i < 26; i++)
{
//打印在文件中
fputc('a' + i, pF);
//打印在屏幕上
fputc('a' + i, stdout);
}
fputc
的使用:int fputc ( int character, FILE * stream );
- 字符
character
被写入流stream
的内部位置- 指示器所指示的位置,然后自动向前移动一个。
运行后:
例2:(使用字符输入函数fgetc)
FILE* pF = fopen("myfile.txt", "r");
//读文件
int ch = fgetc(pF);
printf("%c\n", ch);
ch = fgetc(pF);
printf("%c\n", ch);
ch = fgetc(pF);
printf("%c\n", ch);
ch = fgetc(pF);
printf("%c\n", ch);
fgetc
的使用:int fgetc ( FILE * stream );
- 返回指定流
stream
的内部文件位置指示符当前指向的字符,然后将内部文件位置指示符推进到下一个字符- 如果流在被调用时位于文件的末尾,则该函数返回
EOF
并为流stream
设置文件结束指示器(feof
)- 如果发生读错误,该函数返回
EOF
并设置流stream
的错误指示器(error
)
运行后:
例3:(使用文本行输出函数fputs )
FILE* pF = fopen("myfile.txt", "w");
//写文本文件
fputs("hello word\n", pF);
fputs("hello real word\n", pF);
//打印在屏幕上
fputs("hello word\n", stdout);
fputs
的使用:int fputs ( const char * str, FILE * stream );
- 函数从指定的地址(str)开始复制,直到到达结束的空字符(‘\0’)
- 这个终止的空字符不会复制到流
stream
中fputs
不会写入额外的字符,换行需要自己加上'\n'
运行后:
例4:(使用文本行输入函数fgets )
FILE* pF = fopen("myfile.txt", "r");
//读文本文件
char arr[10] = { 0 };
fgets(arr, 10, pF);
printf("%s\n", arr);
fgets(arr, 10, pF);
printf("%s\n", arr);
fgets
的使用:char * fgets ( char * str, int num, FILE * stream );
- 从流
stream
中读取字符,并将其作为字符串存储到str中,直到读取(num-1)个字符,或者到达换行符或文件结束符,以先发生的为准。- 换行符使
fgets
停止读取,但它被函数认为是一个有效字符,并包含在复制到str
的字符串中- 若先读取到(num-1)个字符,则需要自行添加
'\n'
使得在打印屏幕上显示出换行- 在复制到str的字符之后,将自动追加一个终止null字符
运行后:
例5:(使用格式化输出函数fprintf)
//结构体
struct S
{
int a;
float f;
};
//主函数
FILE* pF = fopen("myfile.txt", "w");
//写文本文件
struct S s = { 100,3.14f };
//打印在文本内
fprintf(pF, "%d %f", s.a, s.f);
//打印在屏幕上
fprintf(stdout, "%d %f", s.a, s.f);
fprintf
的使用:int fprintf ( FILE * stream, const char * format, ... );
- 与
printf
的区别仅在于形参FILE * stream
- 在
printf
的用法上加上参数流stream
运行后:
例6:(使用格式化输入函数fscanf)
//结构体
struct S
{
int a;
float f;
};
//主函数
FILE* pF = fopen("myfile.txt", "r");
//从文本内读取
struct S s = { 100,3.14f };
fscanf(pF, "%d %f", &(s.a), &(s.f));
//打印在屏幕上
printf("%d %f", s.a, s.f);
fscanf
的使用:int fscanf ( FILE * stream, const char * format, ... );
- 与
scanf
的区别仅在于形参FILE * stream
- 在
scanf
的用法上加上参数流stream
运行后:
例7:(使用二进制输出函数fwrite)
//结构体
struct S
{
int a;
float f;
char str[10];
};
//主函数
FILE* pF = fopen("myfile.txt", "wb");
//写文件
struct S s = { 100,3.14f,"hello"};
fwrite(&s, sizeof(struct S), 1, pF);
fwrite
的使用:size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
- 将由
count
元素组成的数组(每个元素的大小为size
字节)从ptr
所指向的内存块写入流stream
中的当前位置- 流
stream
的位置指示器按写入的总字节数前进- 在内部,该函数将
ptr
指向的块解释为unsigned char
类型的(size*count
)元素数组,并将它们顺序写入流stream
运行后:
文本文件中为乱码的原因:fwrite
写入文本中的为二进制编码,无法直接显示出,用fread
函数可以读取出
例8:(使用二进制输入函数fread)
//结构体
struct S
{
int a;
float f;
char str[10];
};
//主函数
FILE* pF = fopen("myfile.txt", "rb");
//读文件
struct S s = { 0 };
fread(&s, sizeof(struct S), 1, pF);
printf("%d %f %s\n", s.a, s.f, s.str);
fread
的使用:size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
- 从流
stream
中读取一个由count
元素组成的数组,每个元素的大小为size
字节,并将它们存储在ptr
指定的内存块中- 流
stream
的位置指示器按读取的总字节数前进- 如果成功读取的总字节数为(
size*count
)
运用后:
补充1:(sprintf函数)
int sprintf ( char * str, const char * format, ... );
将格式化的数据,转换为字符串
- 如果在
printf
上使用format
,则使用将打印的相同文本组成一个字符串,但不是打印,而是将内容作为字符串存储在str
指向的缓冲区中- 缓冲区的大小应该大到足以包含整个结果字符串
- 在内容之后自动附加一个终止
null
字符
struct S
{
int a;
float f;
char str[10];
};
int main()
{
char arr[30] = { 0 };
struct S s = { 100,3.14f,"hehe"};
sprintf(arr, "%d %f %s", s.a, s.f, s.str);
printf("%s\n", arr);
return 0;
}
将结构体
struct S s
中的数据按照"%d %f %s"
的格式,转化为字符串存储在arr
指向的缓冲区中
观察arr
内的变化
补充2:(sscanf函数)
int sscanf ( const char * s, const char * format, ...);
从字符串中读取格式化的数据
- 从
s
中读取数据,并根据参数格式将其存储到附加参数给出的位置,就像使用了scanf
一样,但从s
中读取数据,而不是从标准输入(stdin
)中读取- 额外的参数应该指向已经分配的对象,其类型由格式字符串中相应的格式说明符指定
struct S
{
int a;
float f;
char str[10];
};
int main()
{
char arr[30] = { 0 };
struct S s = { 100,3.14f,"hehe" };
struct S tmp = { 0 };
sprintf(arr, "%d %f %s", s.a, s.f, s.str);
sscanf(arr, "%d %f %s", &(tmp.a), &(tmp.f), tmp.str);
printf("%d %f %s\n", tmp.a, tmp.f, tmp.str);
return 0;
}
从
arr
中读取数据,由"%d %f %s"
的格式字符串中相应的格式说明符指定分配到结构体struct S tmp
中
观察数据变化