谭浩强【C语言程序设计】第十章习题详解

2024-02-18 23:12

本文主要是介绍谭浩强【C语言程序设计】第十章习题详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


1.什么是文件型指针?通过文件指针访问文件有什么好处?

🌵文件型指针是一种特殊类型的指针,用于访问和操作文件。

🌵文件型指针的主要特点和优点:

  • 文件型指针可以标识打开的文件,用于进行文件的读写操作。它存储了文件在内存中的位置信息。

  • 通过文件型指针可以方便地对文件进行读写操作,无需每次都指定文件名和路径。只需要使用指针就可以访问文件。

  • 文件型指针支持随机访问文件,可以直接跳转到文件任意位置进行读写。而不像流式访问只能顺序读写。

  • 文件型指针可以同时打开多个文件,通过不同的指针分别进行文件的读写操作管理。

  • 使用文件指针可以方便实现文件的移动、复制、删除等高级文件操作。

  • 与直接使用文件名相比,文件指针访问文件性能更高,不需要每次进行路径解析等开销。

  • 文件指针作为一个值类型的数据,更易于函数的参数传递和返回,实现对文件的抽象访问。

所以总的来说,通过文件型指针可以更高效地管理和操作文件,实现文件的随机访问,并支持对多个文件的同时操作,相比直接使用文件名更加灵活方便。这是使用文件指针的主要优点。

2.对文件的打开与关闭的含义是什么?为什么要打开和关闭文件?

🌵文件打开和关闭的含义如下:

  • 打开文件:

文件打开指的是在程序中建立一个与某个文件对应的文件对象,以便能够对该文件进行读写操作。

打开文件需要指定文件的路径和名称,以及打开文件的模式,如只读、只写或读写等。打开文件后,程序就可以通过文件对象来读取文件内容或写入文件内容了。

  • 关闭文件:

关闭文件是释放与该文件对应的文件对象。当文件使用完毕后,需要关闭文件,以释放系统资源。

比如在打开一个文本文件进行读写操作后,使用完毕后需要关闭该文件,以便系统可以释放与该文件相关联的内存和文件句柄等资源,以便为其他程序提供资源。

🌵为什么要打开和关闭文件:

  • 打开文件是为了能够对文件进行读写操作。如果不打开文件,程序无法访问文件内容。

  • 关闭文件是为了释放与文件相关的系统资源。如果不关闭打开的文件,文件句柄和内存将一直被占用,影响其他程序的运行。

  • 正常的文件操作流程是:打开文件->进行读写->关闭文件。这可以保证文件资源的有效使用和释放。

所以总的来说,打开文件是为了读写文件,关闭文件是为了释放系统资源,两者配合使用可以保证文件操作的正常进行。

3.从键盘输入一个字符串,将其中的小写字母全部转换成大写字母,然后输出到一个磁盘文件test中保存,输入的字符串以“!”结束。

#include <stdio.h>int main()
{FILE* fp = NULL;fp = fopen("test.txt", "w");if (fp == NULL){printf("Open File Error.\n");return -1;}char ch;while ((ch = getchar()) != '!' && ch != EOF){if (ch >= 'a' && ch <= 'z')ch -= 32;fputc(ch, fp);}fclose(fp);return 0;
}

4.有两个磁盘文件A 和B,各存放一行字母,今要求把这两个文件中的信息合并(按字母顺序排列),输出到一个新文件C中去。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>//打开文件
void OpenFile(FILE** fpa, FILE** fpb, FILE** fpc)
{*fpa = fopen("A.txt", "r");if (NULL == fpa){printf("Open A.txt File Error.\n");exit(1);}*fpb = fopen("B.txt", "r");if (NULL == fpb){printf("Open B.txt File Error.\n");exit(1);}*fpc = fopen("C.txt", "w");if (NULL == fpc){printf("Open C.txt File Error.\n");exit(1);}
}//关闭文件
void CloseFile(FILE* fpa, FILE* fpb, FILE* fpc)
{fclose(fpa);fclose(fpb);fclose(fpc);
}//将A文件和B文件中的字符串读到缓冲区中
void GetBufferChar(FILE* fpa, FILE* fpb, char* buffer)
{fgets(buffer, 1024, fpa);//从A文件读入数据int len = strlen(buffer);fgets(buffer + len, 1024 - len, fpb);//从B文件读入数据
}//排序
void SortBufferChar(char* buffer)
{//冒泡排序int n = strlen(buffer);for (int i = 0; i < n - 1; i++){for (int j = 0; j < n - i - 1; j++){if (buffer[j] > buffer[j + 1]){char tmp = buffer[j];buffer[j] = buffer[j + 1];buffer[j + 1] = tmp;}}}
}//将排好序的字符串写入C文件
void SaveFile(FILE* fpc, char* buffer)
{fputs(buffer, fpc);
}int main()
{FILE* fpa, * fpb, * fpc;OpenFile(&fpa, &fpb, &fpc);//打开文件char buffer[1024] = { 0 };GetBufferChar(fpa, fpb, buffer);//将A文件和B文件中的字符串读到缓冲区中SortBufferChar(buffer);//排序SaveFile(fpc, buffer);//将排好序的字符串写入C文件CloseFile(fpa, fpb, fpc);//关闭文件return 0;
}

5.有5个学生,每个学生有3门课程的成绩,从键盘输入学生数据(包括学号,姓名,3门课程成绩),计算出平均成绩,将原有数据和计算出的平均分数存放在磁盘文件 stud中。

#include <stdio.h>typedef struct student
{int num;		//学号char name[32];  //姓名int score[3];   //成绩float avg;      //平均分
}student;int main()
{student stu[5];//创建5个学生的结构体for (int i = 0; i < 5; i++){printf("num name score1 score2 score3\n");scanf("%d %s %d %d %d", &stu[i].num, stu[i].name, &stu[i].score[0], &stu[i].score[1], &stu[i].score[2]);//计算平均分stu[i].avg = (stu[i].score[0] + stu[i].score[1] + stu[i].score[2]) / 3.0;}FILE* fp = fopen("stud.txt", "w");if (NULL == fp){printf("打开文件失败\n");return -1;}//将数据写入文件for (int i = 0; i < 5; i++){fprintf(fp, "%3d %10s %3d %3d %3d %3.2f\n", stu[i].num, stu[i].name, stu[i].score[0], stu[i].score[1], stu[i].score[2], stu[i].avg);}fclose(fp);return 0;
}

6.将第5题 stud文件中的学生数据,按平均分进行排序处理,将已排序的学生数据存入一个新文件stu_sort中。

#include <stdio.h>
#include <string.h>typedef struct student
{int num;		//学号char name[32];  //姓名int score[3];   //成绩float avg;      //平均分
}student;void ReadData(student* stu)
{FILE* fp = fopen("stud.txt", "r");if (NULL == fp){printf("打开文件失败\n");return -1;}//读入数据for (int i = 0; i < 5; i++){fscanf(fp,"%d %s %d %d %d %f\n", &stu[i].num, stu[i].name,&stu[i].score[0], &stu[i].score[1], &stu[i].score[2], &stu[i].avg);}fclose(fp);
}void SortData(student* stu, int n)
{student tmp_stu;int size = sizeof(tmp_stu);for (int i = 0; i < n - 1; i++){for (int j = 0; j < n - 1 - i; j++){if (stu[j].avg < stu[j + i].avg){//交换结构体数据memcpy(&tmp_stu, &stu[j], size);memcpy(&stu[j], &stu[j + 1], size);memcpy(&stu[j + 1], &tmp_stu, size);}}}
}void WriteData(student* stu)
{FILE* fp = fopen("stu_sort.txt", "w");if (NULL == fp){printf("打开文件失败\n");return -1;}//写入数据for (int i = 0; i < 5; i++){fprintf(fp, "%3d %10s %3d %3d %3d %3.2f\n", stu[i].num, stu[i].name,stu[i].score[0], stu[i].score[1], stu[i].score[2], stu[i].avg);}fclose(fp);
}int main()
{student stu[5];ReadData(stu);SortData(stu, 5);WriteData(stu);return 0;
}

7.将第6题已排序的学生成绩文件进行插入处理。插入一个学生的3门课程成绩,程序先计算新插入学生的平均成绩,然后将它按成绩高低顺序插入,插入后建立一个新文件。

#include <stdio.h>
#include <string.h>typedef struct student
{int num;		//学号char name[32];  //姓名int score[3];   //成绩float avg;      //平均分
}Student;void TnputData(Student* stu)
{printf("请输入新学生的成绩信息:>\n");printf("num  name score1  score2  score3\n");scanf("%d %s %d %d %d", &(stu->num), stu->name,&(stu->score[0]), &(stu->score[1]), &(stu->score[2]));stu->avg = (stu->score[0] + stu->score[1] + stu->score[2]) / 3.0;}void ReadData(Student* stu)
{FILE* fp = fopen("stu_sort.txt", "r");if (NULL == fp){printf("打开文件失败\n");return -1;}//读入数据for (int i = 0; i < 5; i++){fscanf(fp, "%d %s %d %d %d %f\n", &stu[i].num, stu[i].name,&stu[i].score[0], &stu[i].score[1], &stu[i].score[2], &stu[i].avg);}fclose(fp);
}void InsertData(Student* old_stu, Student* new_stu, int n)
{int pos = 0;while (pos < n){if (new_stu->avg > old_stu[pos].avg){break;}pos++;}//移动数据for (int i = n; i > pos; i--){memcpy(&old_stu[i], &old_stu[i - 1], sizeof(Student));}//在pos位置把新学生的数据插入memcpy(&old_stu[pos], new_stu, sizeof(Student));
}void WriteData(Student* stu)
{FILE* fp = fopen("stu_new_sort.txt", "w");if (NULL == fp){printf("打开文件失败\n");return -1;}//写入数据for (int i = 0; i < 6; i++){fprintf(fp, "%3d %10s %3d %3d %3d %3.2f\n", stu[i].num, stu[i].name,stu[i].score[0], stu[i].score[1], stu[i].score[2], stu[i].avg);}fclose(fp);
}int main()
{Student new_stu;//新学生TnputData(&new_stu);Student old_stu[6];ReadData(old_stu);InsertData(old_stu, &new_stu, 5);WriteData(old_stu);return 0;
}

8.将第7题结果仍存入原有的 stu_sort文件而不另建立新文件。

#include <stdio.h>
#include <string.h>typedef struct student
{int num;		//学号char name[32];  //姓名int score[3];   //成绩float avg;      //平均分
}Student;static int count;void TnputData(Student* stu)
{printf("请输入新学生的成绩信息:>\n");printf("num  name score1  score2  score3\n");scanf("%d %s %d %d %d", &(stu->num), stu->name,&(stu->score[0]), &(stu->score[1]), &(stu->score[2]));stu->avg = (stu->score[0] + stu->score[1] + stu->score[2]) / 3.0;}void ReadData(Student** stu)
{FILE* fp = fopen("stu_sort.txt", "r");if (NULL == fp){printf("打开文件失败\n");return -1;}//读出数据的条数fscanf(fp, "%d", &count);*stu = (Student*)malloc(sizeof(Student) * (count + 1));Student* pstu = *stu;//读入数据for (int i = 0; i < count; i++){fscanf(fp, "%d %s %d %d %d %f\n", &pstu[i].num, pstu[i].name,&pstu[i].score[0], &pstu[i].score[1], &pstu[i].score[2], &pstu[i].avg);}fclose(fp);
}void InsertData(Student* old_stu, Student* new_stu, int n)
{int pos = 0;while (pos < n){if (new_stu->avg > old_stu[pos].avg){break;}pos++;}//移动数据for (int i = n; i > pos; i--){memcpy(&old_stu[i], &old_stu[i - 1], sizeof(Student));}//在pos位置把新学生的数据插入memcpy(&old_stu[pos], new_stu, sizeof(Student));
}void WriteData(Student* stu)
{FILE* fp = fopen("stu_sort.txt", "w");if (NULL == fp){printf("打开文件失败\n");return -1;}//写入数据fprintf(fp, "%d\n", count + 1);//先写出记录的条数for (int i = 0; i < count + 1; i++){fprintf(fp, "%3d %10s %3d %3d %3d %3.2f\n", stu[i].num, stu[i].name,stu[i].score[0], stu[i].score[1], stu[i].score[2], stu[i].avg);}fclose(fp);//释放学生结构空间free(stu);
}int main()
{Student new_stu;//新学生TnputData(&new_stu);Student *old_stu;ReadData(&old_stu);InsertData(old_stu, &new_stu, count);WriteData(old_stu);return 0;
}

9.有一磁盘文件 employee,内存放职工的数据。每个职工的数据包括职工姓名、职工号、性别、年龄、住址、工资、健康状况、文化程度。今要求将职工名、工资的信息单独抽出来另建一个简明的职工工资文件。

#include <stdio.h>
#include <stdlib.h>typedef struct employee
{int num;char name[10];int age;char addr[128];char sex[6];char health[10];int salary;char class[10];
}employee;int main()
{employee emp;FILE* fpIn = fopen("employee.txt", "r");if (NULL == fpIn){perror("fopen");return -1;}FILE* fpOut = fopen("emp_salary.txt", "w");if (NULL == fpOut){perror("fopen");fclose(fpIn);fpIn = NULL;return -1;}//读出数据并抽出相应的数据进行写入while (!feof(fpIn)){int count = fscanf(fpIn, "%d %s %d %s %s %s %d %s", &emp.num, emp.name, &emp.age, emp.addr, emp.sex, emp.health, &emp.salary, emp.class);if (count == -1)break;fprintf(fpOut, "%s %d\n", emp.name, emp.salary);}fclose(fpIn);fclose(fpOut);fpIn = NULL;fpOut = NULL;return 0;
}

10. 从第9题的“职工工资文件”中删去一个职工的数据,再存回原文件。

#include <stdio.h>
#include <string.h>typedef struct emp_salary
{char name[32];int salary;
}emp_salary;int main()
{emp_salary es[100];FILE* fp = fopen("emp_salary.txt", "r");if (NULL == fp){perror("fopen");return 1;}int i = 0;while (!feof(fp)){int count = fscanf(fp, "%s %d", es[i].name, &es[i].salary);if (count == -1)break;i++;}fclose(fp);fp = NULL;//输入名字,进行删除char name[32] = { 0 };printf("请输入要删除的职工名字:");scanf("%s", name);fp = fopen("emp_salary.txt", "w");if (NULL == fp){perror("fopen");return 1;}for (int j = 0; j < i; j++){if (strcmp(name, es[j].name) == 0){continue;}fprintf(fp, "%s %d\n", es[j].name, es[i].salary);}fclose(fp);fp = NULL;return 0;
}

11.从键盘输入若干行字符(每行长度不等),输入后把它们存储到一磁盘文件中。再从该文件中读入这些数据,将其中小写字母转换成大写字母后在显示屏上输出。

#include <stdio.h>
#include <string.h>void ToUpper(char* str)
{while (*str != '\0'){if (*str >= 'a' && *str <= 'z')*str -= 32;str++;}
}int main()
{FILE* fp = fopen("letter.txt", "w");if (NULL == fp){perror("fopen");return -1;}char buf[128] = { 0 };while (1){printf("请输入字符串(输入exit则退出):>");gets(buf);if (strcmp("exit", buf) == 0)break;fprintf(fp, "%s\n", buf);}fclose(fp);fp = NULL;//读出数据,进行数据转换fp = fopen("letter.txt", "r");if (NULL == fp){perror("fopen");return -1;}while (!feof(fp)){memset(buf, 0, 128);fgets(buf, 128, fp);ToUpper(buf);printf("%s", buf);}fclose(fp);fp = NULL;return 0;
}

这篇关于谭浩强【C语言程序设计】第十章习题详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/722751

相关文章

MySQL中的交叉连接、自然连接和内连接查询详解

《MySQL中的交叉连接、自然连接和内连接查询详解》:本文主要介绍MySQL中的交叉连接、自然连接和内连接查询,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、引入二、交php叉连接(cross join)三、自然连接(naturalandroid join)四

Go 语言中的select语句详解及工作原理

《Go语言中的select语句详解及工作原理》在Go语言中,select语句是用于处理多个通道(channel)操作的一种控制结构,它类似于switch语句,本文给大家介绍Go语言中的select语... 目录Go 语言中的 select 是做什么的基本功能语法工作原理示例示例 1:监听多个通道示例 2:带

mysql的基础语句和外键查询及其语句详解(推荐)

《mysql的基础语句和外键查询及其语句详解(推荐)》:本文主要介绍mysql的基础语句和外键查询及其语句详解(推荐),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋... 目录一、mysql 基础语句1. 数据库操作 创建数据库2. 表操作 创建表3. CRUD 操作二、外键

Spring Boot项目部署命令java -jar的各种参数及作用详解

《SpringBoot项目部署命令java-jar的各种参数及作用详解》:本文主要介绍SpringBoot项目部署命令java-jar的各种参数及作用的相关资料,包括设置内存大小、垃圾回收... 目录前言一、基础命令结构二、常见的 Java 命令参数1. 设置内存大小2. 配置垃圾回收器3. 配置线程栈大小

鸿蒙中@State的原理使用详解(HarmonyOS 5)

《鸿蒙中@State的原理使用详解(HarmonyOS5)》@State是HarmonyOSArkTS框架中用于管理组件状态的核心装饰器,其核心作用是实现数据驱动UI的响应式编程模式,本文给大家介绍... 目录一、@State在鸿蒙中是做什么的?二、@Spythontate的基本原理1. 依赖关系的收集2.

Redis实现延迟任务的三种方法详解

《Redis实现延迟任务的三种方法详解》延迟任务(DelayedTask)是指在未来的某个时间点,执行相应的任务,本文为大家整理了三种常见的实现方法,感兴趣的小伙伴可以参考一下... 目录1.前言2.Redis如何实现延迟任务3.代码实现3.1. 过期键通知事件实现3.2. 使用ZSet实现延迟任务3.3

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Python Faker库基本用法详解

《PythonFaker库基本用法详解》Faker是一个非常强大的库,适用于生成各种类型的伪随机数据,可以帮助开发者在测试、数据生成、或其他需要随机数据的场景中提高效率,本文给大家介绍PythonF... 目录安装基本用法主要功能示例代码语言和地区生成多条假数据自定义字段小结Faker 是一个 python

Java Predicate接口定义详解

《JavaPredicate接口定义详解》Predicate是Java中的一个函数式接口,它代表一个判断逻辑,接收一个输入参数,返回一个布尔值,:本文主要介绍JavaPredicate接口的定义... 目录Java Predicate接口Java lamda表达式 Predicate<T>、BiFuncti

详解如何通过Python批量转换图片为PDF

《详解如何通过Python批量转换图片为PDF》:本文主要介绍如何基于Python+Tkinter开发的图片批量转PDF工具,可以支持批量添加图片,拖拽等操作,感兴趣的小伙伴可以参考一下... 目录1. 概述2. 功能亮点2.1 主要功能2.2 界面设计3. 使用指南3.1 运行环境3.2 使用步骤4. 核