实例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(用“结构”统计学生成绩)的更多相关文章

  1. C语言实例解析精粹学习笔记——18

    <C语言实例解析精粹>中编译环境采用的是Turbo C 2.0.但是这个编译器年代久远,较新的编译器对书中的某些例子支持不好,在学习的时候同时做一些笔记. 实例18:将一个无符号整数转换为 ...

  2. C语言实例解析精粹学习笔记——35(报数游戏)

    实例35: 设由n个人站成一圈,分别被编号1,2,3,4,……,n.第一个人从1开始报数,每报数位m的人被从圈中推测,其后的人再次从1开始报数,重复上述过程,直至所有人都从圈中退出. 实例解析: 用链 ...

  3. C语言实例解析精粹学习笔记——42(插入排序)

    实例说明: 将一个整数数组按从小到大的顺序进行排序.(主要学习基本的插入排序和改进的冒泡排序的算法和应用) 思路1: 从第一个数据开始,分别比较其后的数据,若比它小,则将这两个数的位置交换:从第一个数 ...

  4. C语言实例解析精粹学习笔记——36(模拟社会关系)

    实例: 设计一个模拟社会关系的数据结构,每个人的信息用结构表示,包含名字.性别和指向父亲.母亲.配偶.子女的指针(只限两个子女).要求编写以下函数: (1)增加一个新人的函数 (2)建立人与人之间关系 ...

  5. C语言实例解析精粹学习笔记——32

    实例32: 编制一个包含姓名.地址.邮编和电话的通讯录输入和输出函数. 思路解析: 1.用结构体来完成姓名.地址.邮编和电话的组合. 2.结构体指针的使用. 3.malloc的使用 4.scanf函数 ...

  6. C语言实例解析精粹学习笔记——31

    实例31: 判断字符串是否是回文 思路解析: 引入两个指针变量(head和tail),开始时,两指针分别指向字符串的首末字符,当两指针所指字符相等时,两指针分别向后和向前移动一个字符位置,并继续比较, ...

  7. C语言实例解析精粹学习笔记——30

    实例30: 用已知字符串s中的字符,生成由其中n个字符组成的所有字符排列.设n小于字符串s的字符个数,其中s中的字符在每个排列中最多出现一次.例如,对于s[]="abc",n=2, ...

  8. C语言实例解析精粹学习笔记——28

    实例28:从键盘读入实数 题目要求: 编制一个从键盘读入实数的函数readreal(double *rp).函数将读入的实数字符列转换成实数后,利用指针参数rp,将实数存于指针所指向的变量*rp. 思 ...

  9. C语言实例解析精粹学习笔记——19

    实例19:判断正整数n的d进制表示形式是否是回文数(顺着看和倒着看相同的数). 主要思路: 一种方法:将正整数n数转换成d进制的数,逐个比较首尾对应数字,判断是否为回文数. 另一种方法:将正整数n数转 ...

随机推荐

  1. nginx配置+uwsgi+负载均衡配置

    nginx静态文件配置 location /static{ alias /var/www/myApp/static; } sudo mkdir -vp /var/www/myApp/static/ s ...

  2. 在centos7中安装redis,并通过node.js操作redis

    引言 最近在学习node.js 连接redis的模块,所以尝试了一下在虚拟机中安装cent OS7,并安装redis,并使用node.js 操作redis.所以顺便做个笔记. 如有不对的地方,欢迎大家 ...

  3. ul自适应li问题

    内容提要: li浮动时ul高度为0,解决ul自适应高度的几种方法 在网页设计中,常常需要对li标签做浮动效果,但是在不同浏览器中会遇到兼容性问题,比如IE中会出现ul高度为0的情况,是效果不能达到预期 ...

  4. Java传引用问题

            Java传引用问题  使用Java调用方法时,可以传值,也可以传引用.下面说说两者的区别: 1.传值 传值中的"值"类型是指java的8大基本类型(基础知识,不知道 ...

  5. git作业

    第一部分 我的地址:https://github.com/Tohsaka-Rin-ZYJ/123/tree/master 第二部分 我对git的认识: Git是一个开源的分布式版本控制系统,用以有效. ...

  6. 如何让一个简单的maven项目支持one-jar 做成一个jar fatjar

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  7. linux shell——zsh的安装与使用

    Shell是在程序员与服务器间建立一个桥梁,它对外提供一系列命令,让我们得以控制服务器.常用的Bash就是Shell的一种,也是Linux下默认Shell程序.这里介绍一种更强大的.更人性化的Shel ...

  8. div可编辑框,去除粘贴文字样式😄

    上个月做了个聊天的需求(网页版的).说到聊天都想到输入框,说到输入框都会想到input,但是input标签是不支持插入图片的(包括areatext标签).查阅了一些资料就看到div标签有一个属性con ...

  9. Java字符串常量池是什么?为什么要有这种常量池?

    简单介绍 Java中的字符串常量池(String Pool)是存储在Java堆内存中的字符串池.我们知道String是java中比较特殊的类,我们可以使用new运算符创建String对象,也可以用双引 ...

  10. ORA-01950:对表空间 'USERS' 无权限

    在存储数据时出现ORA-01950:对表空间 'USERS' 无权限 错误,解决如下: 找到对象Users下的用户名,然后点编辑,角色权限添加dba 在oracle创建了一个新的表空间和一个新的用户, ...