谭浩强c语言程序设计 第十章 对文件的输入输出

第十章 对文件的输入输出

文章目录

例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*指针用于通过标准库函数对文件进行操作,如读取、写入等。

通过文件指针访问文件的好处

  • 文件指针使文件操作更加抽象化,用户无需关心底层的操作系统细节。
  • 文件指针提供了缓存功能,优化了文件的读写操作。
  • 可以使用标准库函数,如fopenfclosefreadfwrite等,简化了文件操作。
#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;
}

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值