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

  • 40
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 21
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南风与鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值