第十章 对文件的输入输出
文章目录
- 第十章 对文件的输入输出
- 例10.1 从键盘输入一些字符,并逐个把它们送到磁盘上去,直到用户输入一个“#”为止
- 例10.2 将一个磁盘文件中的信息复制到另一个磁盘文件中。今要求将上例建立的file1.dat文件中的内容复制到另一个磁盘文件file2.dat中
- 例10.3 从键盘读入若干个字符串,对它们按字母大小的顺序排序,然后把排好序的字符串送到磁盘文件中保存。
- 例10.4 从键盘输入10个学生的有关数据,然后把它们转存到磁盘文件上去
- 例10.5 有一个磁盘文件,内有一些信息。要求第一次将它的内容显示在屏幕上,第2次把它复制到另一个文件中。
- 例10.6 在磁盘文件上存有10个学生的数据,要求将第1,3,5,7,9个学生数据输入计算机,并在屏幕上显示出来
- 习题
- 1.什么是文件型指针?通过文件指针访问文件有什么好处?
- 2.对文件的打开与关闭的含义是什么?为什么要打开和关闭文件?
- 3.从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件test中保存,输入的字符串以!结束
- 4.有两个磁盘文件A和B,各存放一行字母,今要求把这两个文件中的信息合并(按字母顺序),输出到一个新文件c中去。
- 5.有五个学生,每个学生有三门课程的成绩,从键盘输入学生数据(包括学号,姓名,3门课程成绩),计算出平均成绩,将原有的数据和计算出的平均分数存放在磁盘文件stud中。
- 6.将第五题stud文件中的学生数据,按平均分进行排序处理,将已排序的学生数据存入一个新文件stu_sort中
- 7.将第六题已排序的学生成绩文件进行插入处理。插入一个学生的三门课程成绩,程序先计算新插入学生的平均成绩,然后将它按成绩高低顺序插入,插入后建立一个新文件。
- 8.将第七题结果仍存入原有的stu_sort文件而不另建立新文件
- 9.有一磁盘文件employee,内存放职工的数据。每个职工的数据包括职工姓名、职工号、性别、年龄、住址、工资、健康状况、文化程度。今要求将职工名、工资的信息单独抽出来另建一个简明的职工工资文件。
- 10.从第九题的“职工工资文件”中删去一个职工的数据,再存回原文件
- 11.从键盘输入若干行字符(每行长度不等),输入后把它们存储到一磁盘文件中。再从该文件中读入这些数据,将其中小写字母转换成大写字母后在显示屏上输出。
例10.1 从键盘输入一些字符,并逐个把它们送到磁盘上去,直到用户输入一个“#”为止
#include<stdio.h>
#include<stdlib.h>
int main(){
FILE *fp;
char ch,filename[10];
printf("请输入所用文件名:");
scanf("%s",filename);
getchar();
if((fp=fopen(filename,"w"))==NULL){
printf("cannot open file\n");
exit(0);
}
printf("请输入一个准备存储到磁盘的字符串(以#结束):");
ch=getchar();
while(ch!='#'){
fputc(ch,fp);
putchar(ch);
ch=getchar();
}
fclose(fp);
putchar(10);
return 0;
}
例10.2 将一个磁盘文件中的信息复制到另一个磁盘文件中。今要求将上例建立的file1.dat文件中的内容复制到另一个磁盘文件file2.dat中
/*输入一行字符,按照降序排序并输出*/
#include<stdio.h>
#include<stdlib.h>
int main(){
FILE *in,*out; //定义指向FIEL类型文件的指针变量
char ch,infile[10],outfile[10]; //定义两个字符数组,分别存放两个数据文件名
printf("输入读入文件的名字:");
scanf("%s",infile); //输入一个输入文件的名字
printf("输入输出文件的名字:");
scanf("%s",outfile); //输入一个输出文件的名字
if((in=fopen(infile,"r"))==NULL){ //打开输入文件
printf("无法打开此文件\n");
exit(0);
}
if((out=fopen(outfile,"w"))==NULL){ //打开输出文件
printf("无法打开此文件\n");
exit(0);
}
ch=fgetc(in); //从输入文件读入一个字符,赋给变量ch
while(!(feof(in))){ //如果未遇到输入文件的结束标志
fputc(ch,out); //将ch写到输出文件
putchar(ch); //将ch显示到屏幕上
ch=fgetc(in); //再从输入文件读入一个字符,赋给变量ch
}
putchar(10); //显示完全部字符后换行
fclose(in); //关闭输入文件
fclose(out); //关闭输出文件
return 0;
}
例10.3 从键盘读入若干个字符串,对它们按字母大小的顺序排序,然后把排好序的字符串送到磁盘文件中保存。
/*输入一行字符,按照降序排序并输出*/
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(){
FILE *fp; //定义指向FIEL类型文件的指针变量
char str[3][10],temp[10];
int i,j,k,n=3;
printf("Enter string:\n");
for(i=0;i<n;i++)
gets(str[i]);
for(i=0;i<n-1;i++){
k=i;
for(j=i+1;j<n;j++)
if(strcmp(str[k],str[j])>0) k=j;
if(k!=i){
strcpy(temp,str[i]);
strcpy(str[i],str[k]);
strcpy(str[k],temp);
}
}
if((fp=fopen("1.txt","w"))==NULL){
printf("无法打开文件");
exit(0);
}
for(i=0;i<n;i++){
fputs(str[i],fp);
fputs("\n",fp);
printf("%s\n",str[i]);
}
return 0;
}
例10.4 从键盘输入10个学生的有关数据,然后把它们转存到磁盘文件上去
定义一个又10个元素的结构体数组,用来存放10个学生的数据。从main函数输入10个学生的数据。用save函数实现向磁盘输出学生数据。用fwrite函数一次输出一个学生的数据
/*输入一行字符,按照降序排序并输出*/
#include<stdio.h>
#define size 10
struct student{
char name[10];
int num;
int age;
char addr[15];
}stu[size];
void save(){
FILE *fp;
int i;
if((fp=fopen("1.txt","wb"))==NULL){
printf("无法打开文件!\n");
return ;
}
for(i=0;i<size;i++)
if(fwrite(&stu[i],sizeof(struct student),1,fp)!=1)
printf("文件输入错误!\n");
fclose(fp);
}
int main(){
int i;
printf("输入字符串\n");
for(i=0;i<size;i++)
scanf("%s%d%d%s",stu[i].name,&stu[i].num,&stu[i].age,stu[i].addr);
save();
return 0;
}
例10.5 有一个磁盘文件,内有一些信息。要求第一次将它的内容显示在屏幕上,第2次把它复制到另一个文件中。
/*输入一行字符,按照降序排序并输出*/
#include<stdio.h>
int main(){
FILE *fp1,*fp2;char ch;
fp1=fopen("1.txt","r");
fp2=fopen("2.txt","w");
ch=getc(fp1); //从第一个文件读入第一个字符
while(!feof(fp1)) //当未读取文件尾标志
{
putchar(ch);
ch=getc(fp1);
}
putchar(10); //在屏幕执行换行
rewind(fp1); //使文件位置标记返回文件开头
ch=getc(fp1);
while(!feof(fp1)){
fputc(ch,fp2);
ch=fgetc(fp1);
}
fclose(fp1);
fclose(fp2);
return 0;
}
例10.6 在磁盘文件上存有10个学生的数据,要求将第1,3,5,7,9个学生数据输入计算机,并在屏幕上显示出来
/*输入一行字符,按照降序排序并输出*/
#include<stdio.h>
#include<stdlib.h>
struct student{
char name[10];
int num;
int age;
char addr[15];
}stu[10];
int main(){
int i;
FILE *fp;
if((fp=fopen("1.txt","rb"))==NULL){
printf("error!\n");
exit(0);
}
for(i=0;i<10;i+=2){
fseek(fp,i*sizeof(struct student),0); //移动文件位置标记
fread(&stu[i],sizeof(struct student),1,fp);//读一个数据块到结构体变量
printf("%-10s %4d %4d %-15s\n",stu[i].name,stu[i].num,stu[i].age,stu[i].addr);
}
fclose(fp);
return 0;
}
习题
1.什么是文件型指针?通过文件指针访问文件有什么好处?
**文件型指针(
FILE*
)**是用于指向文件对象的指针类型,在C语言中通过FILE
结构体来表示文件。FILE*
指针用于通过标准库函数对文件进行操作,如读取、写入等。
通过文件指针访问文件的好处:
- 文件指针使文件操作更加抽象化,用户无需关心底层的操作系统细节。
- 文件指针提供了缓存功能,优化了文件的读写操作。
- 可以使用标准库函数,如
fopen
、fclose
、fread
、fwrite
等,简化了文件操作。
#include<stdio.h>
FILE *fp;
fp = fopen("test.txt", "r");
fclose(fp);
2.对文件的打开与关闭的含义是什么?为什么要打开和关闭文件?
文件的打开:通过函数
fopen
打开文件,为读写操作做准备。它返回文件指针,用于后续操作。打开文件时可以指定模式,如读(“r”)、写(“w”)、追加(“a”)等。
文件的关闭:通过
fclose
函数关闭文件,释放与该文件相关的资源,如文件描述符。关闭文件可以确保数据写入硬盘并避免文件损坏。
为什么要打开和关闭文件:
- 打开文件是为了建立文件和程序之间的连接,使程序能够访问文件内容。
- 关闭文件是为了确保文件操作正确完成,防止内存泄漏或文件损坏。
3.从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件test中保存,输入的字符串以!结束
#include<stdio.h>
#include<ctype.h>
int main() {
FILE *fp;
char ch;
fp = fopen("test.txt", "w"); // 打开文件进行写操作
if(fp == NULL) {
printf("文件打开失败\n");
return 1;
}
printf("请输入字符串(以!结束):\n");
while((ch = getchar()) != '!') {
if(islower(ch)) { // 如果是小写字母,转换为大写
ch = toupper(ch);
}
fputc(ch, fp); // 将字符写入文件
}
fclose(fp); // 关闭文件
printf("字符串已保存至文件test.txt\n");
return 0;
}
4.有两个磁盘文件A和B,各存放一行字母,今要求把这两个文件中的信息合并(按字母顺序),输出到一个新文件c中去。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void merge(char* a, char* b, char* c) {
FILE *fa, *fb, *fc;
char ch;
fa = fopen(a, "r");
fb = fopen(b, "r");
fc = fopen(c, "w");
if (fa == NULL || fb == NULL || fc == NULL) {
printf("文件打开失败\n");
exit(1);
}
while ((ch = fgetc(fa)) != EOF) {
fputc(ch, fc);
}
while ((ch = fgetc(fb)) != EOF) {
fputc(ch, fc);
}
fclose(fa);
fclose(fb);
fclose(fc);
// 排序合并文件
FILE *fp = fopen(c, "r+");
char buffer[256], temp;
int n = 0;
while ((ch = fgetc(fp)) != EOF) {
buffer[n++] = ch;
}
buffer[n] = '\0';
fclose(fp);
// 排序
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (buffer[i] > buffer[j]) {
temp = buffer[i];
buffer[i] = buffer[j];
buffer[j] = temp;
}
}
}
// 将排序后的内容写回文件
fp = fopen(c, "w");
fputs(buffer, fp);
fclose(fp);
printf("文件合并成功并保存至%s\n", c);
}
int main() {
merge("A.txt", "B.txt", "C.txt");
return 0;
}
5.有五个学生,每个学生有三门课程的成绩,从键盘输入学生数据(包括学号,姓名,3门课程成绩),计算出平均成绩,将原有的数据和计算出的平均分数存放在磁盘文件stud中。
#include<stdio.h>
struct Student {
int id;
char name[20];
float score[3];
float avg;
};
int main() {
FILE *fp;
struct Student stu[5];
int i, j;
// 输入学生数据
for(i = 0; i < 5; i++) {
printf("请输入第%d个学生的学号和姓名: ", i + 1);
scanf("%d %s", &stu[i].id, stu[i].name);
printf("请输入三门课程的成绩: ");
stu[i].avg = 0;
for(j = 0; j < 3; j++) {
scanf("%f", &stu[i].score[j]);
stu[i].avg += stu[i].score[j];
}
stu[i].avg /= 3;
}
// 保存到文件
fp = fopen("stud.txt", "w");
if(fp == NULL) {
printf("文件打开失败\n");
return 1;
}
for(i = 0; i < 5; i++) {
fprintf(fp, "学号: %d, 姓名: %s, 三门课程成绩: %.2f, %.2f, %.2f, 平均分: %.2f\n",
stu[i].id, stu[i].name, stu[i].score[0], stu[i].score[1], stu[i].score[2], stu[i].avg);
}
fclose(fp); // 关闭文件
printf("学生数据已保存至stud.txt\n");
return 0;
}
6.将第五题stud文件中的学生数据,按平均分进行排序处理,将已排序的学生数据存入一个新文件stu_sort中
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Student {
int id;
char name[20];
float score[3];
float avg;
};
void sort_students(struct Student stu[], int n) {
struct Student temp;
for(int i = 0; i < n - 1; i++) {
for(int j = i + 1; j < n; j++) {
if(stu[i].avg < stu[j].avg) {
temp = stu[i];
stu[i] = stu[j];
stu[j] = temp;
}
}
}
}
int main() {
FILE *fp_in, *fp_out;
struct Student stu[5];
int i;
fp_in = fopen("stud.txt", "r");
if(fp_in == NULL) {
printf("无法打开文件 stud.txt\n");
return 1;
}
// 读取文件数据
for(i = 0; i < 5; i++) {
fscanf(fp_in, "学号: %d, 姓名: %s, 三门课程成绩: %f, %f, %f, 平均分: %f\n",
&stu[i].id, stu[i].name, &stu[i].score[0], &stu[i].score[1], &stu[i].score[2], &stu[i].avg);
}
fclose(fp_in);
// 排序
sort_students(stu, 5);
// 保存已排序的数据
fp_out = fopen("stu_sort.txt", "w");
if(fp_out == NULL) {
printf("无法创建文件 stu_sort.txt\n");
return 1;
}
for(i = 0; i < 5; i++) {
fprintf(fp_out, "学号: %d, 姓名: %s, 平均分: %.2f\n",
stu[i].id, stu[i].name, stu[i].avg);
}
fclose(fp_out);
printf("学生数据已排序并保存至 stu_sort.txt\n");
return 0;
}
7.将第六题已排序的学生成绩文件进行插入处理。插入一个学生的三门课程成绩,程序先计算新插入学生的平均成绩,然后将它按成绩高低顺序插入,插入后建立一个新文件。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Student {
int id;
char name[20];
float score[3];
float avg;
};
// 比较函数,用于排序
int compare(const void *a, const void *b) {
struct Student *stuA = (struct Student *)a;
struct Student *stuB = (struct Student *)b;
return (stuA->avg < stuB->avg) ? 1 : -1;
}
int main() {
FILE *fp;
struct Student stu[6]; // 5名已有学生 + 1名新插入的学生
int i, j;
// 读取stu_sort.txt中的数据
fp = fopen("stu_sort.txt", "r");
if(fp == NULL) {
printf("文件打开失败\n");
return 1;
}
for(i = 0; i < 5; i++) {
fscanf(fp, "学号: %d, 姓名: %s, 三门课程成绩: %f, %f, %f, 平均分: %f\n",
&stu[i].id, stu[i].name, &stu[i].score[0], &stu[i].score[1], &stu[i].score[2], &stu[i].avg);
}
fclose(fp);
// 输入新学生数据
printf("请输入新学生的学号、姓名和三门课程成绩:\n");
scanf("%d %s", &stu[5].id, stu[5].name);
stu[5].avg = 0;
for(j = 0; j < 3; j++) {
scanf("%f", &stu[5].score[j]);
stu[5].avg += stu[5].score[j];
}
stu[5].avg /= 3;
// 按平均分排序
qsort(stu, 6, sizeof(struct Student), compare);
// 将排序后的数据写入新文件stu_sort_new.txt
fp = fopen("stu_sort_new.txt", "w");
if(fp == NULL) {
printf("文件打开失败\n");
return 1;
}
for(i = 0; i < 6; i++) {
fprintf(fp, "学号: %d, 姓名: %s, 三门课程成绩: %.2f, %.2f, %.2f, 平均分: %.2f\n",
stu[i].id, stu[i].name, stu[i].score[0], stu[i].score[1], stu[i].score[2], stu[i].avg);
}
fclose(fp);
printf("新学生数据已插入并保存至stu_sort_new.txt\n");
return 0;
}
8.将第七题结果仍存入原有的stu_sort文件而不另建立新文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Student {
int id;
char name[20];
float score[3];
float avg;
};
// 比较函数,用于排序
int compare(const void *a, const void *b) {
struct Student *stuA = (struct Student *)a;
struct Student *stuB = (struct Student *)b;
return (stuA->avg < stuB->avg) ? 1 : -1;
}
int main() {
FILE *fp;
struct Student stu[6]; // 5名已有学生 + 1名新插入的学生
int i, j;
// 读取stu_sort.txt中的数据
fp = fopen("stu_sort.txt", "r");
if(fp == NULL) {
printf("文件打开失败\n");
return 1;
}
for(i = 0; i < 5; i++) {
fscanf(fp, "学号: %d, 姓名: %s, 三门课程成绩: %f, %f, %f, 平均分: %f\n",
&stu[i].id, stu[i].name, &stu[i].score[0], &stu[i].score[1], &stu[i].score[2], &stu[i].avg);
}
fclose(fp);
// 输入新学生数据
printf("请输入新学生的学号、姓名和三门课程成绩:\n");
scanf("%d %s", &stu[5].id, stu[5].name);
stu[5].avg = 0;
for(j = 0; j < 3; j++) {
scanf("%f", &stu[5].score[j]);
stu[5].avg += stu[5].score[j];
}
stu[5].avg /= 3;
// 按平均分排序
qsort(stu, 6, sizeof(struct Student), compare);
// 将排序后的数据写入原文件stu_sort.txt
fp = fopen("stu_sort.txt", "w");
if(fp == NULL) {
printf("文件打开失败\n");
return 1;
}
for(i = 0; i < 6; i++) {
fprintf(fp, "学号: %d, 姓名: %s, 三门课程成绩: %.2f, %.2f, %.2f, 平均分: %.2f\n",
stu[i].id, stu[i].name, stu[i].score[0], stu[i].score[1], stu[i].score[2], stu[i].avg);
}
fclose(fp);
printf("新学生数据已插入并保存至stu_sort.txt\n");
return 0;
}
9.有一磁盘文件employee,内存放职工的数据。每个职工的数据包括职工姓名、职工号、性别、年龄、住址、工资、健康状况、文化程度。今要求将职工名、工资的信息单独抽出来另建一个简明的职工工资文件。
#include<stdio.h>
#include<stdlib.h>
struct Employee {
char name[30];
int id;
char gender;
int age;
char address[50];
float salary;
char health[20];
char education[20];
};
int main() {
FILE *fp_in, *fp_out;
struct Employee emp;
// 打开输入文件employee
fp_in = fopen("employee.txt", "r");
if (fp_in == NULL) {
printf("文件打开失败\n");
return 1;
}
// 打开输出文件salary.txt
fp_out = fopen("salary.txt", "w");
if (fp_out == NULL) {
printf("文件创建失败\n");
return 1;
}
// 读取并写入职工名和工资信息
while (fscanf(fp_in, "%s %d %c %d %s %f %s %s", emp.name, &emp.id, &emp.gender, &emp.age, emp.address, &emp.salary, emp.health, emp.education) != EOF) {
fprintf(fp_out, "姓名: %s, 工资: %.2f\n", emp.name, emp.salary);
}
fclose(fp_in);
fclose(fp_out);
printf("职工工资文件已生成: salary.txt\n");
return 0;
}
10.从第九题的“职工工资文件”中删去一个职工的数据,再存回原文件
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Employee {
char name[30];
float salary;
};
int main() {
FILE *fp_in, *fp_out;
struct Employee emp;
char name_to_delete[30];
int found = 0;
// 打开工资文件
fp_in = fopen("salary.txt", "r");
if (fp_in == NULL) {
printf("文件打开失败\n");
return 1;
}
// 创建临时文件
fp_out = fopen("temp.txt", "w");
if (fp_out == NULL) {
printf("临时文件创建失败\n");
return 1;
}
// 输入要删除的职工姓名
printf("请输入要删除的职工姓名: ");
scanf("%s", name_to_delete);
// 逐行读取salary文件,将不匹配的记录写入临时文件
while (fscanf(fp_in, "姓名: %s, 工资: %f\n", emp.name, &emp.salary) != EOF) {
if (strcmp(emp.name, name_to_delete) != 0) {
fprintf(fp_out, "姓名: %s, 工资: %.2f\n", emp.name, emp.salary);
} else {
found = 1;
}
}
fclose(fp_in);
fclose(fp_out);
if (found) {
remove("salary.txt");
rename("temp.txt", "salary.txt");
printf("职工数据已删除\n");
} else {
remove("temp.txt");
printf("未找到要删除的职工\n");
}
return 0;
}
11.从键盘输入若干行字符(每行长度不等),输入后把它们存储到一磁盘文件中。再从该文件中读入这些数据,将其中小写字母转换成大写字母后在显示屏上输出。
#include<stdio.h>
#include<ctype.h>
int main() {
FILE *fp;
char ch;
// 打开文件存储输入数据
fp = fopen("input.txt", "w");
if(fp == NULL) {
printf("文件打开失败\n");
return 1;
}
printf("请输入若干行字符(输入#结束):\n");
// 将输入的数据存储到文件
while((ch = getchar()) != '#') {
fputc(ch, fp);
}
fclose(fp);
// 重新打开文件进行读取并处理
fp = fopen("input.txt", "r");
if(fp == NULL) {
printf("文件打开失败\n");
return 1;
}
printf("\n转换后的数据:\n");
// 将文件内容读取并转换为大写
while((ch = fgetc(fp)) != EOF) {
if(islower(ch)) {
ch = toupper(ch);
}
putchar(ch);
}
fclose(fp);
return 0;
}