实验内容:
从文件中读取学生信息并打印。完成以下编程实验,调试运行程序并完成报告。
设每个学生包含如下信息:
属性名 | 姓名 | 专业名称 | 英语成绩 | 线性代数成绩 | C成绩 | 总成绩 | 类型 | 字符串 | 字符串 | 整数 | 整数 | 整数 | 整数(初始化为0) |
- 设计一个表示学生信息的结构体 struct student;
- 编写函数从文件读入所有学生信息:
- 函数定义 int ReadStudentInfo(const char* filename, struct student** pStudents); 函数返回值:返回学生个数,失败返回-1。输入参数const char* filename:数据文件名;struct student** pStudents:返回读取的学生信息,内存由ReadStudentInfo函数分配,main函数释放。
- 建议函数流程:
- 打开数据文件,失败返回-1;
- 从头到尾扫描数据文件(即预读一遍)获得学生人数;
- 根据学生人数,利用malloc和sizeof等函数或运算符为struct student** pStudents分配内存;
- 利用fseek函数,定位到文件头;
- 读取数据文件,并把每一条记录通过数组下标法或指针法保存到结构体数组pStudents中;
- 关闭文件;
- 返回学生人数。
- 数据文件格式说明:
一行一条学生信息的记录,不同属性用空格隔开,输入数据中无总成绩记录,例如:
张三 通信 89 93 95
李四 网络 88 91 94
王五 物联网 71 94 88
…
- 编写统计函数:
- 函数定义void Count(struct student pStudents[], int num)。输入参数分别为保存学生的结构体数组和学生人数。
- 功能为:统计所有学生的总成绩和每个专业(假定一共三个专业:通信,网络,物联网)的平均成绩;输入参数包括学生信息结构体数组,学生人数,返回的每个学生的总成绩直接填充到对应的输入结构体数组对应字段中。统计信息包括三个专业的总人数、平均成绩数组,用全局变量来表示。访问每个学生信息的时候,用指针来指向当前正在处理的学生。
- 设计一个或者三个带参数的宏,判断输入的字符串是否是指定的专业名称,并在函数Count中使用。
- 编写信息输出函数:
要求通过一定的格式控制符,使得输出美观。输出格式为:
学生信息: ----------------------------------------------------- 序号 姓 名 专业名称 英语成绩 线性代数成绩 C成绩 总成绩 ???1 张三 ?????通信 ??????89 ??????????93 ????95 ???277 ???2 …?… 统计信息: ----------------------------------------------------- ?序号 专业名称 学生人数 平均成绩 1 ????通信 ????322 ?????242 2 …?… |
- 编写main函数实现:
- 定义变量,其中保存学生信息的数据文件直接在源代码中初始化;
- 读取学生信息,如果失败,打印失败信息并退出程序;
- 统计学生信息;
- 输出统计信息。
- 释放内存。
参考代码:
?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct student{
char name[25];
char major[25];
int english;
int algebra;
int C;
int total;
};
int SICE=0,NE=0,IOT=0,ave_SICE=0,ave_NE=0,ave_IOT=0;
int ReadStudentInfo(const char* filename,struct student** pStudents);
void Count(struct student pStudents[], int num);
int main()
{
int num,i;
struct student *STU;
num=ReadStudentInfo("students.txt",&STU);
printf("学生信息:\n");
printf("------------------------------------------------------\n");
printf("序号 姓 名 专业名称 英语成绩 线性代数成绩 C成绩 总成绩\n");
for(i=0;i<num;i++)
{
printf("%4d %6s %8s %8d %12d %5d %6d\n",i+1,(STU+i)->name,(STU+i)->major,(STU+i)->english,(STU+i)->algebra,(STU+i)->C,(STU+i)->total);
}
Count(STU,num);
printf("\n\n统计信息:\n");
printf("------------------------------------------------------\n");
printf("序号 专业名称 学生人数 平均成绩\n");
printf("%4d %8s %8d %8d\n",1,"通信",SICE,ave_SICE);
printf("%4d %8s %8d %8d\n",2,"网络",NE,ave_NE);
printf("%4d %8s %8d %8d\n",3,"物联网",IOT,ave_IOT);
free(STU);
//printf("%d %d %d %d %d %d",SICE,NE,IOT,ave_SICE,ave_NE,ave_IOT);
return 0;
}
int ReadStudentInfo(const char* filename,struct student** pStudents)
{
FILE* fp;
int num=0,i;
char str[50];
if((fp=fopen(filename,"r"))==NULL) return -1;
while(fgets(str,100,fp)!=NULL) num++;
fseek(fp,0,SEEK_SET);
*pStudents=(struct student*)malloc(sizeof(struct student)*num);
for(i=0;i<num;i++)
{
fscanf(fp,"%s %s %d %d %d",(*pStudents+i)->name,(*pStudents+i)->major,&(*pStudents+i)->english,&(*pStudents+i)->algebra,&(*pStudents+i)->C);
(*pStudents+i)->total=(*pStudents+i)->english+(*pStudents+i)->algebra+(*pStudents+i)->C;
//fread((*pStudents+i),sizeof(struct student),1,fp);
}
fclose(fp);
return num;
}
void Count(struct student pStudents[], int num)
{
int i;
for(i=0;i<num;i++)
{
if(strcmp(pStudents[i].major,"通信")==0)
{
SICE++;
ave_SICE+=pStudents[i].total;
}
if(strcmp(pStudents[i].major,"网络")==0)
{
NE++;
ave_NE+=pStudents[i].total;
}
if(strcmp(pStudents[i].major,"物联网")==0)
{
IOT++;
ave_IOT+=pStudents[i].total;
}
}
ave_SICE/=SICE;
ave_NE/=NE;
ave_IOT/=IOT;
}
讲解:
? ? ? ? 注意:运行此程序时,请确保源代码与“students.txt”在同一目录下。
? ? ? ? 实验8主要考察:文件输入/输出,结构体指针运用,动态内存。
????????有关文件输入/输出这里引入相关链接:点击进入。
????????己见:由于实验报告说的并不清楚,所以只能写出针对本题附件中“students.txt”的相关操作,如果另有测试文件,例如增加专业“计算机”等,本程序无法实现。另外对于题目中的设计带参数的宏,我不解,直接用strcmp()不是很好吗。当然,如果有小伙伴追求更快更强更完美,可以自行修改count函数,使用带参宏。
|