C语言实例解析精粹学习笔记——34(用“结构”统计学生成绩)
实例34:
设学生信息包括学号、姓名和五门功课的成绩,要求编写输入输出学生信息的函数。在输入学生信息后,以学生成绩的总分从高到低顺序输出学生信息。
思路:
程序引入一个结构数组依次存储输入的学生信息,为了在一组学生信息排序时避免交换整个学生结构,另外引入一个存储下标的数组。排序过程中改变学生结构下标的顺序而不是交换整个结构。
程序代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h> #define N 2 //学生数据个数,练习时两三个就可以了。
#define SCORES 5 //成绩个数
#define NUMLEN 10 //允许的学号长度 //学生信息的结构体,包括:学号、姓名、五项成绩
struct std_type{
char no[NUMLEN];
char *name;
int scores[SCORES];
}; struct std_type students[N]; //定义一个学生结构体数组
//用于根据学生成绩对输出学生信息的先后进行排序
int order[N];
int total[N]; //函数读取一个学生的信息
int readastu(struct std_type *spt)
{
int len,j;
char buf[]; //输入学生的学号信息
//根据原书中的意思,是在进行错误输入时会终止,但实际上还是有些问题的
//目前我还没弄清楚是编译器的问题,还是程序的问题
//感觉像是程序的问题
printf("\nNumber : ");
if(scanf("%s",buf)==)
strncpy(spt->no,buf,NUMLEN-);
else
return ; //输入学生的姓名信息
printf("Name : ");
if(scanf("%s",buf)==)
{
len = strlen(buf);//自己不清楚缓冲区是怎么变化的,strncpy好像只是复制,好像没有清除的功能
//那么之前输入的学号(Number)也是放在buf缓冲区中,这个学号信息是被
//清除了吗?是怎么清除的?(有理解上的错误,在文末有补充)
spt->name = (char *)malloc(len+);
strcpy(spt->name,buf);
}
else
return ; //输入学生的成绩信息
printf("Scores(5 Number) : ");
for(j=; j< SCORES; j++)
{
if(scanf("%d",spt->scores+j)!=)
break;
}
if(j==)
{
free((spt->name));
return ;
}
for(;j<SCORES;j++)
spt->scores[j] = ;
return ;
} //函数输出一个学生的信息
int writeastu(struct std_type *spt)
{
int i; printf("Number : %s\n",spt->no);
printf("Name : %s\n",spt->name);
printf("Scores : ");
for(i=; i<SCORES; i++)
printf("%2d",spt->scores[i]);
printf("\n\n");
} int main()
{
int n,i,j,t;
char check_i; for(n=; n<N; n++) readastu(students+n);//此处和原书代码有些区别 //采用冒泡法对学生信息数组排序
for(i=; i<N; i++)
{
order[i] = i; //预置第i个输入的学生
for(t=,j=; j<SCORES; j++) //求第i个学生的总分
t += students[i].scores[j];
total[i] = t;
} //冒泡排序
for(i=; i<n-; i++) //共扫视n-1遍
{
for(j=; j<n--i; j++)
if(total[order[j]] < total[order[j+]])
{
t = order[j];
order[j] = order[j+];
order[j+] = t;
}
} printf("\n\nDo you want to check if your inputs are correct?(Y/N):");
scanf("%s",&check_i);
if(check_i=='y' || check_i=='Y')
for(j=; j<n; j++)
writeastu(students+order[j]);
else
return ; return ;
}
上述代码基本上99%是原书中的源代码,但是发现对于现在的编译器来说是有问题的(WIN7+CodeBlocks16.01),其中一些不解在注释中已标注。
一、对于学生的学号来说,并不能限制错误输入。
程序中设置的学号长度为10(NUMLEN),但实际上输入超过10个数字也是可以的,虽然输出结果会截止到10个数字。
第32行将输入的学号放入buf中,第33行将buf中前10个字符复制到结构体的no中

二、关于缓冲区的问题
41行中的注释是我的理解有点问题,
第39行的代码将我们输入的字符(学生的姓名)放入到buf中,(自己理解的)会覆盖之前输入的学号,所以缓冲区其实是没什么问题的。
三、对于输入成绩来说,也不能限制输入为5
当输入多于5个成绩时,输出会出现错误:

程序多于5个的数值会停留在缓冲区中,影响下一个学生的信息的输入,可以看下图中的例子

多于五个的成绩,02会被认为是下一个学生的学号,Ed会被认为是下一个学生的姓名;可以在第56后加一句fflush(stdin)来清空缓冲区以避免这种情况,下图是改正后的结果。

总结:程序吗,总是有可以改进的地方
C语言实例解析精粹学习笔记——34(用“结构”统计学生成绩)的更多相关文章
- C语言实例解析精粹学习笔记——18
<C语言实例解析精粹>中编译环境采用的是Turbo C 2.0.但是这个编译器年代久远,较新的编译器对书中的某些例子支持不好,在学习的时候同时做一些笔记. 实例18:将一个无符号整数转换为 ...
- C语言实例解析精粹学习笔记——35(报数游戏)
实例35: 设由n个人站成一圈,分别被编号1,2,3,4,……,n.第一个人从1开始报数,每报数位m的人被从圈中推测,其后的人再次从1开始报数,重复上述过程,直至所有人都从圈中退出. 实例解析: 用链 ...
- C语言实例解析精粹学习笔记——42(插入排序)
实例说明: 将一个整数数组按从小到大的顺序进行排序.(主要学习基本的插入排序和改进的冒泡排序的算法和应用) 思路1: 从第一个数据开始,分别比较其后的数据,若比它小,则将这两个数的位置交换:从第一个数 ...
- C语言实例解析精粹学习笔记——36(模拟社会关系)
实例: 设计一个模拟社会关系的数据结构,每个人的信息用结构表示,包含名字.性别和指向父亲.母亲.配偶.子女的指针(只限两个子女).要求编写以下函数: (1)增加一个新人的函数 (2)建立人与人之间关系 ...
- C语言实例解析精粹学习笔记——32
实例32: 编制一个包含姓名.地址.邮编和电话的通讯录输入和输出函数. 思路解析: 1.用结构体来完成姓名.地址.邮编和电话的组合. 2.结构体指针的使用. 3.malloc的使用 4.scanf函数 ...
- C语言实例解析精粹学习笔记——31
实例31: 判断字符串是否是回文 思路解析: 引入两个指针变量(head和tail),开始时,两指针分别指向字符串的首末字符,当两指针所指字符相等时,两指针分别向后和向前移动一个字符位置,并继续比较, ...
- C语言实例解析精粹学习笔记——30
实例30: 用已知字符串s中的字符,生成由其中n个字符组成的所有字符排列.设n小于字符串s的字符个数,其中s中的字符在每个排列中最多出现一次.例如,对于s[]="abc",n=2, ...
- C语言实例解析精粹学习笔记——28
实例28:从键盘读入实数 题目要求: 编制一个从键盘读入实数的函数readreal(double *rp).函数将读入的实数字符列转换成实数后,利用指针参数rp,将实数存于指针所指向的变量*rp. 思 ...
- C语言实例解析精粹学习笔记——19
实例19:判断正整数n的d进制表示形式是否是回文数(顺着看和倒着看相同的数). 主要思路: 一种方法:将正整数n数转换成d进制的数,逐个比较首尾对应数字,判断是否为回文数. 另一种方法:将正整数n数转 ...
随机推荐
- liunx增强命令
查找命令 grep 格式:grep [option] pattern [file] 实例: ps -ef | grep sshd 查找指定 ssh 服务进程 ps -ef | grep sshd | ...
- (原创)攻击方式学习之(3) - 缓冲区溢出(Buffer Overflow)
堆栈溢出 堆栈溢出通常是所有的缓冲区溢出中最容易进行利用的.了解堆栈溢出之前,先了解以下几个概念: 缓冲区 简单说来是一块连续的计算机内存区域,可以保存相同数据类型的多个实例. 堆栈 堆 栈是 ...
- verilog 三段式状态机的技巧
三段式代码多,但是有时钟同步,延时少,组合逻辑跟时序逻辑分开并行出错少. (1)同步状态转移 (2)当前状态判断接下来的状态 (3)动作输出 如果程序复杂可以不止三个always .always ...
- cobbler自动安装
基础环境:centos7.2 本地IP地址:192.168.56.12 网络环境:桥接模式 一.安装cobbler # rpm -ivh http://mirrors.aliyun.com/epel/ ...
- 简单的PHP算法题
简单的PHP算法题 目录 1.只根据n值打印n个0 2.根据n值打印一行 0101010101010101010101…… 3.根据n值实现1 00 111 0000 11111…… 4.根据n值实现 ...
- html默认样式重置
几个著名的重置css goal https://meyerweb.com/eric/tools/css/reset/ 雅虎 https://yuilibrary.com/yui/docs/cssr ...
- 2016 ACM/ICPC亚洲区大连站 F - Detachment 【维护前缀积、前缀和、二分搜索优化】
F - Detachment In a highly developed alien society, the habitats are almost infinite dimensional spa ...
- ASP.NET SignalR 与LayIM配合,轻松实现网站客服聊天室(一) 整理基础数据
最近碰巧发现一款比较好的Web即时通讯前端组件,layim,百度关键字即可,我下面要做的就是基于这个前端组件配合后台完成即时聊天等功能.当然用到的技术就是ASP.NET SingalR框架.本人不会c ...
- sublime重构变量
选中变量后按下Ctrl+D可批量修改变量名
- 学大伟业 Day 2 培训总结
一.dp 动态规划的本质 是一种思想.通过对原问题划分成子问题,寻找子问题之间的联系,通过求解子问题得出原问题的解.与贪心不同的是,动归是深谋远虑,考虑全局最优解:而贪心则目光短浅,只考虑局部最优解. ...