谭浩强【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

相关文章

Linux线程同步/互斥过程详解

《Linux线程同步/互斥过程详解》文章讲解多线程并发访问导致竞态条件,需通过互斥锁、原子操作和条件变量实现线程安全与同步,分析死锁条件及避免方法,并介绍RAII封装技术提升资源管理效率... 目录01. 资源共享问题1.1 多线程并发访问1.2 临界区与临界资源1.3 锁的引入02. 多线程案例2.1 为

Python使用Tenacity一行代码实现自动重试详解

《Python使用Tenacity一行代码实现自动重试详解》tenacity是一个专为Python设计的通用重试库,它的核心理念就是用简单、清晰的方式,为任何可能失败的操作添加重试能力,下面我们就来看... 目录一切始于一个简单的 API 调用Tenacity 入门:一行代码实现优雅重试精细控制:让重试按我

C语言中%zu的用法解读

《C语言中%zu的用法解读》size_t是无符号整数类型,用于表示对象大小或内存操作结果,%zu是C99标准中专为size_t设计的printf占位符,避免因类型不匹配导致错误,使用%u或%d可能引发... 目录size_t 类型与 %zu 占位符%zu 的用途替代占位符的风险兼容性说明其他相关占位符验证示

Python标准库之数据压缩和存档的应用详解

《Python标准库之数据压缩和存档的应用详解》在数据处理与存储领域,压缩和存档是提升效率的关键技术,Python标准库提供了一套完整的工具链,下面小编就来和大家简单介绍一下吧... 目录一、核心模块架构与设计哲学二、关键模块深度解析1.tarfile:专业级归档工具2.zipfile:跨平台归档首选3.

idea的终端(Terminal)cmd的命令换成linux的命令详解

《idea的终端(Terminal)cmd的命令换成linux的命令详解》本文介绍IDEA配置Git的步骤:安装Git、修改终端设置并重启IDEA,强调顺序,作为个人经验分享,希望提供参考并支持脚本之... 目录一编程、设置前二、前置条件三、android设置四、设置后总结一、php设置前二、前置条件

python中列表应用和扩展性实用详解

《python中列表应用和扩展性实用详解》文章介绍了Python列表的核心特性:有序数据集合,用[]定义,元素类型可不同,支持迭代、循环、切片,可执行增删改查、排序、推导式及嵌套操作,是常用的数据处理... 目录1、列表定义2、格式3、列表是可迭代对象4、列表的常见操作总结1、列表定义是处理一组有序项目的

python使用try函数详解

《python使用try函数详解》Pythontry语句用于异常处理,支持捕获特定/多种异常、else/final子句确保资源释放,结合with语句自动清理,可自定义异常及嵌套结构,灵活应对错误场景... 目录try 函数的基本语法捕获特定异常捕获多个异常使用 else 子句使用 finally 子句捕获所

C++11范围for初始化列表auto decltype详解

《C++11范围for初始化列表autodecltype详解》C++11引入auto类型推导、decltype类型推断、统一列表初始化、范围for循环及智能指针,提升代码简洁性、类型安全与资源管理效... 目录C++11新特性1. 自动类型推导auto1.1 基本语法2. decltype3. 列表初始化3

SQL Server 中的 WITH (NOLOCK) 示例详解

《SQLServer中的WITH(NOLOCK)示例详解》SQLServer中的WITH(NOLOCK)是一种表提示,等同于READUNCOMMITTED隔离级别,允许查询在不获取共享锁的情... 目录SQL Server 中的 WITH (NOLOCK) 详解一、WITH (NOLOCK) 的本质二、工作

springboot自定义注解RateLimiter限流注解技术文档详解

《springboot自定义注解RateLimiter限流注解技术文档详解》文章介绍了限流技术的概念、作用及实现方式,通过SpringAOP拦截方法、缓存存储计数器,结合注解、枚举、异常类等核心组件,... 目录什么是限流系统架构核心组件详解1. 限流注解 (@RateLimiter)2. 限流类型枚举 (