• C语言程序设计第四次作业


    C语言程序设计第四次作业

    一:改错题

    输入所给源代码并编译,提示错误信息如下:

    (错误一)错误信息指向第13及17行,返回检查。
    错误原因:第13行关于面积的计算式的sqrt数学函数缺少“)”,导致编译器无法将括号正确配对。
    改正方法:补齐缺少的“)”。

    (错误二)继续编译,再次提示错误信息,如下图:

    错误原因:if语句后缺少对应的“{}”大括号,导致逻辑关系出现问题。在此,需要提醒一点,在if后若只包含一条语句,原则上大括号可以省略,但是若是涉及多条语句,就必须要加上大括号,否则会出现如本题一样的问题。
    改正方法:补齐所缺“{}”。
    继续编译,编译成功,点击运行,并输入所给样例“5 5 3”,运行结果如下图:

    该样例输入输出正常。

    (错误三)紧接着输入第二组样例“1 4 1”,输出如下图:

    可以看到,结果显然不符合期望,经过分析,该组数据为不符合三角形构成条件的数据,因此返回检查选择语句的判断条件部分,即第11行。
    错误原因:第11行的选择语句中,三边的判断语句应为且“&&”,而不是或"||"。
    改正方法:将或“||”改为且“&&”。
    改正后,再次输入样例“1 4 1”,结果如下:

    符合预期,改正结束。

    二:学习总结:

    (1):首先是关于if以及else if,switch的区别。
    在之前的总结中我笔者也提到过这两者的一些区别,即独立性以及相关性。对于if而言,每一个if都相当于一个独立的系统,即程序执行时,每次遇到if,都将执行一次判断,若程序中有多个if,相当于多个if并联,因此当使用多个if时,对于程序本身而言具有一定的风险。尤其是涉及对于取值范围的判断较多的情况。而else if相当于“否则”,并且包含在对应的if之后。if和其配对的else if实际上在一定程度上是互斥的,参照该文:

    https://www.zhihu.com/question/27797637?sort=created

    再者可以参照第三次作业中的总结之一:

    #include<stdio.h>
    
    int main(void)
    {
         int ele = 0;
         double cost = 0.0;
         scanf("%d",&ele);
         if(ele >= 0&&ele <=50)
         {
         cost = 0.53 * e;
         printf("cost = %.2f",cost);
         }
         if(ele > 50)            //此处笔者将else if改为if 
         {
         cost = 50 * 0.53 + (ele - 50) * 0.58;
         printf("cost = %.2f",cost);
         }
         else
        {
         printf("Invalid Value!");
         }
    
        return 0;
    
    }
    

    这里就是一个典型案例,当笔者输入任意小于50的值时,伴随着对应的电费的输出,同时对应非法数据提示的语句也被输出,原因就在于if的连用。详情可以参照第三次作业的其它总结:

    http://www.cnblogs.com/Reloaded/p/7719971.html

    以语言叙述,就是当if满足时,该独立系统执行完毕,若if后存在与其配对的else if,也不执行。当if不满足,开始按序执行下一条else if,可以理解为否则。若else if满足,系统结束,进入下一语句。else if不满足,继续在系统内执行下一条else if,若都不满足,执行else。但else并非必需。可以理解为,某if系统内不存在满足条件的语句,该系统结束,执行之后的语句。
    之后是关于switch与if else语句的区别:
    switch语句在C语言中的应用实际上是非常广泛和灵活的。首先是关于switch本身,是一种多选择结构,可以根据所给的变量来进行逐步判断,再给出与条件对应的语句。虽然和if相比同为选择结构,但是区别也很明显。其一是对应数值类型不同。if的判断框中,数据类型较为广泛,几乎可以覆盖所有的类型数值,尤其是对于取值范围的判断,其便捷性和灵活性要远高与switch case,因为case后只能为常量,只能为常量,只能为常量!!!这是区别之一。
    其次是执行效率问题,当选择较少时,if的执行效率要高于switch case结构,但当选择较多时,则需要使用switch case结构,其中涉及的算法问题暂不深究,附参考博文链接:

    http://www.cnblogs.com/pureEve/p/6564012.html

    另一区别在于其比较条件的方式不同,对于if else结构实际上应用的是比对法,即将所给值与条件所给的范围或条件进行比对,而switch case结构实际上是一种枚举机制,因此省略了许多多余的计算过程,这也就解释了多选择结构中,switch语句的效率要高于if else的原因。参考博文链接:

    http://www.cnblogs.com/bluesky365/p/5631517.html

    关于例证,可以给出两段此次作业中的代码段来加以区分:

    首先是成绩的分档问题:实际上两种结构都可以使用,但是在不考虑技巧性的情况下,先给出if语句写出的代码段:

    #include<stdio.h>
    int main(void)
    {
        int mark = 0;
        scanf("%d",&g);
        if(mark >= 90)
        {
    	    printf("A");
        }
        else if(mark >= 80)
        {
    	    printf("B");
        }
        else if(mark >= 70)
        {
    	    printf("C");
        }
        else if(mark >= 60)
        {
    	    printf("D");
        }
        else
        {
    	    printf("E");
        }
        return 0;
    
    }
    

    之后是switch结构:

    #include<stdio.h>
    int main(void)
    {
        int mark = 0;
        scanf("%d",&mark);
        switch(mark)
        {
    	    case 100: case 99: case 98:.......................  //此处省略 
    	    printf("A");
    	    break;
    	    case 89: case 88: case 87:....................    //此处省略
    	    printf("B");
    	    break;
        }
        return 0;
    
    }
    

    可以看到,若是在涉及常数较多的情况下,再用switch的枚举法显然很繁琐且不现实,若是涉及到更多的数据,穷举法显然无法实现,因此相比if else结构,这实际上也是适用范围上的不同点之一。

    总结而言,if相对于else if相当于一个较大的集合,else if实际上是if的几个分支,关联性较强。而switch语句与其相比,虽同为选择结构,但差异也较多。其一是其条件的取值范围,if else在取值上更加灵活,但是对于条件的判断要求考虑的要多一些,尤其是在临界值附近,要尤为谨慎。而switch虽然在取值上较为严苛,但是当处理较少选择条件以及处理常量时,其便捷性以及简洁性又远高于if else结构,因此二者应当适当选择,可以取得最好的效果。
    (2)其他总结

    首先是关于字符与字符串,我认为这两者在使用时要严格加以区分,特别是在输入语句中,要区分%c 与 %s,因为%c每次只读入一个字符,因此当输入的字符大于一个字符时,多余部分会丢失,因此要多加小心。

    另外一点,是要时刻注意使用字符输入输出语句时,要留意缓存区中是否有残留的字符。下面以笔者遇到的一个问题为例:

    笔者本来是想制作一个能计算任意多个值的平均值的程序,当用户输入数值之后,系统会询问用户是否继续输入数值,当选择“y”(即yes)时,系统允许用户继续输入数据,若是选择“n”(即no)时,停止输入循环,并计算平均值。当制作完成后,计算部分与选择部分并没有出现问题,首先给出有问题的源代码:

    #include<stdio.h>
    int main(void)
    {
        int i = 0;
        char choice;
        double num = 0.0,degree = 0.0;
        printf("Enter you want to compute average
    ");
        for( ; ;)
        {
    	    printf("Enter your number
    ");
    	    scanf("%lf",&degree);
    	    num += degree;
    	    ++i;
    	    printf("Do you want to continue?          y/n
    ");
    	    scanf("%c",&choice);                    //此处的%c前遗漏了空格
    	    if(choice == 'n'||choice == 'N')
    	    break;
        }
        printf("The average = %.2f",(double)num / i);
        return 0;
    
    }
    

    但是当笔者多次测试后,却发现了问题。笔者依次输入“3 y 5 n”,输出如下结果:

    可以看到,当笔者最后一次选择n后,虽然输出了对应的均值,但是也输出了在循环内的语句,令笔者十分费解。进过长时间的检查仍未发现问题所在,无奈之下请教了老师,最终解决了该问题。
    首先是观察for循环内的(“Do you want to continue”)后的转义字符,本身并没有问题,之后再观察这一句下面的scanf语句,这里就是问题所在,因为笔者的%c前并未加空格,而上一句留下的 本身是以遗留在缓存区的,所以执行到scanf语句时,%c将 读入,循环再次进行,输出了不该出现的内容。因此想以这个例子说明,一定要时刻注意缓存区内的情况,这也是老师再三叮嘱的,希望同学们不会犯和我一样的错误。

    另一个典型错误出现在笔者的第三次作业中,先给出代码:

    #include <stdio.h>
    
    int main()
    {   
        int  a, b;
        scanf("%d %c", &a, &b);
        printf("a = %d, b = %c
    ", a, b);
        return 0;
    }
    

    在这个问题中,笔者的测试实际上是不完全的,笔者在此问题中以为数字相对于%c为非法数据,连续输入了两次123 123,结果如图:

    实际上第二个123未被读入的原因并非是%c不读入数字,而是因为%c只读入一个字符,因此只读入了一个“1”。在此也感谢助教老师的指点。

    另一点需要总结的是关于字符型变量的ASCII码的问题,一定要记住几个常用字符的ASCII码,例如‘A’,‘0’;以及字符型与char,int型的混合运算问题,混合运算时,实际上是将其ASCII码数值相加,再根据输出所指定的格式给出结果。
    最后是关于1与‘1’的区别。实际上这里的‘1’可以表示任意整数,应当注意的是区分二者的区别。前者为数字型常量,后者为字符型常量,本质意义是不同的。还有字符型变量的问题。
    例如“char A = 'a'”,这里的‘A’为字符型变量,它是用来保存单字符的一种变量,而‘a’就为字符型常量。还有‘a’与“a”的区别,前者为字符型变量,后者为字符串型变量,虽然只差了一个符号,但是其意义也是完全不同的,在定义时也应多加小心,希望引起注意。

    二:实验总结

    (1)比较大小的问题:

    1)流程图如下:


    2)源代码如下:

    #include<stdio.h>
    int main(void)
    {
        int num1 = 0,num2 = 0,num3 = 0,middle = 0;
        scanf("%d%d%d",&num1,&num2,&num3);
        if(num1 > num2)
        {
    	    middle = num1,num1= num2,num2 = middle;
        }
        if(num1 > num3)
        {
    	    middle = num1,num1 = num3,num3 = middle;
        }
        if(num2 > num3)
        {
    	    middle = num2,num2 = num3,num3 = middle;
        }
        printf("%d->%d->%d",num1,num2,num3);
        return 0;
    
    }
    

    3)实验分析:
    本题主要应用数值交换,以及简单的if语句连用。
    这道题实际上十分的经典,从顺序结构的数值交换延伸到现在的比较大小,虽然难度较低。但是笔者同样遇到了许多错误。
    错误一:
    笔者一开始将数值交换写入,开始运行,输入样例数据“4 2 8”,发现输出结果如下:

    显然不符合逻辑。
    错误原因:在数值交换语句的第二条即num1与num3的比较中,顺序与逻辑出现问题。如图:

    改正方法:将出现问题的语句修改,将逻辑捋顺。
    错误二:修改完成后,继续输入“4 2 8”,结果如下:

    发现输出结果是由大到小的,显然不符合题意。
    错误原因:分析题意出现问题。
    改正方法:将输出语句的变量的顺序更换。
    4)提交列表:

    (2)超速处罚问题:
    1)流程图如下:

    2)源代码如下:

    #include<stdio.h>
    int main(void)
    {
        double exceed = 0.0,speed = 0.0,limit = 0.0,ratio = 0.0;
        scanf("%d%d",&speed,&limit);
        exceed = (speed - limit) / limit;
        ratio = exceed * 100;
        if(exceed < 0.1)
        {
        printf("OK");
        }
        else if(exceed < 0.5)
        {
        printf("Exceed %.0f%%. Ticket 200",ratio);
        }
        else
        {
    	    printf("Exceed %.0f%%. License Revoked",ratio);
        }
        return 0;
    }
    

    3)实验分析:
    问题一:
    笔者一开始编译完成后,输入了几组数据,均未出现问题。但是当笔者输入临界值“150 100”时,却出现了以下结果:

    显然不符合题设要求。
    错误原因:笔者在临界条件判断时,误将等号加入判断中,如图:

    因而导致出现错误。
    改正方法:
    将等号去除。
    小总结:
    当出现浮点数的比较时,尽量不要取等,因为浮点数本身就具有一定的误差,可能会影响判断。因此要多加注意。
    4)提交列表:

    (3)加油问题:
    1)流程图如下:


    2)源代码如下:

    #include<stdio.h>
    
    int main(void)
    {
        int litre,model,choice;
        double cost;
        scanf("%d%d %c",&litre,&model,&choice);
        switch(model)
        {
    	    case 90:
    		    cost = 6.95 * litre;
    		    break;
    	    case 93:
    	        cost = 7.44 * litre;
    		    break;
    	    default:
    	        cost = 7.93 * litre;
    	    	break;	
        }
        if(choice == 'm')
        {
    	    cost *=0.95;
        }
        else
        {
    	    cost *=0.97;
        }
        printf("%.2f",cost);
        return 0;
    
    }
    

    3)实验分析:
    本题主要使用switch结构以及if else选择语句。
    错误一:笔者开始将“40 97 m”样例输入,未发现问题,但是提交时却提示部分正确,于是返回测试其它数据,输入“40 97 e”,结果如下:

    发现与“40 97 e”相同。
    错误原因:
    在最后判断用户的输入服务种类的区域,笔者误将协助所对应的折扣也输入为9.5折,导致数据出现错误。
    改正方法:将“e”对应的折扣改为0.97,即“cost *= 0.97”.
    在制作流程图时,也出现了一些意想不到的错误。
    错误二:
    笔者开始写完流程图,输入样例数据“40 97 m”,但是出现如下提示信息:

    错误原因:在判断选择是自助还是协助时,流程图内的判断框中的“choice==“m””被笔者遗漏了引号。
    改正方法:
    补全所缺引号。
    错误三:
    继续执行,样例数据不变,但是又出现了如下错误:

    错误原因:
    在reptor中,字符型变量应用“”“”(双引号)扩起,而不是C语言中的“‘’”(单引号)。
    改正方法:
    将““””(双引号)改为“‘’”(单引号)。
    4)提交列表:

    (4)12-24小时制转换:
    1)流程图:

    2)源代码:

    #include<stdio.h>
    int main(void)
    {
        int hour = 0,minute = 0;
    	scanf("%d:%d",&hour,&minute);
    	if(hour > 12)
    	{
        hour = hour -12;
        printf("%d:%d PM",hour,minute);
        }
        else if(hour < 12 || hour == 0)
        {
    	    printf("%d:%d AM",hour,minute);
        }
        else
        printf("%d:%d PM",hour,minute);
        return 0;
    
    }
    

    3)实验分析:
    本题主要使用if else语句的选择结构。以及字符型变量的输入输出。
    错误一:笔者在开始时,输入样例数据“21:11”,并未出现问题,但是提交后提示部分正确,于是返回检查。开始逐条检查临界条件“0:00”,结果如下:

    不符合题意。
    错误原因:
    对于零点的临界判断不完全,导致输出了错误的结果。
    改正方法:将零点单独写入else if判断语句中。用以增强稳定性。
    4)提交列表:

    四:博客互评链接:

    1:许天笑:

    http://www.cnblogs.com/snxtx/p/7763856.html

    2:胡展业:

    http://www.cnblogs.com/SYDneyHZY/p/7774739.html

    3:郭展旭:

    http://www.cnblogs.com/1234569ss/p/7754274.html

  • 相关阅读:
    centos下 yum安装ngix
    [转]ORACLE函数大全
    Oracle的DML语言必备基础知识
    微信公众账号开发教程
    freemarker页面如何获取绝对路径basePath
    使用intellij的svn时提示出错: Can't use Subversion command line client: svn.Errors found while svn working copies detection.
    网站地址
    如何让tomcat不记录catalina.out这个日志文件
    在centos6.7用yum安装redis解决办法
    剑指 Offer 06. 从尾到头打印链表
  • 原文地址:https://www.cnblogs.com/Reloaded/p/7753789.html
Copyright © 2020-2023  润新知