Skip to content

Instantly share code, notes, and snippets.

@yuikns
Created July 14, 2013 17:59
Show Gist options
  • Save yuikns/5995108 to your computer and use it in GitHub Desktop.
Save yuikns/5995108 to your computer and use it in GitHub Desktop.
感觉博主代码还有些改进的地方,所以手痒改了一番.gcc编译测试通过.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 硬编码就不说什么了,不过真的环境中随意使用硬编码绝对是不可取的
#define N 208
// 命名规则习惯,你这儿说的是1个student,请不要加s
typedef struct
{
long stu_id; //学号
char name[20]; //学生姓名
int class_id; //班级号
char profession[20]; //专业名称
// 这儿这个结构我觉得做的不怎么合理,稍稍修改
//int average_sucess; //个人专业平均成绩
//int science; //科技活动奖励加分
//int ociology; //社会活动奖励加分
//int pro_flag; //专业挂科记录
//int CET4_flag; //英文四级是否通过
int scores[3]; // 0: 个人专业平均成绩 1: 科技活动奖励加分 2:社会活动奖励加分
int flags; // 按位保存bool flag 从低到高分别保存: 1.专业挂科记录 2.CET4是否过 共可以保存int类型位数个
//文中没有保研方面相关信息,勿凭空生成
//int status; //保研状况
double average; // scores[0] * 0.6 + scores[1] * 0.3 + scores[2] * 0.1
}student;
typedef student * p_student ; // 我们可以这么用typedef
// 全局变量谨慎使用
int comp(const void *lp,const void *rp)
{
return ((p_student)rp)->average > ((p_student)lp)->average; //
}
//读取文本文件,最好不要凭空来个文件名
int fun_load(const char * file_name,p_student p,int max_len);
void fun_sort(p_student ,int len);//排序计算排名 为毛注释是"冒泡"?说好的qsort呢
void fun_print_all(p_student p,int len);//输出所有学生表单
// 很好,我喜欢你没有写 void main
int main(int argc, char *argv[])
{
// 其实可以用malloc或calloc,但是既然没有用,我也不用了
student data[N]; //申请空间,以后的操作都在这儿搞
p_student ps;
ps = data; // 等价于 ps = &data[0];
// i是什么意思 ? 我们用个更加容易理解的变量名吧
int num=fun_load("stud.txt",ps,N); //读取文本内容 得到学生信息总数
if(num == 0)
{
fprintf(stderr,"读取信息为空!\n");
return -1; // 在main中,返回0表示正常,返回非0表示不同的错误,以便调试之类
}
fun_sort(ps,num); //全校排名
fun_print_all(ps,num); //输出
return 0;
}
//将文本文件内容读取到结构体数组中
int fun_load(const char * file_name,p_student p,int max_len)
{
int num=0;
FILE *fp;
if((fp=fopen(file_name,"r"))==NULL)
{
fprintf(stderr,"无法打开指定文件\n");
// 错误信息我们输出到 stderr,正常进程信息我们输出到stdout
//不要直接断开,我们不妨返回"找到0个内容"吧
return 0;
}
// 我们观察目标文件,每条信息放在一行,中间用\t隔开
// 读取文件有很多方法,比如fread/fwrite比较适用于读取固定长度的文件
// 此处比较适合按行读取
// linux C 提供了getline,但是它不是std函数
// std库只提供了fgets
// fgets的原型是: char *fgets(char *s, int size, FILE *stream);
// 此外,我们传入参数有个 max_len,表示已申请的空间的容量,
// 用来保证没有下标越界的问题
// 所以我们读取的是"小于等于N条数据",而不是所有数据
char buff[1024];
const char *delim = "\t"; // 分隔符定义为 \t
while(fgets(buff,1024,fp) != 0 && num < max_len)
{
// 字符串数组初始化
memset(p[num].name,0,20);
memset(p[num].profession,0,20);
// strtok 是一种分割字符串的很好的方法,注意:线程不安全
p[num].stu_id = atol(strtok(buff,delim)) ; //
// memcpy 是最好的字符串copy , 20表示最长copy 19个字符,
// 因为至少要一个位置存放'\0'表示结束
memcpy(p[num].name,strtok(NULL,delim),19);
p[num].class_id = atoi(strtok(NULL,delim)) ; //
memcpy(p[num].profession,strtok(NULL,delim),19);
int j;
for(j=0;j<3;j++)
p[num].scores[j] = atoi(strtok(NULL,delim)) ; //
int pflag = atoi(strtok(NULL,delim)); // 专业课有挂科
int cflag = atoi(strtok(NULL,delim)); // CET有通过
p[num].flags = (cflag & 1) * 2 + (pflag & 1);
// 个人觉得计算最后平均分放在这儿比较好.
// 所有内容额外遍历一遍计算需要花费更多的时间
p[num].average = p[num].scores[0] * 0.6 + p[num].scores[1] * 0.3 + p[num].scores[2] * 0.1 ;
num ++;
}
// 空间申请了需要释放,文件打开了需要关闭
fclose(fp);
return num; // 返回 读取过的行数
}
void fun_sort(p_student p,int len) // qsort排序,把总成绩进行排名
{
qsort(p,len,sizeof(student),comp);
}
void fun_print_all(p_student p,int len)
{
int i;
// 打表我们还是输出表头吧
printf("%-10s %-10s %-5s %-8s %-10s %-8s %-8s %-8s %-8s %-10s\n",
"学号","姓名","班级","专业",
"专业均分","科技加分","社会加分",
"专业挂科","CET4通过",
"综合");
for(i=0;i<len;i++)
{
// 其实可以调节下让输出平整的,不过就这样吧
printf("%-10d %-10s %-5d %-8s %-10d %-8d %-8d %-8s %-8s %.2f\n",
p[i].stu_id,p[i].name,p[i].class_id,p[i].profession,
p[i].scores[0],p[i].scores[1],p[i].scores[2],
(p[i].flags%1?"是":"否"),
((p[i].flags/2)%2?"是":"否"),
p[i].average);
}
printf("共%d条信息\n",len);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment