printf --- sprintf --- fprintf:
变参函数:参数形参中 有“...”, 最后一个固参通常是格式描述串(包含格式匹配符), 函数的参数个数、类型、顺序由这个固参决定。
printf("hello");
printf("%s", "hello");
printf("ret = %d+%d\n", 10, 5);
printf("%d = %d%c%d\n", 10+5, 10, '+', 5); --> 屏幕
char buf[1024]; //缓冲区
sprintf(buf, "%d = %d%c%d\n", 10+5, 10, '+', 5); --> buf 中
FILE * fp = fopen();
fprintf(fp, "%d = %d%c%d\n", 10+5, 10, '+', 5); --> fp 对应的文件中
scanf --- sscanf --- fscanf
scanf("%d", &m); 键盘 --> m
char str[] = "98";
sscanf(str, "%d", &m); str --> m
FILE * fp = fopen("r");
fscanf(fp, "%d", &m); fp指向的文件中 --> m
fprintf()函数:
写
int fprintf(FILE * stream, const char * format, ...);
fscanf()函数:
读
int fscanf(FILE * stream, const char * format, ...);
成功:正确匹配的个数。
失败: -1
1) 边界溢出。 存储读取的数据空间。在使用之前清空。 memset(buf,0,sizeof(buf));
2)fscanf函数,每次在调用时都会判断下一次调用是否匹配参数2, 如果不匹配提前结束读文件。(feof(fp) 为真)。
示例
void write_file()
{
FILE* fp = fopen("abc.c", "w");
if (!fp)
{
perror("fopen error");
return;
}
fprintf(fp, "%d%c%d=%d\n", 10, '*', 5, 10 * 5);
fclose(fp);
}
void read_file()
{
int a, b, c;
char ch;
FILE* fp = fopen("abc.c", "r");
if (!fp)
{
perror("fopen error");
return;
}
fscanf(fp, "%d%c%d=%d\n", &a, &ch, &b, &c);
printf("%d%c%d=%d\n", a, ch, b, c);
fclose(fp);
}
int main(void)
{
write_file();
read_file();
system("pause");
return EXIT_SUCCESS;
}
fgets和fscanf比较
示例
void write_file()
{
FILE* fp = fopen("test01.txt", "w");
if (!fp)
{
perror("fopen error");
return;
}
fprintf(fp, "%d\n", 10);
fprintf(fp, "%d\n", 6);
fprintf(fp, "%d\n", 8);
fclose(fp);
}
void read_file()
{
int a;
FILE* fp = fopen("test01.txt", "r");
if (!fp)
{
perror("fopen error");
return;
}
while (1)
{
fscanf(fp, "%d\n", &a);
printf("%d\n", a);
if (feof(fp))
{
break;
}
}
fclose(fp);
}
void read_file1()
{
char buf[1024];
FILE* fp = fopen("test01.txt", "r");
if (!fp)
{
perror("fopen error");
return;
}
while (1)
{
memset(buf, 0, 1024);
fgets(buf, 1024, fp);
printf("%s", buf);
if (feof(fp))
{
break;
}
}
fclose(fp);
}
int main(void)
{
write_file();
read_file1();
system("pause");
return EXIT_SUCCESS;
}
练习:文件版排序
生成随机数,写入文件。将文件内乱序随机数读出,排好序再写回文件。
示例
void write_random()
{
FILE* fp = fopen("test02.txt", "w");
if (!fp)
{
perror("fopen error");
return;
}
srand(time(NULL));
for (size_t i = 0; i < 10; i++)
{
fprintf(fp, "%d\n", rand() % 100);
}
fclose(fp);
}
void BubbleSort(int* src, int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - 1 - i; j++)
{
if (src[j] > src[j + 1])
{
int temp = src[j];
src[j] = src[j + 1];
src[j + 1] = temp;
}
}
}
}
void read_random()
{
int arr[10];
int i = 0;
FILE* fp = fopen("test02.txt", "r");
if (!fp)
{
perror("fopen error");
return;
}
while (1)
{
fscanf(fp, "%d\n", &arr[i]);
i++;
if (feof(fp))
{
break;
}
}
for (size_t i = 0; i < 10; i++)
{
printf("%d\n", arr[i]);
}
BubbleSort(arr, 10);
fclose(fp);
FILE* fp1 = fopen("test02.txt", "w");
if (!fp1)
{
perror("fopen error");
return;
}
srand(time(NULL));
for (size_t i = 0; i < 10; i++)
{
fprintf(fp1, "%d\n", arr[i]);
}
fclose(fp1);
}
int main(void)
{
read_random();
system("pause");
return EXIT_SUCCESS;
}
fwrite和fread函数
fgetc --- fputc
fgets --- fputs
fprintf -- fscanf 默认处理文本文件。
fwrite()函数: 既可处理文本文件也可处理二进制文件。
写出数据到文件中。
stu_t stu[4] = { ...... };
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参1:待写出的数据的地址
参2:待写出数据的大小
参3:写出的个数 -- 参2 x 参3 = 写出数据的总大小。
参4:文件
返回值: 成功:永远是 参3 的值。 --- 通常将参2 传 1. 将参3传实际写出字节数。
失败:0
示例
typedef struct student
{
int age
char name[10]
int num
} stu
int main(void)
{
stu stu1[4] =
{
18,"afei",10,
20,"andyi",20,
17,"nvnv",15,
15,"wang",14,
}
FILE* fp = fopen("test03.txt", "w")
if(!fp)
{
perror("fopen error")
return -1
}
int ret = fwrite(&stu1[0], 1, sizeof(stu)*4, fp)
if (ret == 0)
{
perror("fwrite error")
return -1
}
printf("%d\n", ret)
fclose(fp)
system("pause")
return EXIT_SUCCESS
}
fread()函数:
从文件fp中读出数据。
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参1:读取到的数据存储的位置
参2:一次读取的字节数
参3:读取的次数 -- 参2 x 参3 = 读出数据的总大小
参4:文件
返回值: 成功:参数3. --- 通常将参2 传 1. 将参3传欲读出的字节数。
0:读失败 -- 到达文件结尾 -- feof(fp)为真。
示例
typedef struct student
{
int age;
char name[10];
int num;
} stu;
void write_struct()
{
stu stu1[4] =
{
18,"afei",10,
20,"andyi",20,
17,"nvnv",15,
15,"wang",14,
};
FILE* fp = fopen("test04.txt", "w");
if (!fp)
{
perror("fopen error");
return -1;
}
int ret = fwrite(&stu1[0], 1, sizeof(stu) * 4, fp);
if (ret == 0)
{
perror("fwrite error");
return -1;
}
fclose(fp);
}
void read_file01()
{
FILE* fp = fopen("test04.txt", "r");
if (!fp)
{
perror("fopen error");
return -1;
}
stu buf;
int ret = fread(&buf, sizeof(stu), 1, fp);
printf("ret =%d\n", ret);
printf("age = %d,name =%s,num =%d\n", buf.age, buf.name, buf.num);
fclose(fp);
}
void read_file()
{
FILE* fp = fopen("test04.txt", "r");
if (!fp)
{
perror("fopen error");
return -1;
}
stu buf[10];
int i = 0;
while (1)
{
int ret = fread(&buf[i], sizeof(stu), 1, fp);
if (ret ==0)
{
break;
}
printf("age = %d,name =%s,num =%d\n", buf[i].age, buf[i].name, buf[i].num);
i++;
}
fclose(fp);
}
int main(void)
{
write_struct();
read_file();
system("pause");
return EXIT_SUCCESS;
}
练习:大文件拷贝
已知一个任意类型的文件,对该文件复制,产生一个相同的新文件。
1. 打开两个文件, 一个“r”, 另一“w”
2. 从r中 fread , fwrite到 w 文件中。
3. 判断到达文件结尾 终止。
4. 关闭。
注意: 在windows下,打开二进制文件(mp3、mp4、avi、jpg...)时需要使用“b”。如:“rb”、“wb”
示例
void myfile_cp()
{
char buf[128] = { 0 }
int ret = 0
FILE* rfp = fopen("D:/BaiduNetdiskWorkspace/研究生/课程/编程基础/01-C语言基础/C语言基础-第11天(文件操作下)/1-教学资料/10-午后回顾.avi", "rb")
if (rfp == NULL)
{
perror("rfp fopen error")
return
}
FILE* wfp = fopen("test05.avi", "wb")
if (wfp == NULL)
{
perror("wfp fopen error")
return
}
while (1)
{
memset(buf, 0, sizeof(buf))
ret= fread(buf, 1, sizeof(buf), rfp)
if (ret == 0)
{
break
}
fwrite(buf, 1, ret, wfp)
}
fclose(rfp)
fclose(wfp)
}
int main(void)
{
myfile_cp()
system("pause")
return EXIT_SUCCESS
}
随机位置 读:fseek;ftell;rewind
文件读写指针。在一个文件内只有一个。
fseek():
int fseek(FILE *stream, long offset, int whence);
参1:文件
参2:偏移量(矢量: + 向后, - 向前)
参3: SEEK_SET:文件开头位置
SEEK_CUR:当前位置
SEEK_END:文件结尾位置
返回值: 成功:0, 失败: -1
ftell():
获取文件读写指针位置。
long ftell(FILE *stream);
返回:从文件当前读写位置到起始位置的偏移量。
借助 ftell(fp) + fseek(fp, 0, SEEK_END); 来获取文件大小。
rewind():
回卷文件读写指针。 将读写指针移动到起始位置。
void rewind(FILE *stream);
示例
typedef struct student
{
int age;
char name[10];
int num;
} stu;
int main(void)
{
stu stu1[4] =
{
18,"afei",10,
20,"andyi",20,
17,"nvnv",15,
15,"wang",14,
};
stu s1;
FILE* fp = fopen("test06.txt", "wb+");
if (!fp)
{
perror("fopen error");
return -1;
}
fwrite(&stu1[0], 1,sizeof(stu1), fp);
fseek(fp, sizeof(stu), SEEK_SET);
fread(&s1, 1, sizeof(s1), fp);
printf("age =%d, name =%s, num =%d", s1.age, s1.name, s1.num);
int len = ftell(fp);
printf("len =%d\n", len);
rewind(fp);
fread(&s1, 1, sizeof(s1), fp);
printf("age =%d, name =%s, num =%d", s1.age, s1.name, s1.num);
fseek(fp, 0, SEEK_END);
len = ftell(fp);
printf("文件大小为:%d\n", len);
fclose(fp);
system("pause");
return EXIT_SUCCESS;
}
Linux和windows文件区别:
1)对于二进制文件操作, Windows 使用“b”, Linux下二进制和文本没区别。
2)windows下,回车 \r, 换行 \n。 \r\n , Linux下 回车换行\n
3) 对文件指针,先写后读。windows和Linux效果一致。
先读后写。Linux无需修改。windows下需要在写操作之前添加 fseek(fp, 0, SEEK_CUR); 来获取文件读写指针,使之生效。
获取文件状态:stat函数
打开文件,对于系统而言,系统资源消耗较大。
int stat(const char *path, struct stat *buf);
参1: 访问文件的路径
参2: 文件属性结构体
返回值: 成功: 0, 失败: -1;
示例
int main(void)
{
struct stat buf;//需要<sys/types.h> <sys/stat.h>头文件
int ret = stat("test05.txt", &buf);//传出参数:在函数调用结束时,充当函数返回值
printf("文件大小:%d\n", buf.st_size);//不打开文件获取文件大小
system("pause");
return EXIT_SUCCESS;
}
删除、重命名文件:remove函数;rename函数
int remove(const char *pathname); 删除文件。
int rename(const char *oldpath, const char *newpath); 重名文件
缓冲区刷新:fflush函数

标准输出-- stdout -- 标准输出缓冲区。 写给屏幕的数据,都是先存缓冲区中,由缓冲区一次性刷新到物理设备(屏幕)
标准输入 -- stdin -- 标准输入缓冲区。 从键盘读取的数据,直接读到 缓冲区中, 由缓冲区给程序提供数据。
预读入、缓输出。
行缓冲:printf(); 遇到\n就会将缓冲区中的数据刷新到物理设备上。
全缓冲:文件。 缓冲区存满, 数据刷新到物理设备上。
无缓冲:perror。 缓冲区中只要有数据,就立即刷新到物理设备。
文件关闭时, 缓冲区会被自动刷新。 隐式回收:关闭文件、刷新缓冲区、释放malloc
手动刷新缓冲区: 实时刷新。
int fflush(FILE *stream);
成功:0
失败:-1
示例
int main(void)
{
FILE* fp = fopen("test08.txt", "w+");
if (!fp)
{
perror("fopen error");
return;
}
char m = 0;
while (1)
{
scanf("%c", &m);
if (m == ':')
{
break;
}
fflush(fp);
fputc(m, fp);
}
fclose(fp);
system("pause");
return EXIT_SUCCESS;
}