b) 建议函数流程:
i. 打开数据文件,失败返回-1;
ii. 从头到尾扫描数据文件(即预读一遍)获得学生人数;
iii. 根据学生人数,利用malloc和sizeof等函数或运算符为struct student** pStudents分配内存;
iv. 利用rewind函数,定位到文件头;
v. 读取数据文件,并把每一条记录通过数组下标法或指针法保存到结构体数组pStudents中;
vi. 关闭文件;
vii. 返回学生人数。
c) 数据文件格式说明:
一行一条学生信息的记录,不同属性用空格隔开,输入数据中无总成绩记录,例如:
张三 通信 89 93 95
李四 网络 88 91 94
王五 物联网 71 94 88
编写统计函数:
a) 函数定义void Count(struct student pStudents[], int num)。输入参数分别为保存学生的结构体数组和学生人数。
b) 功能为:统计所有学生的总成绩和每个专业(假定一共三个专业:通信,网络,物联网)的平均成绩;输入参数包括学生信息结构体数组,学生人数,返回的每个学生的总成绩直接填充到对应的输入结构体数组对应字段中。统计信息包括三个专业的总人数、平均成绩数组,用全局变量来表示。访问每个学生信息的时候,用指针来指向当前正在处理的学生。
c) 设计一个或者三个带参数的宏,判断输入的字符串是否是指定的专业名称,并在函数Count中使用。
编写main函数实现:
a) 定义变量,其中保存学生信息的数据文件直接在源代码中初始化;
b) 读取学生信息,如果失败,打印失败信息并退出程序;
c) 统计学生信息;
d) 输出统计信息。
e) 释放内存。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student{
char name[15];
char major[15];
int Eng_sco;
int cal_sco;
int c_sco;
int sum;
};
int tx_per=0,tx_ave,tx_sum=0;
int wl_per=0,wl_ave,wl_sum=0;
int wlw_per=0,wlw_ave,wlw_sum=0;
int ReadStudentInfo(const char* filename, struct student** pStudents);
void Count(struct student pStudents[], int num);
int main()
{
int count;
int m;
struct student *list;
count=ReadStudentInfo("readme.txt", &list);
printf("学生信息: \n");
printf("----------------------------------------------------\n");
printf("序号 姓 名 专业名称 英语成绩 线性代数成绩 c语言成绩 总成绩\n");
for(m=1;m<=count;m++)
{
printf("%4d %s %s %4d %4d %4d %4d\n",m,(list+m-1)->name,(list+m-1)->major,(list+m-1)->Eng_sco,(list+m-1)->cal_sco,(list+m-1)->c_sco,(list+m-1)->sum);
}
Count(list, count);
printf("\n统计信息 :\n");
printf("----------------------------------------------------\n");
printf("序号 专业名称 学生人数 平均成绩\n");
printf(" 1 通信 %d %d\n",tx_per,tx_ave);
printf(" 2 网络 %d %d\n",wl_per,wl_ave);
printf(" 3 物联网 %d %d\n",wlw_per,wlw_ave);
return 0;
}
int ReadStudentInfo(const char* filename, struct student** pStudents)
{
FILE *fp;
char ch;
int i=1,j;
fp=fopen(readme.txt,"r");
if(fp==NULL)
{
printf("cann't open the file");
exit(-1);
}
ch=fgetc(fp);
while(ch!=EOF)
{
if(ch=='\n')
{
i++;
}
ch=fgetc(fp);
}
rewind(fp);
*pStudents=(struct student*)malloc(sizeof(** pStudents)*i);
for(j=0;j<i;j++)
{
fread(&*pStudents[j],sizeof(struct student)-sizeof(int),1,fp);
(*pStudents+j)->sum=((*pStudents+j)->Eng_sco+(*pStudents+j)->cal_sco+(*pStudents+j)->c_sco);
}
fclose(fp);
return i;
}
void Count(struct student pStudents[], int num)
{
int n=1;
for(n=1;n<=num;n++)
{
if(!strcmp((pStudents+n-1)->major,"通信"))
{
tx_per++;
tx_sum=tx_sum+(pStudents+n-1)->sum;
}
if(!strcmp((pStudents+n-1)->major,"网络"))
{
wl_per++;
wl_sum=wl_sum+(pStudents+n-1)->sum;
}
if(!strcmp((pStudents+n-1)->major,"物联网"))
{
wlw_per++;
wlw_sum=wlw_sum+(pStudents+n-1)->sum;
}
tx_ave=tx_sum/tx_per;
wl_ave=wl_sum/wl_per;
wlw_ave=wlw_sum/wlw_per;
}
free(pStudents);
}
运行不起来,是哪里出问题了?
\#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct student{
char name[15];
char major[15];
int Eng_sco;
int cal_sco;
int c_sco;
int sum;
};
int tx_per=0,tx_ave,tx_sum=0;
int wl_per=0,wl_ave,wl_sum=0;
int wlw_per=0,wlw_ave,wlw_sum=0;
int ReadStudentInfo(const char* filename, struct student** pStudents);
void Count(struct student pStudents[], int num);
int main()
{
int count;
int m;
struct student *list;
count=ReadStudentInfo("stu.txt", &list);
printf("学生信息: \n");
printf("----------------------------------------------------\n");
printf("序号 姓名 专业名称 英语成绩 线性代数成绩 c语言成绩 总成绩\n");
for(m=1;m<=count;m++)
{
printf("%4d %6s %6s %4d %4d %4d %4d\n",m,(list+m-1)->name,(list+m-1)->major,(list+m-1)->Eng_sco,(list+m-1)->cal_sco,(list+m-1)->c_sco,(list+m-1)->sum);
}
Count(list, count);
printf("\n统计信息 :\n");
printf("----------------------------------------------------\n");
printf("序号 专业名称 学生人数 平均成绩\n");
printf(" 1 通信 %d %d\n",tx_per,tx_ave);
printf(" 2 网络 %d %d\n",wl_per,wl_ave);
printf(" 3 物联网 %d %d\n",wlw_per,wlw_ave);
return 0;
}
void CutString(char* buf,char*temp,char sp);
int ReadStudentInfo(const char* filename, struct student** pStudents)
{
FILE *fp;
char ch;
int i=1,j;
fp=fopen(filename,"r");
if(fp==NULL)
{
printf("cann't open the file");
exit(-1);
}
ch=fgetc(fp);
while(ch!=EOF)
{
if(ch=='\n')
{
i++;
}
ch=fgetc(fp);
}
rewind(fp);
*pStudents=(struct student*)malloc(sizeof(** pStudents)*i);
char buf[512]={0};
for(j=0;j<i;j++)
{
memset(*pStudents+j,0,sizeof(struct student));
fgets(buf,512,fp);
int len = strlen(buf);
buf[len]=' ';
CutString(buf,(*pStudents+j)->name,' ');
CutString(buf,(*pStudents+j)->major,' ');
char e_Score[8],cal_Score[8],c_Score[8];
memset(e_Score,0,8);
memset(cal_Score,0,8);
memset(c_Score,0,8);
CutString(buf,e_Score,' ');
(*pStudents+j)->Eng_sco = atoi(e_Score);
CutString(buf,cal_Score,' ');
(*pStudents+j)->cal_sco = atoi(cal_Score);
CutString(buf,c_Score,' ');
(*pStudents+j)->c_sco = atoi(c_Score);
(*pStudents+j)->sum=((*pStudents+j)->Eng_sco+(*pStudents+j)->cal_sco+(*pStudents+j)->c_sco);
}
fclose(fp);
return i;
}
void CutString(char* buf,char*temp,char sp)
{
int len = strlen(buf);
for (int i=0;i<len;i++)
{
if (buf[i]==sp)
{
memcpy(buf,buf+i+1,strlen(buf+i+1));
break;
}
temp[i] = buf[i];
}
}
void Count(struct student pStudents[], int num)
{
int n=1;
for(n=1;n<=num;n++)
{
if(!strcmp((pStudents+n-1)->major,"通信"))
{
tx_per++;
tx_sum=tx_sum+(pStudents+n-1)->sum;
tx_ave=tx_sum/tx_per;
}
if(!strcmp((pStudents+n-1)->major,"网络"))
{
wl_per++;
wl_sum=wl_sum+(pStudents+n-1)->sum;
wl_ave=wl_sum/wl_per;
}
if(!strcmp((pStudents+n-1)->major,"物联网"))
{
wlw_per++;
wlw_sum=wlw_sum+(pStudents+n-1)->sum;
wlw_ave=wlw_sum/wlw_per;
}
}
free(pStudents);
}
闲来无事,改了一把, 拿过去跑一把吧
ReadStudentInfo(const char* filename, struct student** pStudents)函数中fopen的readme.txt如果是文件名,请加双引号,如果是形参,请写参数名
书上C语言的文件里有
ReadStudentInfo(const char* filename, struct student** pStudents)函数中fopen的readme.txt如果是文件名,请加双引号,如果是形参,请写参数名
fp=fopen(readme.txt,"r")这里加个双引号
fp=fopen(readme.txt,"r");
改成
fp=fopen(filename,"r");
我把fopen中的文件名改为一个不存在的文件名时,可以打印出cann't open the file然后跳出。但改为形参或存在的文件名时,程序就运行不起来
读文件函数写的有问题,1、最好把while(ch!=EOF)改为while(!feof(fp)) 2、你打开文件的方式为“r”,但却用fread以二进制方式读取,还是先看看读写文件的基本方式吧
问题出在 fread(&*pStudents[j],sizeof(struct student)-sizeof(int),1,fp);这一句,你这样读,要求文件保存的时候也是直接保存结构体到文件,这样的文件你是看不懂的,而现在是保存的是人可以看懂的字符串,所以这个函数是不能用的,可以使用fgets()来读取一行放到缓冲里,让后按照空格解析出每一个字段来,赋值给结构体的相应的成员
首先确定文件以什么格式保存的,用txt打开文件,显示的是乱码的话一般是二进制文件,反之是文本文件;
假如是二进制文件的话,一般不能这样用fread直接读取数据到结构体,要考虑到数据对齐问题;
假如是文本文件的话,先读取整行数据,然后用函数split将数据按照分割字符分开,挨个按照数据类型处理保存到结构体中:字符串数据可以直接拷贝,整型数据是用字符串表示的,需要使用atoi之类的函数转换一下;
还有很多问题要解决,这里只提供个大概的思路,好好研究下C语言吧。。。
没有问题的话请,请采用并把C币付了,好歹也花了半个多小时帮你搞
读文件函数有问题,
1、最好把while(ch!=EOF)改为while(!feof(fp))
2、你打开文件的方式为“r”,但却用fread以二进制方式读取,还是先看看读写文件的基本方式吧
fp=fopen(readme.txt,"r");第一个参数路径需要双引号