第六章
写注释时要注意什么问题?(1)注释不是白话文翻译,不要鹦鹉学舌。 (2)不写做了什么,要写想做什么,如何做。 (3)注释可长可短,但应画龙点睛,重点加在语义转折处。 (4)边写代码边注释。 (5)修改代码的同时也修改注释。 (6)供别人使用的函数必须严格注释,特别是入口参数和出口参数,内部使用的函数以及某些简单的函数可以简单注释。
求阶乘 #include <stdio.h>int main() {int i;int sum=1;int n;scanf("%d",&n); for(i=1;i<=n;i++){sum*=i;}printf("%d",sum);} 输入一组数据,然后显示每次将输入数据进行累加运算后的结果。当输入 0时,停止输入数据,结束程序的运行。 标记控制的循环(推荐使用!),是以一个 标记值 (Sentinel Value )来控制循环的结束。 #include <stdio.h>int main(){int n,sum=0;int flag=1;while(flag){scanf("%d",&n);if(n==0){flag=0;}sum+=n;}printf("%d\n",sum);} 读入5个正整数,并显示,当程序读入数据为负数时,立即终止 #include <stdio.h>int main(){printf("请输入5个数:(每输入一个数字请敲击回车)\n");for(int i=0;i<5;i++){scanf("%d",&i);if(i<0) {printf("Program is over!");continue;}else{printf("你输入了:%d\n",i);}}} 计算1+2+3+……+100的和,同理计算1到n的和把n设为50,求前50项和。
//for循环,求1-n的和#include <stdio.h>int main(){int sum=0;int n;scanf("%d",&n); for(int i=1;i<=n;i++){sum+=i;}printf("%d",sum);}//while循环#include <stdio.h>int main(){int sum=0;int i=1;while (i <= 100){sum += i;i++;}printf("%d",sum);}//do while循环:i的值从0或1开始结果都正确#include <stdio.h>int main(){int sum=0;int i=1;do {sum += i;i++;}while (i <= 2);printf("%d",sum);} 大多数for 循环可以利用标准模式转换成 while 循环。为什么不能是所有 for 循环呢? n = 0;sum = 0;while (n < 10){scanf(“%d”, &i);if (i == 0) continue;//while循环中当i=0时,每次都不做n++sum += i;n++;}sum = 0;for (n = 0; n < 10; n++){scanf(“%d”, &i);if (i == 0) continue;//for循环中i=0时,每次都还会做n++sum += i;} 计算机在教育中的应用常被称为计算机辅助教学(Computer-Assisted Instruction, CAI)。请编写一个程序来帮助小学生学习四则混合运算。 按下列任务要求以循序渐进的方式编程。程序依次输出以下问题中的一题(包含编号和题目,编号和题目之间用)隔开):1)1+1=? 2)2+3=? 3)3+6=? 4)4+10=? 5)5+15=? ...
然后让学生输入答案。程序检查学生输入的答案是否正确。若正确,则打印"Right!";否则打印"Wrong!",如果用户输入非法,则清除用户的非法输入。用户完成一道题(无论对错)后询问用户是否继续下一题"Do you want to continue?",是(用户输入 y/Y)则问下一个问题,否则(用户输入 n/N/其他)结束测试,并输出学生的回答正确率(即正确题数除以总题数的百分比)。/*计算机在教育中的应用常被称为计算机辅助教学(Computer-Assisted Instruction, CAI)。请编写一个程序来帮助小学生学习四则混合运算。按下列任务要求以循序渐进的方式编程。程序依次输出以下问题中的一题(包含编号和题目,编号和题目之间用)隔开):1)1+1=?2)2+3=?3)3+6=?4)4+10=?5)5+15=?...然后让学生输入答案。程序检查学生输入的答案是否正确。若正确,则打印"Right!";否则打印"Wrong!",如果用户输入非法,则清除用户的非法输入。用户完成一道题(无论对错)后询问用户是否继续下一题"Do you want to continue?",是(用户输入 y/Y)则问下一个问题,否则(用户输入 n/N/其他)结束测试,并输出学生的回答正确率(即正确题数除以总题数的百分比)。*/#include <stdio.h>int main(){char *mission[]={"1)1+1=","2)2+3=","3)3+6=","4)4+10=","5)5+15="};int answer[]={2,5,9,14,20};int stuAn;char Yn;int ret;int count=0;//printf("%d\n",sizeof(mission));//printf("%d",sizeof(mission[0]));for(int i=0;i<sizeof(mission)/sizeof(mission[0]);i++){printf(" %s",mission[i]);ret=scanf("%d",&stuAn);//如果输入类型与指定类型匹配,则返回1while(ret!=1){fflush(stdin);//等价于while(getchar()!='\n');清空缓冲区printf("请输入一个数字\n");ret=scanf("%d",&stuAn);}if(stuAn==answer[i]){printf("Right!\n");count++;}else {printf("Wrong!\n");}printf("Do you want to continue?\n");scanf(" %c",&Yn);if(Yn=='y'||Yn=='Y') continue;else{break; }}printf("共有%d道题,你答对了%d道,你的正确率=%d%%",sizeof(mission)/sizeof(mission[0]),count,100*count/(sizeof(mission)/sizeof(mission[0])));}测试主要功能:是否能判断正误(输入错误答案1), 是否能提问用户要不要继续(输入y可以继续做题),是否能阻止非法输入(输入非法字符a,提示请输入一个数字)。
ret=scanf("%d",&stuAn);while(ret!=1){fflush(stdin);//等价于while(getchar()!='\n');都是清空缓存printf("请输入一个数字\n");ret=scanf("%d",&stuAn);}sizeof(mission)/sizeof(mission[0]),求数组长度 continue 语句有时还是非常方便的
continue 语句的确很少使用。但假设编写的循环要读入一些输入的数据,并且测试它是否有效,接下来,如果有效则以某种方法进行处理。如果有许多有效性测试,或者如果它们都很复杂,那么 continue 语句就非常有用了。循环将类似于下面这样:(大概就是这条不行,重新开始测下一条,如果全都可以,那么可以全部都执行到底)
for (; ;){读入数据;if (数据的第一条测试失败)continue;if (数据的第二条测试失败)continue;…if (数据的最后一条测试失败)continue;处理数据;} //作为注释的开头而不是/*,并且没有*/作为注释的结尾 这种写法在标准C中是不合法的。用//作为注释的开始是 C++的方式,有一些 C语言编译器也支持。然而,另外一些编译器可能并不支持这种方式,于是程序就成了不可移植的程序,因此应尽量避免使用//。函数 exit()的作用(还不知道怎么获得它的返回值) 终止整个程序的执行,强制返回操作系统,并将 int 型参数 code 的值传给调用进程(一般为操作系统)。当code 值为 0 或为宏常量 EXIT_SUCCESS 时,表示程序正常退出;当 code 值为非 0 值或为宏常量EXIT_FAILURE 时,表示程序出现某种错误后退出。下面两种情况适合使用goto 语句: 跳向共同的出口位置,进行退出前的处理工作跳出多重循环的一条捷径结构化程序设计关注的焦点 程序化程序设计关注的焦点是程序结构的好坏有无 goto 语句,并不是程序结构好坏的标志,限制和避免使用 goto 语句,只是得到结构化程序的一种手段,而不是目的。所谓的“好”程序是指“好结构”的程序,即“结构清晰、容易阅读、容易修改、容易验证”。一旦效率与“好结构”发生矛盾,那么宁可在可容忍的范围内降低效率,也要确保好的结构。如何获得好结构的程序 尽量避免使用 goto 语句。采用顺序、选择和循环三种基本结构作为程序设计的基本单元,用这三种基本结构编写的程序在语法结构上具有如下4 个特性:只有一个入口。只有一个出口。无不可达语句,即不存在永远都执行不到的语句。无死循环,即不存在永远都执行不完的循环。break语句练习 /*读入5个正整数,并显示,当程序读入数据为负数时,立即终止*/改为continue之后,可以发现当输入数字为负数,则跳过后面的语句开始新的循环。break是直接跳出循环了。#include <stdio.h>int main(){for(int i=0;i<5;i++){scanf("%d",&i);if(i<0) break;else{printf("%d\n",i);}}} 韩信点兵(控制流程的方法) 标志变量(flag)goto (要配合end: ;注意冒号后面还有个空格)breakexit(0)(表示如果正确退出则返回0,exit(1)表示正确退出则返回1)#include <stdio.h>#include <stdlib.h>int main(){int num;int find=0;//for(int num=1;!find;num++){for(int num=1; ;num++){if(num%5==1&&num%6==5&&num%7==4&&num%11==10){printf("韩信有%d个兵",num);//break;//goto end; //exit(0);注意配合stdlib.h的头文件//find=1; }}//end: ;} 猜数游戏 随机函数rand(),产生[0,RAND_MAX]间的随机数,RAND_MAX在stdlib.h中定义,不大于双字节整数的最大值32767 #include <stdlib.h>magic = rand(); 产生[0,b-1] 之间的随机数magic = rand()%b; 产生[a,a+b-1] 之间的随机数magic = rand()%b + a; 随机函数srand(),为函数rand()设置随机数种子,使产生的随机数“随机化” ,通过键入随机数种子,产生[1,100]之间的随机数scanf("%u", &seed); srand(seed); magic = rand() % 100 + 1; 改用系统时间作为随机数种子更好 #include <time.h> srand(time(NULL)); magic = rand() % 100 + 1;函数time()取得系统时间的方法有两种:函数参数,函数返回值(系统时间为从1970年1月1日0时0分0秒到time函数运行的那一刻所经过的时间的秒数) 使用NULL作为函数参数,使其不具备相应功能,仅能从返回值取得系统时间,便于将函数写到表达式中。
【例题解析】通过本例讲解条件控制的循环。通过调用函数 time()读取计算机的时钟值,并把该值设置为随机数种子。使每次运行程序计算机所“想”的数不一样。函数 time()返回以秒计算的当前时间值,即一个代表时间的字符串,使用 NULL 作为 time()的参数可使其不具有此功能。
/*要求键入一个数,以确定随机数范围,magic=rand()%b+1;//产生1到b的之间的随机数。并确定最多能猜几次。 */ #include <stdio.h>#include <stdlib.h>#include <time.h>int main(){int b;printf("请输入1到你想猜的数字的范围:例如1-100,请输入100\n"); scanf("%d",&b);srand(time(NULL));int magic=rand()%b+1;//产生1-b的之间的随机数 int guess;int flag=0;int count=0;int n;printf("请输入最多能猜几次\n"); scanf("%d",&n);printf("正确答案是%d",magic); for(int i=1;i<=n;i++){scanf("%d",&guess);if(guess<magic){printf("小了\n"); count++;}else if(guess>magic){printf("大了\n"); count++;} else{flag=1; count++;printf("恭喜你猜对了!你猜了%d次就猜对了!\n",count); }}if(!flag){printf("你已经猜了%d次,还没猜对,不能再猜了\n",count); printf("正确答案是%d",magic); }}自定义最多猜几次
自定义最多猜3次,3次都没猜对的情况:
如果用 scanf 输入用户猜测的数据时,如果用户不小心输入了非法字符,如字符 a,那么程序运行就会出错,为避免这样的错误发生,请修改程序。如果 scanf()返回值不等于应该读入的数据项数,说明输入的数据项数和格式(包括输入格式错误、存在非法字符、无数据 可读等)有误,利用 while 循环让用户重新输入数据,但是用户重新输入数据之前必须先清除输入缓冲区中的内容。
#include <stdio.h>#include <stdlib.h>#include <time.h>int main(){int b;printf("请输入1到你想猜的数字的范围:例如1-100,请输入100\n"); scanf("%d",&b);srand(time(NULL));int magic=rand()%b+1;//产生1-b的之间的随机数 int guess;int flag=0;int count=0;int n;int ret;//保存scanf的返回值printf("正确答案是%d\n",magic); while(!flag){ret=scanf("%d",&guess);while(ret!=1){while(getchar()!='\n');//等价于fflush(stdin);printf("请猜一个数字\n");ret=scanf("%d",&guess);}if(guess<magic){printf("小了\n"); count++;}else if(guess>magic){printf("大了\n"); count++;} else{flag=1; count++;printf("恭喜你猜对了!你猜了%d次就猜对了!\n",count); }}}每次运行程序可以反复猜多个数,直到操作者想停止时才结束。(改成while循环,用标志结束循环) #include <stdio.h>#include <stdlib.h>#include <time.h>int main(){int b;printf("请输入1到你想猜的数字的范围:例如1-100,请输入100\n"); scanf("%d",&b);srand(time(NULL));int magic=rand()%b+1;//产生1-b的之间的随机数 int guess;int flag=0;int count=0;int n;int ret;//保存scanf的返回值char react;//是否要继续? printf("正确答案是%d\n",magic); while(!flag){ret=scanf("%d",&guess);while(ret!=1){fflush(stdin);printf("请猜一个数字\n");ret=scanf("%d",&guess);}if(guess<magic){printf("小了\n"); count++;}else if(guess>magic){printf("大了\n"); count++;} else{flag=1; count++;printf("恭喜你猜对了!你猜了%d次就猜对了!\n",count); }if(!flag){printf("想继续吗?Y/y或N/n\n"); scanf(" %c",&react);if(react=='y'||react=='Y') {printf("请猜:"); continue;}else break; }}printf("The game is over!\n");}
测试:你想继续吗,y则继续并提示“请猜”,n则结束直接break;
【实验任务】 小学生 计算机辅助教学系统计算机在教育中的应用常被称为 计算机辅助教学(Computer-Assisted Instruction,CAI)。请编写一个程序来帮助小学生学习乘法。参考本章介绍的猜数游戏(例6.7、例6.11和例6.12)程序,按下列任务要求以循序渐进的方式编程。
任务1:程序首先随机产生两个1~10之间的正整数,在屏幕上打印出问题,例如:6 * 7 = ? 然后让学生输入答案。程序检查学生输入的答案是否正确。若正确,则打印"Right!",然后问 下一个问题;否则打印"Wrong! Please try again.",然后提示学生重做,直到答对为止。 任务1+2:在任务1的基础上,当学生回答错误时,最多给三次重做的机会,三次仍未做 对,则显示"Wrong! You have tried three times! Test over!",程序结束。 #include <stdio.h>int main(){int a,b,c;//分别保存学生输入的两个运算数和运算结果int flag=0;int count;//计数猜了几次scanf("%d %d",&a,&b);printf("%d * %d = ?\n",a,b);scanf("%d",&c);while(!flag&&count<4){//只能猜3次,当count=4时不满足条件退出循环if(a*b==c){printf("Right!");flag=1;//如果猜对了就退出循环}else{printf("Wrong! Please try again.");scanf("%d",&c);count++;if(count>3)printf("Wrong! You have tried three times! Test over!");}}}全都猜错了,那么退出测试
猜对了
任务1+3:在任务1的基础上,连续做10道乘法运算题,不给机会重做,若学生回答正确,则显示"Right!",否则显示"Wrong!"。10道题全部做完后,按每题10分统计并输出总分,同时为了记录学生能力提高的过程,再输出学生的回答正确率(即正确题数除以总题数的百分比)。 #include <stdio.h>int main(){int a,b,c;int count;//计数学生对了几道题 int n=3;for(int i=1;i<=n;i++){printf("请输入两个操作数\n");//不提示一下,我自己都不知道下一步该干嘛了 scanf("%d %d",&a,&b);printf("%d * %d = ",a,b);scanf("%d",&c);if(a*b==c){printf("Right!\n");count++;}else{printf("Wrong!\n ");}}printf("你得了%d分,你的正确率是:%d%%",10*count,100*count/n);}做了3次,对了两道题错了一道题,得到了总分和正确率
任务3+4:在任务3的基础上,通过计算机随机产生10道四则运算题,两个操作数为1~10之间的随机数,运算类型为随机产生的加、减、乘、整除中的任意一种,不给机会重做,如果学生回答正确,则显示"Right!",否则显示"Wrong!"。10道题全部做完后,按每题10分统计总得分,然后打印出总分和学生的回答正确率。 #include <stdio.h>#include <stdlib.h>#include <time.h>int main(){int a,b,c;char op;//运算符 int count=0;//计数学生对了几道题 int n=3;//总共要做几道题 int r=3;//操作符随机数的范围 rand()%3意思是随机0到3的数字 用在case里面随机选操作符int d=10;//随机选择1到10之间的数,作为操作数 int answer;//标准答案 for(int i=1;i<=n;i++){//printf("请输入两个操作数\n");//不提示一下,我自己都不知道下一步该干嘛了 //scanf("%d %d",&a,&b);//printf("%d * %d = ",a,b);//scanf("%d",&c);a=rand()%d+1;b=rand()%d+1;switch(rand()%r){case 0: op='+';answer=(a+b) ;break;case 1: op='-';answer=(a-b) ;break;case 2: op='*';answer=(a*b) ;break;case 3: op='/';answer=(a/b) ;break;}printf("%d%c%d = ",a,op,b);scanf("%d",&c);if(answer==c){//比对标准答案 printf("Right!\n");count++;}else{printf("Wrong!\n ");}}printf("你得了%d分,你的正确率是:%d%%",10*count,100*count/n);}测试了全对的情况,可以正确得到算式,可以判断正确答案
测试了错误的情况
任务5:在任务4基础上,为使学生通过反复练习熟练掌握所学内容,在学生完成10道运算题后,若学生回答正确率低于75%,则重新做10道题,直到回答正确率高于75%时才退出程序。(本例中改为5道题做测试60%正确率为界,比较方便) #include <stdio.h>#include <stdlib.h>#include <time.h>int main(){int a,b,c;char op;//运算符 int count=0;//计数学生对了几道题 int n=5;//总共要做几道题 int r=3;//操作符随机数的范围 rand()%3意思是随机0到3的数字 用在case里面随机选操作符int d=10;//随机选择1到10之间的数,作为操作数 int answer;//标准答案int i=1; int flag=1;//用来判断是否做够了n次 int flag2=1;//用来区分这个人第一次就做的超过60的正确率 和重做才超过60 do{a=rand()%d+1;b=rand()%d+1;switch(rand()%r){case 0: op='+';answer=(a+b) ;break;case 1: op='-';answer=(a-b) ;break;case 2: op='*';answer=(a*b) ;break;case 3: op='/';answer=(a/b) ;break;}printf("%d%c%d = ",a,op,b);scanf("%d",&c);if(answer==c){//比对标准答案 printf("Right!\n");count++;//计数做对了几道题}else{printf("Wrong!\n ");}if(i==n&&(100*count/n)<60){printf("你的正确率低于60%%,请继续做10题直到你的正确率高于60%\n");flag2=0; count=0;i=0;}if(((100*count/n)>60)&&i==n) flag=0; //如果正确率高于60而且题数做了n道就停止循环i++;//计数总共做了几道题}while(flag);if(flag2==0){printf("恭喜!你的正确率终于高于60%了\n");}else{printf("恭喜!你第一次做正确率就高于60%了\n");}}
测试了正确率低于60的情况,正确的重新做题5道,并计算新的正确率此时全对,但当答对了4道时已经大于百分之六十正确率时并未退出循环,因为加了条件i==n才能结束循环
用flag2来区分第一次就高于60和重做才60的情况,测试正确
任务6:开发一个CAI系统所要解决的另一个问题是学生疲劳的问题。消除学生疲劳的一种办法就是通过改变人机对话界面来吸引学生的注意力。在任务5的基础上,使用随机数产生函数产生一个1~4之间的随机数,配合使用switch语句和printf()函数调用,来为学生输入的每一个正确或者错误的答案输出不同的评价。对于正确答案,可在以下4种提示信息中选择一个进行显示: Very good! Excellent! Nice work! Keep up the good work! 对于错误答案,可在以下4种提示信息中选择一个进行显示: No. Please try again. Wrong. Try once more. Don’t give up! Not correct. Keep trying. #include <stdio.h>#include <stdlib.h>#include <time.h>int main(){int a,b,c;//连个随机数,一个随机符号int pingjia;//随机评价语句 1到4char op;//运算符 int count=0;//计数学生对了几道题 int n=5;//总共要做几道题 int r=3;//操作符随机数的范围 rand()%3意思是随机0到3的数字 用在case里面随机选操作符int d=10;//随机选择1到10之间的数,作为操作数 int answer;//标准答案int i=1; int flag=1;//用来判断是否做够了n次 int flag2=1;//用来区分这个人第一次就做的超过60的正确率 和重做才超过60 do{pingjia=rand()%4+1;a=rand()%d+1;b=rand()%d+1;switch(rand()%r){case 0: op='+';answer=(a+b) ;break;case 1: op='-';answer=(a-b) ;break;case 2: op='*';answer=(a*b) ;break;case 3: op='/';answer=(a/b) ;break;}printf("%d%c%d = ",a,op,b);scanf("%d",&c);if(answer==c){//比对标准答案 switch(pingjia){case 4: printf("Very good!!\n") ;break;case 1: printf("Excellent!!\n") ;break;case 2: printf("Nice work!!\n") ;break;case 3: printf("Keep up the good work!!\n") ;break;}count++;}else{switch(pingjia){case 4: printf("No. Please try again.\n") ;break;case 1: printf("Wrong. Try once more.\n") ;break;case 2: printf("Don’t give up!\n") ;break;case 3: printf("Not correct. Keep trying.\n") ;break;}}if(i==n&&(100*count/n)<60){printf("你的正确率低于60%%,请继续做10题直到你的正确率高于60%\n");flag2=0; count=0;i=0;}if(((100*count/n)>60)&&i==n) flag=0; i++;//统计做了几次题了,因为count是用来计数对了几道题的,所以需要单独的i来做总共做了几道题的计数}while(flag);if(flag2==0){printf("恭喜!你的正确率终于高于60%了\n");}else{printf("恭喜!你第一次做正确率就高于60%了\n");}}
第六章