1 文件操作
1.1 文件的输入输出
输出:使用printf()
和命令行重定向>
实现文件输出;
输入:使用scanf()
和命令行重定向<
实现文件输入。
#include <stdio.h>
//printf() 写入文件 ./a.out > hello.txt
//scanf() 从文件读 ./a.out < hello.txt
int main(){
char name[20];
scanf("%s",name);
printf("Hello %s!\n",name);
}
1.2 文件打开fopen()
和关闭fclose()
fopen()
函数原型:
FILE *fopen(char restrict *filename, char restrict *mode);
restrict C99标准才引进的,属于类型修饰符,表示修饰的这块内存空间只能被这个指针引用和修改,除此之外别无他法。
如果文件顺利打开,则返回值是指向这个文件流的文件指针,如果文件打开失败,返回NULL。
- filename:需要打开的文件
- mode:打开方式
mode的几种类型
1、r: 读
2、w: 写
3、a: 追加
4、+: 读或写,配合r、w、a使用
5、t: 文本文件
6、b: 二进制文件
注:a只能追加不能修改,w会把文件清空,r+读写方式可以修改文件原有内容。
fclose()
函数原型:
int flcose(FILE* stream);
stream: 函数指针
返回值:成功返回0,否则返回-1
1.3 文本读写fprintf()
和fscanf()
int fprintf(FILE *stream, char *format, argument...);
int fscanf(FILE *stream, char *format, argument... );
fprintf()/fscanf()
与printf()/scanf()
使用非常相似,区别在于fprintf()/fscanf()
第一个参数stream
是文件描述符。
#include <stdio.h>
int main(){
char name[20];
fscanf(stdin,"%s",name); //stdin标准读,从终端读
fprintf(stdout,"Hello %s!\n",name); //stdout标准写,向终端写
}
#include <stdio.h>
typedef struct{
char name[20];
int age;
float score;
} Stu;
int main(){
FILE* pfile = fopen("./student","r");
if(NULL == pfile){
printf("file is not exited!\n");
return 1;
}
int n;
fscanf(pfile,"%d",&n);
Stu s[n];
for(int i = 0;i < n;++i){
fscanf(pfile,"%s%d%f",&s[i].name,&s[i].age,&s[i].score);
}
fclose(pfile);
pfile = NULL;
FILE* pfile2 = fopen("./student2","w");
if(NULL == pfile2){
printf("file ./student2 is not exited!\n");
return 1;
}
for(int i = 0;i < n;++i){
fprintf(pfile2,"%s %d %.2f\n",s[i].name,s[i].age,s[i].score);
}
fclose(pfile2);
pfile2 = NULL;
}
- 学生信息管理: 采用
fprintf()
和fscanf()
实现增删查改
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct{
char name[20];
int age;
float score;
} Stu;
bool Load(const char* path,Stu* s,int* n){
FILE* file = fopen(path,"r");
if(NULL == file){
printf("file is not exited!\n");
return false;
}
int m;
fscanf(file,"%d",&m);
*n = m;
for(int i = 0;i < m;++i){
fscanf(file,"%s%d%f",&s[i].name,&s[i].age,&s[i].score);
}
fclose(file);
file = NULL;
return true;
}
void ShowStudents(Stu* s,int n){
for(int i = 0;i < n;++i){
printf("%s %d %f\n",s[i].name,s[i].age,s[i].score);
}
}
void SaveStudents(const char* path,Stu* s,int* n){
FILE* file = fopen(path,"w");
if(NULL == file){
printf("file is not exited!\n");
return;
}
fprintf(file,"%d\n",*n);
for(int i = 0;i < *n;++i){
fprintf(file,"%s %d %f\n",s[i].name,s[i].age,s[i].score);
}
fclose(file);
file = NULL;
}
void Register(const char* path,Stu* s,int* n){
int before = *n;
printf("请输入录入学生个数:");
int append_num;
scanf("%d",&append_num);
*n += append_num;
printf("请依次输入学生姓名,年龄和成绩:\n");
for(int i = before;i < *n;++i){
scanf("%s%d%f",&s[i].name,&s[i].age,&s[i].score);
}
SaveStudents(path,s,n);
}
int cmp(const void* a,const void* b){
return ((Stu*)(a))->score < ((Stu*)(b))->score?1:-1;
}
void SortStudents(Stu* s,int n){
qsort(s,n,sizeof(Stu),cmp);
ShowStudents(s,n);
}
void SearchStudents(Stu* s,int n){
printf("请输入学生姓名:");
char name[20];
scanf("%s",name);
bool found = false;
for(int i = 0;i < n;++i){
if(strcmp(name,s[i].name) == 0){
found = true;
printf("查询结果:%s %d %f\n",s[i].name,s[i].age,s[i].score);
}
}
if(!found){
printf("查无此人!\n");
}
}
void DeleteStudents(const char* path,Stu* s,int* n){
printf("请输入学生姓名:");
char name[20];
scanf("%s",name);
bool found = false;
for(int i = 0;i < *n;++i){
if(strcmp(name,s[i].name) == 0){
found = true;
for(int j = i+1;j < *n;++j){
s[i++] = s[j];
}
*n -= 1;
printf("删除成功!\n");
break;
}
}
if(!found){
printf("查无此人!\n");
return;
}
SaveStudents(path,s,n);
}
void ModifyStudents(const void* path,Stu* s,int n){
printf("请输入学生姓名:");
char name[20];
scanf("%s",name);
bool found = false;
for(int i = 0;i < n;++i){
if(strcmp(name,s[i].name) == 0){
found = true;
printf("请依次输入修改后的信息:姓名 年龄 成绩\n");
scanf("%s%d%f",&s[i].name,&s[i].age,&s[i].score);
break;
}
}
if(!found){
printf("查无此人!\n");
return;
}
SaveStudents(path,s,&n);
}
int main(){
const char* data = "./student.txt";
Stu s[10];
int n;
if(Load(data,s,&n)){
printf("已经加载%d名学生信息\n",n);
}
while(true){
printf("功能列表:\n");
printf("1.查看所有学生信息\n");
printf("2.录入学生信息\n");
printf("3.按成绩排序\n");
printf("4.查询学生信息\n");
printf("5.删除学生信息\n");
printf("6.修改学生信息 \n");
printf("0.退出\n");
int num;
scanf("%d",&num);
switch(num){
case 1:
ShowStudents(s,n);
break;
case 2:
Register(data,s,&n);
break;
case 3:
SortStudents(s,n);
break;
case 4:
SearchStudents(s,n);
break;
case 5:
DeleteStudents(data,s,&n);
break;
case 6:
ModifyStudents(data,s,n);
break;
case 0:
return 0;
}
}
}
1.4 二进制读和写:fread()和fwrite()
size_t fread(void *ptr, size_t size, size_t count, FILE* stream);
size_t fwrite(void *ptr, size_t size, size_t count, FILE* stream);
ptr: 一个指针,在fread()
中是从文件里读入的数据存放的地址;在fwrite()
中是写入到文件里的数据存放的地址。
ptr |
指针,在fread() 中是从文件里读入的数据存放的地址;在fwrite() 中是写入到文件里的数据存放的地址 |
size |
每次要读写的字节数 |
count |
读写的次数 |
stream |
文件指针 |
- 返回值:成功读取/写入的字节数
- 实例:
fread()和fwrite()
实现文件读和写
#include <stdio.h>
#include <string.h>
int main(){
FILE* fp= fopen("./hello.txt","rw");
char str[] = "Hello World";
fwrite(str,sizeof(str),1,fp);
char str1[20];
fread(str1,sizeof(str1),1,fp);
printf("%s\n",str1);
}
- 学生信息管理: 采用
fread()和fwrite()
实现增删查改
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
typedef struct{
char name[20];
int age;
float score;
} Stu;
bool Load(const char* path,Stu* s,int* n){
FILE* file = fopen(path,"rb");
if(NULL == file){
printf("file is not exited!\n");
return false;
}
int m;
fread(&m,sizeof(m),1,file);
//fscanf(file,"%d",&m);
*n = m;
fread(s,sizeof(Stu),m,file);
/*
for(int i = 0;i < m;++i){
fscanf(file,"%s%d%f",&s[i].name,&s[i].age,&s[i].score);
}
*/
fclose(file);
file = NULL;
return true;
}
void ShowStudents(Stu* s,int n){
for(int i = 0;i < n;++i){
printf("%s %d %f\n",s[i].name,s[i].age,s[i].score);
}
}
void SaveStudents(const char* path,Stu* s,int n){
FILE* file = fopen(path,"wb");
if(NULL == file){
printf("file is not exited!\n");
return;
}
fwrite(&n,sizeof(n),1,file);
//fprintf(file,"%d\n",*n);
fwrite(s,sizeof(Stu),n,file);
/*
for(int i = 0;i < *n;++i){
fprintf(file,"%s %d %f\n",s[i].name,s[i].age,s[i].score);
}
*/
fclose(file);
file = NULL;
}
void Register(const char* path,Stu* s,int* n){
int before = *n;
printf("请输入录入学生个数:");
int append_num;
scanf("%d",&append_num);
*n += append_num;
printf("请依次输入学生姓名,年龄和成绩:\n");
for(int i = before;i < *n;++i){
scanf("%s%d%f",&s[i].name,&s[i].age,&s[i].score);
}
SaveStudents(path,s,*n);
}
int cmp(const void* a,const void* b){
return ((Stu*)(a))->score < ((Stu*)(b))->score?1:-1;
}
void SortStudents(Stu* s,int n){
qsort(s,n,sizeof(Stu),cmp);
ShowStudents(s,n);
}
void SearchStudents(Stu* s,int n){
printf("请输入学生姓名:");
char name[20];
scanf("%s",name);
bool found = false;
for(int i = 0;i < n;++i){
if(strcmp(name,s[i].name) == 0){
found = true;
printf("查询结果:%s %d %f\n",s[i].name,s[i].age,s[i].score);
}
}
if(!found){
printf("查无此人!\n");
}
}
void DeleteStudents(const char* path,Stu* s,int* n){
printf("请输入学生姓名:");
char name[20];
scanf("%s",name);
bool found = false;
for(int i = 0;i < *n;++i){
if(strcmp(name,s[i].name) == 0){
found = true;
for(int j = i+1;j < *n;++j){
s[i++] = s[j];
}
*n -= 1;
printf("删除成功!\n");
break;
}
}
if(!found){
printf("查无此人!\n");
return;
}
SaveStudents(path,s,*n);
}
void ModifyStudents(const void* path,Stu* s,int n){
printf("请输入学生姓名:");
char name[20];
scanf("%s",name);
bool found = false;
for(int i = 0;i < n;++i){
if(strcmp(name,s[i].name) == 0){
found = true;
printf("请依次输入修改后的信息:姓名 年龄 成绩\n");
scanf("%s%d%f",&s[i].name,&s[i].age,&s[i].score);
break;
}
}
if(!found){
printf("查无此人!\n");
return;
}
SaveStudents(path,s,n);
}
int main(){
const char* data = "./student2.dat";
Stu s[10];
int n;
if(Load(data,s,&n)){
printf("已经加载%d名学生信息\n",n);
}
while(true){
printf("功能列表:\n");
printf("1.查看所有学生信息\n");
printf("2.录入学生信息\n");
printf("3.按成绩排序\n");
printf("4.查询学生信息\n");
printf("5.删除学生信息\n");
printf("6.修改学生信息 \n");
printf("0.退出\n");
int num;
scanf("%d",&num);
switch(num){
case 1:
ShowStudents(s,n);
break;
case 2:
Register(data,s,&n);
break;
case 3:
SortStudents(s,n);
break;
case 4:
SearchStudents(s,n);
break;
case 5:
DeleteStudents(data,s,&n);
break;
case 6:
ModifyStudents(data,s,n);
break;
case 0:
return 0;
}
}
}
注:读取文件须为二进制文件.dat
1.5 文件定位:ftell()
和fseek()
// 获取位置
long ftell(FILE* stream);
// 设置位置
int fseek(FILE* stream,long offset,int whence);
stream |
文件指针 |
offset |
基于起始点的偏移量 |
whence |
起始点 |
whence的集中状态及含义:
whence |
数值 |
含义 |
SEEK_SET |
0 |
从头开始 |
SEEK_CUR |
1 |
从当前开始 |
SEEK_END |
2 |
从结束开始 |
- 返回值
ftell()返回基于文件开头的偏移字节数。
- 实例:计算文件大小
#include <stdio.h>
int main() {
FILE* fp = fopen("hello.txt","r");
if(fp) {
fseek(fp,0,SEEK_END);//设置指针为最后位置,便宜0字节
long size = ftell(fp); //ftell()返回基于文件开头的偏移字节数。
printf("大小为%ldB\n",size);
}
}
1.6 文件结尾判断feof()
int feof(FILE* stream);
- 参数
stream
文件指针
- 返回值
若指针指向文件结尾,返回一个真值,否则返回非真值。
1.7 返回开头rewind()
void rewind(FILE* stream);
#include <stdio.h>
int main() {
FILE* fp = fopen("hello.txt","r");
fseek(fp,0,SEEK_END);
long len = ftell(fp);
printf("%d\n",len);
rewind(fp);
len = ftell(fp);
printf("%d\n",len);
}
13
0
1.8 清空数据流
void fflush(FILE* stream);
fflush(fp); // 清空文件流