C语言程序设计第五次作业
一:改错题:
错误一:输入所给代码段,执行编译命令,编译错误,错误信息如下:
错误信息:
该错误信息指向第十三行:
错误原因:经过检查,发现该行的for语句后多出一个“;”(分号),导致编译器无法识别该语句的断句,出现编译错误。
改正方法:将多余的分号删去。
错误二:继续编译,提示编译错误,错误信息如下:
错误信息:
该错误指向第17行。
错误原因:13行的for语句后有多条语句,但是for后并未添加“{}”(大括号)。
改正方法:分别在第13,17行上添加“{}”(大括号)。
错误三:继续编译,提示错误信息如下:
错误信息:
错误原因:经过回头检查,发现在for语句的圆括号中,分别表示fahr初值,判断范围以及步长的语句之间的分隔符为“,”(逗号),而非“;”(分号)。
改正方法:将使用错的 符号改为“;”(分号)。
编译成功,如图:
错误四:运行程序,输入样例数据“32 35”,发现对应的值输出不符合预期,如图:
错误原因:该错误为典型的输出0错误,根据之前总结,可以初步判定为数型的声明以及计算过程中的数型转换错误,经过检查,首先发现第16行的输出语句中对应华氏度数的格式化输出符号有问题,在声明时以及输出时均为int型,但是输出时却格式化为浮点型。如图:
改正方法:将对应华氏度的输出符号改为对应整形输出的“%3d.
错误五:继续运行,输入样例“32 35”,结果如下:
仍不符合预期,继续按照数型的思路去查错。
错误原因:经过查证,发现温度转换的计算式有误,如图:
原题设应为c = 5×(f-32)/9。
改正方法:将计算式改正,如图:
错误六:样例数据不变,输出结果如下:
比预期多出数组数据。
错误原因:原题设为每次循环,华氏度的温度增加2,而在源代码的for语句中,每次循环华氏度只增加1.
改正方法:将循环后华氏度的增量改变为+2。如图:
再次输入样例数据“32 35”,结果如图:
该组数据符合题设,再次输入另一组数据“40 30”,结果如图:
符合预期。
为保证临界值的准确性,输入“32 32”,结果如图:
符合预期。
输入“34 34”,结果如图:
符合预期。
符合预期,改正结束。
附上改正后的代码:
#include <stdio.h>
int main(void)
{
int fahr , lower, upper; /* fahr表示华氏度 */
double celsius; /* celsius表示摄氏度 */
printf("Enter lower:");
scanf("%d",&lower);
printf("Enter upper:");
scanf("%d",&upper);
printf("fahr celsius
"); /* 显示表头 */
/* 温度转换 */
for (fahr = lower ;fahr <= upper;fahr += 2)
{
celsius = 5 * (fahr - 32.0) / 9 ;
printf(" %3d %6.1f
", fahr, celsius);
}
return 0;
}
二:学习总结:
1:根据所给源代码总结:
1)首先运行程序,按序输入1~10,运行结果如下:
2)实验分析:
①首先定义三个整形变量,分别存储用户输入数据,奇数的数目,偶数的数目。
②进入for循环,
i= 1,判断条件为真。进入循环体。
③用户输入一个整型变量num。此时笔者输入的值为1.
④进入选择语句。判断输入的值能否被2整除。
⑤判断结果为假,执行else语句。
即odd++,此时odd的值为1.
⑥回到for循环。i=2.条件为真。
⑦继续输入数据,笔者输入2.此时num = 2.
⑧进入选择语句,判断为真,执行even++,此时even = 1.
.....................................
⑨输入十次后,i = 11,不符合for循环的条件,执行for循环后面的语句。输出even以及odd的值。就笔者输入的数值而言,此时odd,even均=5.
程序终止。
3)该程序的主要功能是用户输入10个整型数据,由系统判断该数值是奇数还是偶数,10个数输入完毕后统计奇数与偶数的个数。
2:增量运算符:
(1)运行所给程序,结果如下:
单独分析该程序,只是单纯输出i,j的值,其中的自增运算符不涉及其他运算,因此在本例中增量运算符不构成影响,但是增量运算符的前缀与后缀格式实际上是影响计算的。
(2)运行程序2:
①将所给源代码输入编译器并执行,结果如图:
②运行过程分析:
本案例说明增量运算符的前缀与后缀影响运算过程与结果。该程序首先声明两个整型变量i,j,并赋初值2.执行第一条输出语句,由于i的增量运算符为后缀形式,因此先执行输出语句,再对i执行增量操作层,所以b的值输出为2,即为增量前的值。而j的输出语句中,j为前缀形式,因此首先对j执行增量操作,再执行输出命令,因此j输出的值为3,而实际上在计算机内部,i与j此时的值都为3,下面稍微修改程序,用以验证。
修改后的代码如下:
#include <stdio.h>
int main()
{
int i,j;
i = 2;
j = 2;
printf("%d
",i++);
printf("%d
",++j);
printf("%d %d",i,j);
return 0;
}
笔者在最后又增加了一条输出语句,且为执行其他操作,用以观察i,j实际的值。运行修改后的程序,结果如下:
可以看到,i,j的值均为3,证明上述分析正确。
下面再给出一个与运算有关的更简单的程序,如下:
#include <stdio.h>
int main()
{
int i = 2;
i = i++ * 2;
printf("i = %d
",i);
return 0;
}
首先给i赋初值2.此时增量运算符为后缀形式,运行结果如下:
此时i的值为4,紧接着修改程序,将“i++”改为“++i”,即将后缀改为前缀。
再次运行,结果如下:
可以发现,在i的初值不变的情况下,i的运算结果出现了不同。因此较为简明的解释为,前缀形式的增量/减量运算符,在进行运算时,先对被赋予增量/减量的变量的值执行增/减量操作再执行后续运算,而后缀则相反,先执行其他运算,再将变量的值执行增/减量操作。因此在确定增/减量运算时一定要合理分析其前/后缀形式的使用。
3)关于循环语句的大括号:
①首先按序执行所给代码,之后加以分析总结。
程序1:结果如图:
输出为一行5个星号。
程序二:结果如图:
输出同样为一行5个星号。
程序3:结果如图:
输出为五行各1个星号。
程序4:结果如图:
输出为一行5个星号。
④下面给出分析:
首先分析程序1和2,1和2的主要区别在于缩格不同,但是再通过结果分析,结果上二者完全相同,效果完全相同,因此证明循环体的认定与缩格并没有关系。
紧接着结合3与4,这二者的区别在于大括号括起的位置不同。但是输出结果完全不同,可以从执行过程分析。以第1次循环为例。执行顺序为先进入循环的判断部分,i = 1满足条件,进入循环,执行星号与换行的输出语句,之后找到大括号,并判断该次循环结束,因此每次循环实际上都输出了一个星号与一个换行符。
之后是4的分析,仍然以第一次循环为例,i的值为1,进入循环判断,判断为真,进入循环体内,执行星号的输出语句,检测到大括号,认为本次循环结束,并重复执行五次,输出五个星号,最后一次i > 5,条件判断为假,跳出循环,执行for循环后的换行符的输出语句,输出一个换行符。
因此从数值上讲,1输出了五个星号与五个换行符,而4输出了五个星号与1个换行符。因此可以证明,循环体的判定与缩格无关,而与大括号有关。系统在进入循环时,会以大括号为界来实现循环体的判定。
因此,单从循环体的判断而不是输出目的而言,1和2都是错误的,3和4都是正确的,只不过实现目的不同。因此,循环体的判定总结而言就是通过大括号的配对来判定。即寻找for后的左大括号与循环体后的右大括号。
4)其它总结:
首先关于本章的内容,实际上可以总结的大多数都在上面的案例中。但是有一些细节是总结不完的。
首先是复合运算符,实际上这种运算的本质是将赋值运算与算数运算复合的结果。参照博文:
http://blog.csdn.net/lyh__521/article/details/49622601
关于其优点最显著的两点在于其可以将同一变量重复使用,此外,当算数表达式较长且涉及较多变量时,太长太多的算数运算符显然显得繁琐以及拖沓,因此合理使用复合运算符,能显著提高代码的可读性以及简洁性。
其次是关于逗号运算符。逗号运算符的基本性质有两条,第一是其运算优先级为C语言中最低的,第二,其右结合性,逗号运算符的运算过程为将从左至右最后一个逗号后的值作为 整个表达式的值输出,下面给出一段代码:
#include <stdio.h>
int main(void)
{
int num1, num2 , num3;
num2 = 2;
num3 = 3;
num1 = 18+ (num2+2 * 2,num3+4);
printf("%d",num1);
return 0;
}
其中就用到了逗号运算符,且在括号中,还涉及了算数运算以及优先级较高的乘法运算。结果如下:
最终结果为25.
可以看到,括号中的“num2 + 2 * 2”就像是凭空消失了一般,实际上并不是,只是因为逗号运算符的结合性以及只取最右表达式的值的特性,使得整个括号的值为“num3 + 4”,即等于7,因此结果为18 + 7 =25.
正因为这种性质,使逗号运算符在顺序求值上有很大的用途。也希望通过这个例子使同学更加理解这种运算符的运算规则。
最后是循环结构的使用方面。
第一,循环条件的使用实际上是十分广泛的,特别是对于一些涉及重复操作的实际问题,例如输入学生成绩计算均值以及及格人数的问题。若是只有五个同学还好,不使用循环结构的情况下首先定义五个整形变量存放学生的成绩,之后定义一个int型变量存放五位同学成绩的总和,之后定义一个int型变量来存放及格人数,之后是定义一个double型变量存放均值.............................
五个还好,那么十个呢...100....1000000........
显然定义那么多变量并不现实。这种情况下就能极大地体现出循环结构的优势,即变量复用,重复操作的快捷性。
因此,回到开头,for循环的适用范围即为重复操作较多且不含更多变数的情况。
实际上for循环也有一些妙用,下面给出本次作业中的求学生成绩的均值及及格人数的改版来说明:
#include<stdio.h>
int main(void)
{
int score = 0,sum = 0,pass = 0,i = 0;
for(;;) //此处判断循环的条件为空
{
scanf("%d",&score); //输入成绩
if(score < 0) //判断输入成绩是否小于0,此处以成绩小于0为结束循环的信号
{
break;
}
else
{
sum += score;
if(score >= 60) //计算及格人数
{
pass++;
}
i++;
}
}
printf("average = %.1f
",(double)sum / i);
printf("count = %d",pass);
return 0;
}
首先可以看到,在本案例中的for循环的判断语句中,是不存在任何语句的,这就意味着在循环体内如果不添加结束循环的条件的话,这个循环是会无限进行的,但是笔者在循环体内增加了判断分数是否小于0的选择结构,即在此以小于0为结束循环的“暗号”,因此这个程序就实现了可以计算任意多个学生平均分以及及格人数的功能,所以适当利用这种手法,可以获得强大的功能,只不过这种手法的使用需要注意的一点在于for后的括号内虽然可以没有语句,但是表示分隔的两个分号一定不能丢,一定不能丢,一定不能丢!!!!!!!!!
(3)实验总结:
一:输入学生数量以及成绩求成绩均值与及格人数:
1:流程图:
2:源代码:
#include<stdio.h>
int main(void)
{
int score = 0,count = 0,i = 1,sum = 0,pass = 0;
scanf("%d",&count);
if(count == 0 )
{
sum = 0,pass = 0;
}
else
{
for(i = 0;i < count;i++)
{
scanf("%d",&score);
sum += score;
if(score >= 60)
{
pass++;
}
}
}
printf("average = %.1f
",(double)sum / i);
printf("count = %d",pass);
return 0;
}
3:实验分析:
该题主要使用了简单的for循环结构以及if else选择结构,总体难度较低。笔者并未遇到太多困难,只不过要说明的地方在于几个数型转换的问题,在变量较多又不适合全部定义为double型的情况下,可以适当使用强制转换来达到目的。另一点在于除0的问题,笔者有许多同学都出现过这样的错误,因此在某个变量(本题中为i)的值可能为0且做分母时,一定要判断其是否存在直接被使用的风险,在本题中保险起见笔者将其初始化为1,从而避免这种情况的发生。
虽然在代码阶段笔者未遇到错误,但是在流程图的编辑阶段却出现了错误。
错误1:笔者将流程图制作完成后,输入样例数据“5 77 54 92 73 60”,前期并未出现问题,但是当笔者输入5个成绩后,却发现仍在提示输入,进入死循环。
错误原因:在循环体内未添加i的自增函数,如图:
改正方法:在循环体的最后添加“i = i + 1”,确保每一次循环i的值会增加1.
4:本题提交列表:
二:判断到底是不是太胖了:
1:流程图:
2:源代码:
#include<stdio.h>
#include<math.h>
int main(void)
{
int count= 0,i = 0;
double high = 0.0,weight = 0.0,standard = 0.0;
scanf("%d",&count);
for(i = 1;i <= count;i++)
{
scanf("%lf%lf",&high,&weight);
weight /= 2;
standard = (high - 100) * 0.9;
if(fabs(standard - weight) < standard * 0.1)
{
printf("You are wan mei!
");
}
else if(standard - weight < 0)
{
printf("You are tai pang le!
");
}
else
{
printf("You are tai shou le!
");
}
}
return 0;
}
3:实验分析:
本题主要使用for循环以及if else选择结构的使用。实际上与前几题相近,只不过这道题上比较使人疑惑的地方在于if else的选择条件上。
错误1:笔者输入样例数据“3 169 136 150 81 178 155”,结果如下:
可以看到,第三组数据得到的结果不符合题意,因此回头检查。
错误原因:经过检查,发现在判断胖和瘦的选择语句中的条件有误,如图:
该处的判断实际上已经不需要加上绝对值,只需判断标准体重减去实际体重的值是否大于0即可,若大于零,则证明实际体重小于标准体重,且偏差值是大于10%的。
改正方法:将绝对值符号去掉。
4:本题提交列表:
三:统计学生成绩:
1:流程图:
由于Reptor中没有switch结构,因此由if else结构代替。
2:源代码:
#include<stdio.h>
int main(void)
{
int count = 0,A = 0,B = 0,C = 0,D = 0,E = 0,i = 0,score = 0;
scanf("%d",&count);
for(i = 1;i <= count;i++)
{
scanf("%d",&score);
switch(score / 10)
{
case 10:case 9:A++;break;
case 8:B++;break;
case 7:C++;break;
case 6:D++;break;
default:
E++;
}
}
printf("%d %d %d %d %d",A,B,C,D,E);
return 0;
}
3:实验分析:本题实际上是前几次练习的又一次改版,只不过加入了for循环的结构,并不存在太大问题。因此...好吧...真的没出错.........
4:本题提交列表:
四:找出最小值:
1:流程图:
此处用int型最大值取代C语言中的“INT_MAX”。
2:源代码:
#include<stdio.h>
#include<limits.h>
int main(void)
{
int num = 0,n = 0,min = INT_MAX,i = 0;
scanf("%d",&n);
for(i = 1;i <= n;i++)
{
scanf("%d",&num);
if(num <= min)
{
min = num;
}
}
printf("min = %d",min);
return 0;
}
3:实验分析:
本题主要还是使用for循环与if else结构,虽然仍然是之前练习的改编,但是显然简洁了许多,也体现出了for循环处理多数据重复操作问题的优越性。虽然笔者并未遇到问题,但是有一点需要说明,关于“limits.h”。
使用该库函数的目的是保证无论用户输入数值多大,都能保证输入的值能被存储到下一循环中去比较的变量中去,因此省去不必要的数值交换过程。关于错误分析...好吧...这个真的没有...
4:本题提交列表:
四:博客互评:
刘畅:http://www.cnblogs.com/LLIU/p/7810044.html
第八题的实验总结只写了第一点,后面没有了。
陈魔(真的不不知道同学的名字,希望下次注明一下):
http://www.cnblogs.com/liumiaomiao520/p/7795587.html
(1)第一题的错误都用红笔标注出来啦,很清晰明了。
(2)第二题有的图片格式不正确,导致没有显示出来。
(3)第二题总结的很完整,很完善,分析的有条例。
刘恺烜:http://www.cnblogs.com/liukaixuan/p/7812027.html
同学你的一个图片没有加载出来。
你在修改错误时将错误都用红笔划了出来。而且你将比较大的流程图切割开再在网页上拼接上使得图片更容易看清。这些都是我没有做到应该向你学习的。
许天笑:http://www.cnblogs.com/snxtx/p/7812139.html
我觉得你写的这个都比较清晰,而且解释的比较详细,每一点都很详细,每道题的实验分析说的很明确,向你学习。
郭玉霖:http://www.cnblogs.com/HBQ521/p/7803633.html
感觉每次你写的很好,值得学习,。不出毛病。
范凯华:http://www.cnblogs.com/fkh1/p/7812032.html
内容详细,知识点总结全面,排版清晰。
郭展旭:http://www.cnblogs.com/1234569ss/p/7801245.html
错误改正较为细致,对题目边界值的测试较好,避免错误的发生。课下总结较好,在阅读博文链接后学习到了很多,作业质量很高,值得学习。