一、简述
标准库的I/O函数:
fopen(), fread(), fwrite(), fseek(), fclose(),fprintf(),fscanf(),ftell(),rewind()
格式化字符串:
sprintf(),sscanf()
系统I/O和标准I/O区别:
1、移植性
系统函数移植性有限,标准函数移植性高。
2、文件IO层次
系统IO函数为低级,标准IO函数为高级,
区分标准:低级文件IO运行在内核态,高级文件IO运行在用户态。
3、缓冲区
系统函数不带缓冲区,标准函数自带缓冲区。系统函数既可以读写字符、字符串、格式化数据,也可以读写二进制数据。标准函数只能读写二进制文件,但效率高、速度快。
二、标准I/O
fopen()函数 | ||
功能 | 打开指定文件并获取文件结构体指针,或创建新文件 | |
头文件 | #include <stdio.h> | |
声明 | FILE *fopen(const char *path, const char *mode) | |
参数 | path | 文件路径名称 |
mode | 文件打开方式 | |
返回值 | 成功 | 返回文件结构体指针 |
失败 | 返回NULL |
说明:
mode 文件打开方式
r 只读打开。流位于文件的开头。
r+ 在 r 基础上加上写权限。
w 只写打开。如果文件存在则清空文件内容。不存在则创建。
w+ 在 w 基础上加上读权限。
a 只写追加打开。如果文件存在则保留文件内容。不存在则创建。
a+ 在 a 的基础上加上读权限。
b b (二进制文件)与上列权限搭配使用,作为最后一个字符,或作为两个字符中任意一个字符之间的字符。
fclose()函数 | ||
功能 | 关闭文件 | |
头文件 | #include <stdio.h> | |
声明 | int fclose(FILE *fp) | |
参数 | fp | 指向需要关闭的文件的结构体指针 |
返回值 | 成功 | 返回 0 |
失败 | 返回 -1 |
fread()函数 | ||
功能 | 从给定流 stream 读取数据到 ptr 所指向的内存中 | |
头文件 | #include <stdio.h> | |
声明 | size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) | |
参数 | ptr | 存储读取到的数据的内存地址 |
size | 要读取的每个元素的大小,以字节为单位 | |
nmemb | 元素的个数,每个元素的大小为 size 字节 | |
stream | 指向读取对象的文件结构体指针 | |
返回值 | 成功 | 返回成功读取元素总数。 如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾。 |
失败 | 返回 0 | |
备注 | 剩余数据大小 < 元素大小则无法被读取 |
fwrite()函数 | ||
功能 | 将指定内存中的数据写入到文件中 | |
头文件 | #include <stdio.h> | |
声明 | size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream) | |
参数 | ptr | 存储需要写入的数据的内存地址 |
size | 要写入的每个元素的大小,以字节为单位 | |
nmemb | 元素的个数,每个元素的大小为 size 字节 | |
stream | 指向写入对象的文件结构体指针 | |
返回值 | 成功 | 返回写入元素总数。如果总数与 nmemb 参数不同,则可能发生了一个错误或者到达了文件末尾。 |
失败 | 返回 0 |
fseek()函数 | ||
功能 | 设置光标的位置 | |
头文件 | #include <stdio.h> | |
声明 | int fseek(FILE *stream, long offset, int whence) | |
参数 | stream | 指向需要改变光标的对象的文件结构体指针 |
offset | 偏移值 | |
whence (基准点) | SEEK_SET(文件头) | |
SEEK_CUR (光标当前位置) | ||
SEEK_END (文件尾) | ||
返回值 | 成功 | 返回 0 |
失败 | 返回 -1 |
fprintf()函数 | ||
功能 | 以文本形式,按照一定格式向文件写入数据 | |
头文件 | #include <stdio.h> | |
声明 | int fprintf(FILE *stream, const char *format, ...) | |
参数 | stream | 指向写入的文件的结构体指针 |
format | 占位符 | |
... | 与占位符相对应的变量名 | |
返回值 | 成功 | 成功写入的字节数 |
失败 | 返回 -1 |
fscanf()函数 | ||
功能 | 以文本形式,从文件中按照一定格式读取文件内容到变量中 | |
头文件 | #include <stdio.h> | |
声明 | int fscanf(FILE *stream, const char *format, ...) | |
参数 | stream | 指向要读取的文件的结构体指针 |
format | 占位符 | |
... | 与占位符相对应的变量名 | |
返回值 | 成功 | 成功读取的字节数 |
失败 | 返回 -1 |
说明:
占位符
%*s 或 %d 跳过该类型的数据 (到空格或\t止)
%[width]s 读指定宽度的数据
%[a-z] 匹配 a 到 z 中任意字符(尽可能多的匹配,不区分大小写)
%[aBc] 匹配 a 、 B 、 c 中的一员,贪婪性
%[^a] 匹配非 a 的任意字符,贪婪性
%[^a-z] 表示读取除 a-z 以外的字符
ftell()函数 | ||
功能 | 获取光标的位置(相对开头) | |
头文件 | #include <stdio.h> | |
声明 | long ftell(FILE *stream) | |
参数 | stream | 指向要获取光标位置的文件的结构体指针 |
返回值 | 成功 | 相对文件开头的字节数(包括\0) |
失败 | 返回 -1 |
rewind()函数 | ||
功能 | 将光标调至文件开头 | |
头文件 | #include <stdio.h> | |
声明 | void rewind(FILE* stream) | |
参数 | stream | 文件结构体指针 |
返回值 | 无 |
demo:
1. fopen() 创建文件 2. fwrite() 写入数据 3. ftell() 获取文件大小
4. rewind() 将光标调回文件头 5. fread() 读取数据并打印 6. fprintf() 写入数据
7. rewind() 将光标调回文件头 8. fscanf() 读取数据并打印 9. fclose() 关闭文件
#include <stdio.h>
#include <string.h>
int main()
{
FILE *fp;
char *w_buf = "hallo world!";
char r_buf[128] = {0};
int len = 0;
char *send = " fprintf success!";
if ((fp = fopen("./file", "w+")) == NULL) {
printf("error from fopen\n");
}
if (fwrite(w_buf, strlen(w_buf), 1, fp) != 1) {
printf("error from fwrite\n");
}
len = ftell(fp);
if (len == -1) {
printf("error from ftell\n");
} else {
printf("len = %d\n",len);
}
rewind(fp);
if (fread(r_buf, len, 1, fp) != 1) {
printf("error from fread\n");
} else {
printf("%s\n", r_buf);
}
if (fprintf(fp, "%s", send) == -1) {
printf("error from fprintf\n");
} else {
rewind(fp);
if (fscanf(fp, "%[^\t]s", r_buf) == -1) {
printf("error from fscanf\n");
} else {
printf("%s\n", r_buf);
}
}
fclose(fp);
return 0;
}
运行结果:
三、格式化字符串函数
sprintf()函数 | ||
功能 | 将变量按照一定的格式合并成字符串形式 | |
头文件 | #include <stdio.h> | |
声明 | int sprintf(char* str, const char* format, …) | |
参数 | str | 合成目标字符串首地址 |
format | 占位符 | |
... | 与占位符相对应的变量名 | |
返回值 | 成功 | 目标字符串实际长度 |
失败 | 返回 -1 | |
备注 | 匹配到字符串结束符 '\0' 结束 |
sscanf()函数 | ||
功能 | 从字符串中按照格式读取数据至变量中 | |
头文件 | #include <stdio.h> | |
声明 | int sscanf(char* str, const char* format, ...) | |
参数 | str | 字符串首地址 |
format | 占位符 | |
... | 与占位符相对应的变量名 | |
返回值 | 成功 | 读取数据赋值给变量个数 |
str 为空字符串时 | 返回 -1 | |
备注 | 当匹配到与对应占位符格式不一致时结束 |
说明:
占位符
到空格或\t或类型不同结束本个占位符的匹配
%*s 或 %d 跳过该类型的数据
%[width]s 读指定宽度的数据
%[a-z] 匹配 a 到 z 中任意字符
%[aBc] 匹配 a 、 B 、 c 中的一员,贪婪性
%[^a] 匹配非 a 的任意字符,贪婪性
%[^a-z] 表示读取除 a-z 以外的字符
demo:
sprintf()用法:
demo1() 格式化字符串 demo2() 接拼字符串 demo3() 数字转换成字符串格式
#include <stdio.h>
void demo1()
{
char buf[128] = {0};
sprintf(buf, "hallo %s", "world!");
printf("buf1 = %s\n", buf);
}
void demo2()
{
char *str1 = "hallo";
char *str2 = "world!";
char buf[128] = {0};
sprintf(buf, "%s %s", str1, str2);
printf("buf2 = %s\n", buf);
}
void demo3()
{
int num = 123;
char buf[128] = {0};
sprintf(buf, "%d", num);
printf("buf3 = %s\n", buf);
}
int main()
{
demo1();
demo2();
demo3();
return 0;
}
运行结果:
sscanf()用法:
demo1() 跳过该类型的数据 demo2()读指定宽度的数据 demo3()匹配 a 到 z 中任意字符
demo4()匹配 a 、B 、c 中的一员,贪婪性 demo5()匹配非 a 的任意字符,贪婪性
demo6()表示读取除 a-z 以外的字符
#include <stdio.h>
void demo1() //%*s 或 %d 跳过该类型的数据
{
char *str = "Ab12 cd";
char buf[128] = {0};
sscanf(str, "%*s%s", buf);
printf("%s\n", buf); // %s到空格止 buf = cd
}
void demo2() //%[width]s 读指定宽度的数据
{
char *str = "hallo world!";
char buf[128] = {0};
sscanf(str, "%8s", buf);
printf("%s\n", buf); //到空格止 buf = hallo
}
void demo3() //%[a-z] 匹配 a 到 z 中任意字符
{
char *str = "ab12cD!";
char buf[128] = {0};
sscanf(str, "%[a-z]", buf);
printf("%s\n", buf); // 1 非 a-z buf = ab
}
void demo4() //%[aBc] 匹配 a 、 B 、 c 中的一员,贪婪性
{
char *str = "aB12c";
char buf[128] = {0};
sscanf(str, "%[aBc]", buf);
printf("%s\n", buf); // 1 非 aBc buf = aB
}
void demo5() //%[^a] 匹配非 a 的任意字符,贪婪性
{
char *str = "123ooo";
char buf[128] = {0};
sscanf(str, "%[^o]", buf);
printf("%s\n", buf); //匹配非o字符串 buf = 123
}
void demo6() //%[^a-z] 表示读取除 a-z 以外的字符
{
char *str = "123aBc";
char buf[128] = {0};
sscanf(str, "%[^a-z]", buf);
printf("%s\n", buf); // 匹配非a-z字符串 buf = 123
}
int main()
{
demo1();
demo2();
demo3();
demo4();
demo5();
demo6();
return 0;
}
运行结果: