实例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. How To Capture Packets with TCPDUMP?

    http://linux-circles.blogspot.com/2012/11/how-to-capture-packets-with-tcpdump.html See the list of i ...

  2. 【Leetcode】【Easy】Balanced Binary Tree

    Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary ...

  3. ul自适应li问题

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

  4. ABAP git客户端

    Jerry习惯把自己写的小程序放到自己的github上:https://github.com/i042416 对于写的ABAP程序,需要先把SAPGUI里的代码手动拷贝到本地,然后用git客户端pus ...

  5. vue错误提示 Cannot read property 'beforeRouteEnter' of undefined,刷新后跳到首页

    vue错误提示 Cannot read property 'beforeRouteEnter' of undefined,刷新后跳到首页 因为vue-router版本太高了,我vue用的是2.3.4, ...

  6. IOS 连接服务器(socket)

    // // ViewController.m // 05.聊天室 // // Created by apple on 14/12/5. // Copyright (c) heima. All righ ...

  7. bash: ./adb: No such file or directory

    运行adb出现这种错误: bash: ./adb: No such file or directory   但adb确实存在. 可能1.你用的是64位的Linux,没装32位运行时库,安装 $ sud ...

  8. expected expression __bridge

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u013020103/article/details/30491117 expected expres ...

  9. 【[CTSC2012]熟悉的文章】

    题目 好题啊 \(SAM\)+单调队列优化\(dp\) 首先这个\(L\)满足单调性真是非常显然我们可以直接二分 二分之后套一个\(dp\)就好了 设\(dp[i]\)表示到达\(i\)位置熟悉的文章 ...

  10. WebStorm11 注册码及激活

    网址:http://www.jianshu.com/p/5ce394a28ce5 1.获取注册码 打开第一个网址(IntelliJ IDEA 注册码),我们能看到下面的界面,直接点击获取激活码,将生成 ...