




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
译中科技大孚课程实验报告课程名称: C语言程序设计专业班级:计算机科学与技术1234班学号: U123412345姓名: OOO指导教师: O。O报告日期: OOOO年。月O日计算机科学与技术学院目录TOC\o"1-5"\h\z\o"CurrentDocument"实验1表达式和标准输入与输出实验 1\o"CurrentDocument"实验目的 1\o"CurrentDocument"实验内容及要求 1\o"CurrentDocument"自设题 12\o"CurrentDocument"实验小结 14\o"CurrentDocument"实验2流程控制实验 15\o"CurrentDocument"实验目的 15\o"CurrentDocument"实验内容及要求 15\o"CurrentDocument"自设题 29\o"CurrentDocument"实验小结 34\o"CurrentDocument"实验3函数与程序结构实验 35\o"CurrentDocument"实验目的 35\o"CurrentDocument"实验内容及要求 35\o"CurrentDocument"自设题 49\o"CurrentDocument"实验小结 53\o"CurrentDocument"实验4编译预处理实验 54\o"CurrentDocument"实验目的 54\o"CurrentDocument"实验内容及要求 54\o"CurrentDocument"自设题 67\o"CurrentDocument"实验小结 69\o"CurrentDocument"实验5数组实验 70\o"CurrentDocument"实验目的 70\o"CurrentDocument"实验内容及要求 70\o"CurrentDocument"自设题 96\o"CurrentDocument"实验小结 97\o"CurrentDocument"实验6指针实验 98\o"CurrentDocument"实验目的 98\o"CurrentDocument"实验内容及要求 98\o"CurrentDocument"自设题 123\o"CurrentDocument"实验小结 127\o"CurrentDocument"实验7结构与联合实验 128\o"CurrentDocument"实验目的 128\o"CurrentDocument"实验内容及要求 128\o"CurrentDocument"自设题 171\o"CurrentDocument"实验小结 177\o"CurrentDocument"实验8文件实验 178\o"CurrentDocument"实验目的 178\o"CurrentDocument"实验内容及要求 178\o"CurrentDocument"自设题 188\o"CurrentDocument"实验小结 190\o"CurrentDocument"参考文献 191实验1表达式和标准输入与输出实验1.1实验目的(1)熟练掌握各种运算符的运算功能,操作数的类型,运算结果的类型及运算过程中的类型转换,重点是C语言特有的运算符,例如位运算符,问号运算符,逗号运算符等;熟记运算符的优先级和结合性。(2)掌握getchar,putchar,scanf和printf函数的用法。(3)掌握简单C程序(顺序结构程序)的编写方法。(4)掌握书写实验报告的格式与基本要求。1.2实验内容及要求源程序改错下面给出了一个简单C语言程序例程,用来完成以下工作:(1)输入华氏温度f,将它转换成摄氏温度C后输出;(2)输入圆的半径值r,计算并输出圆的面积s;(3)输入短整数k、p,将k的高字节作为结果的低字节,p的高字节作为结果的高字节,拼成一个新的整数,然后输出;在这个例子程序中存在若干语法和逻辑错误。要求在计算机上对这个例子程序进行调试修改,使之能够正确完成指定任务。#include<stdio.h>#definePI3.14159;intmain(void)4{intf;shortp,k;doublec,r,s;/*fortask1*/printf(€€InputFahrenheit:'');scanfT%d'',f);c=5/9*(f-32);print"“\n%d(F)=%.2f(C)\n\n”,f,c);13/*fortask2*/printfpinputtheradiusr:n);scanf(n%ff,&r);s=PI*r*r;printf(M\nTheacreageis%.2f\n\nM,&s);/*fortask3*/printfpinputhexintk,p:");scanf(n%x%x”,&k,&p);21newint=(p&0xff00)|(k&0xfTO0)«8;printf(Mnewint=%x\n\n°,newint);return0;24}解答:(1)错误修改:1)第2行的符号常量定义后不能有分号,正确形式为:#definePI3.141592)第3行的intmain(void)返回值类型和函数名应分开,正确形式为:intmain(void)3)第10行的scanf("%d”,f);在输入内容时指向地址应使用&,正确形式为:scanf("%d”,&f)4)第11行的c=5/9*(f-32);由于f是int型,在运算时右侧表达式会被截去小数部分,正确形式为:c=5.0/9*(&32);5)第12行的printf(41\n%d(F)=%.2f(C)\n\n”,f,c);由于c被定义为双精度浮点数应使用占位符%If,正确形式为:prints"\n%d(F)=%.21f(C)\n\n”,f,c);6)第15行的scanf("%f',&r);由于r被定义为双精度浮点数应使用占位符%If,正确形式为:scanfi["%lf,,&r);7)第17行的prints"\nTheacreageis%.2f\n\n",&s);由于s被定义为双精度浮点数应使用占位符%If,正确形式为:printfl^"\nTheacreageis%.21f\n\n",&s);8)第17行的printf("\nTheacreageis%.2f\n\n",&s);在printf中不涉及对s的修改,应不用&,正确形式为:prints"\nTheacreageis%.21f\n\n",s);9)第20行的scanf("%x%x",&k,&p);由于k,p被定义为短整数,占位符应使用%hx,正确形式为:scanff%hx%hx",&k,&p);10)第21行的newint=(p&0xfR)0)|(k&0xflro0)«8中使用了一个未声明的变量newint,应在使用前声明,正确形式为:(6)shortp,k,newint;(注意,改动针对第六行)11)第21行的newint=(p&0xfTO0)|(k&0xffD0)<<8忽略了运算顺序,应恰当使用括号改变运算顺序,正确形式为:newint=(p&0xflTO0)|((k&0xflTO0)<<8);12)第21行的newint=(p&0xfTO0)|(k&0xflTO0)<<8位运算逻辑有误,应恰当改变运算方式,正确形式为:newint=(p&0x1TO0)|((k&0x1TO0)»8);13)第22行的printff'newint=%x\n\n",newint);由于newint被定义为短整数,占位符应使用%hx,正确形式为:printf("newint=%hx\n\n",newint);(2)错误修改后运行结果:见图1-1(查阅资料知1华氏度确为-17.22摄氏度;半径为2的圆面积在保留2位小数且n取3.14159时面积确为12.57;将a2cd的高字节作为结果的低字节,a3a3的高字节作为结果的高字节,拼成一个新的整数,这样的确得到a3a2,其中采用16进制是为了表达与验证方便)InputPahrenheit:11<F>--17.22<C>inputtheradiusi*:2Theacreayeis12.57inputhexintk.p:a2cda3a3newint-a3a2图1-1源程序改错的运行结果1.2.2源程序修改替换下面的程序利用常用的中间变量法实现两数交换,请改用不用第三个变量的交换法实现。#include<stdio.h>intmain(){inta,b,t;print/'Inputtwointegers:^^);scanfT%d%d,,,&a,&b);t=a,a=b,b=t;prinfC'\na=%d,b=%d”,a,b);return0;}解答:由于只能使用两个变量,我们需要利用一个变量来保存两个数的一些共同特征,而这些特征要能通过一定的运算返回初始的数,而若把两数之和存放于第一个数中,通过依次均减去第二个数,可在恢复原来的数的同时将它们交换顺序。替换后的程序如下所示:#include<stdio.h>intmain()(inta,b;printffTnputtwointegers:");scanf^s(n%d%dn,&a,&b);a=a4-b;b=a-b;a=a-b;printf("\na=%d,b=%d",a,b);return0;运行结果见图1-2(1,2交换位置后确为2,1)InputtMointegers:12a-2,!>-1图1-2源程序修改替换题的运行结果1.2.3程序设计(1)编写一个程序,输入字符C,如果C是大写字母,则将C转换成对应的小写,否则C的值不变,最后输出C。解答:首先,无论输入什么字符,这个字符均具有相应的ASCII码,所以我们无需检测输入是否合理,而在接受这个输入之后,我们需要根据它的ASCII码来判断它是否为大写字母,如果它是大写字母,那么就把它变为小写字母(减去A与a的ASCH码值之差即可实现这个要求),而若该字符不满足该要求,直接原样输出即可,算法见流程图1-1,其余细节见程序注释,程序如下。流程图1-1程序设计题1的算法#include<stdio.h>intmain()intc;printf("输入字符,如果它是大写字母,则将它转换成对应的小写,否则原样输出:");c=getchar();〃通过getchar()来获得字符对应的ASCII码if(c<='Z'&&c>='A') 〃判断是否为大写字母c=c-('A'-'a');〃大写字母变小写printf("处理结果是:%c",c);return0;)测试:由于本题不涉及无效输入,所以我们只需分析程序的几种运行情况,其中可分为对大写字母进行转化为相对应的小写字符;而对于小写字母而言,程序不应该将其进行任何转化;此外,对于非字母输入我们也不应该转化,具体测试数据见表1-1,测试结果见图1-3〜1-5。表1-1编程题1的测试数据测试用例程序输入理论结果运行结果用例1Eee用例2eee用例3111对应测试测试用例1的运行结果如图1-3所示输入字符,如果它是大写字母,则将它转换成对应的小写,否则原样输出:E见或结果是:e图1-3编程题1的测试用例一的运行结果对应测试测试用例2的运行结果如图14所示。盘翥矗如既是大写字母’则将垂挨成对应的小弓否则原样输出一图1-4编程题1的测试用例二的运行结果对应测试测试用例3的运行结果如图1-5所示。输入字符,如果它是大写字母,则将它转换成对应的小写,否则原样输出:1七里结果是:1图1-5编程题1的测试用例三的运行结果说明上述的运行结果与理论分析吻合,验证了程序的正确性。(2)编写一个程序,输入无符号短整数x,m,n(0<m<15,1<n<16-m),取出x从第m位开始向左的n位(m从右至左编号为0〜15),并使其向左端(第15位)靠齐。解答:由于题目中明确要求输入无符号短整数,且目前我们缺少检查输入是否为整数的手段,所以本题并不检查输入的x是否合理;不过以我们目前的知识,我们可以根据题目要求对输入的m,n是否合理进行检查(仅检查它们是否在合理范围内,默认其为整数)。而在确认输入合理之后,我们着手开始对问题进行处理,由于这是一个涉及到计算机内部数据的二进制运算的问题,相应地,我们在解决这个问题时也要利用C语言提供的位运算来完成相应的操作,首先,由于我们只需要x从第m位开始向左的n位,所以我们需要去掉x的其余部分(第m位之前的内容),同时从第m位开始向左的n位之后的内容也不再被需要,所以我们也将其去除。至于这去除的实现,为防止数据的丢失,我们不应直接对x进行操作,而应对我们之后会用到的逻辑尺进行操作,而有关逻辑尺的操作,我们可先使用十六进制数对其赋值,使其全为KOxffff,这样较将0取反更方便),再进行相应的左移与右移(注意在移动时要分开进行,否则会由于编译器对运算的简化使部分该被清0的位保留为1),而后,我们再用我们取得的逻辑尺与x进行按位与运算,即可取出x中相应的二进制位,之后,再根据题目的要求,把x移动到指定的位置,最后,由于题目中使用的数字均为十进制数,所以我们的输入与输出均采用十进制数进行。其余细节见程序注释,算法见流程图1-2,程序如下。#include<stdio.h>intmain()unsignedshortintx,m,n,i;printf("输入x(10进制)、m(0-15)和n(1〜16-m):”);scanf(n%hu%hu%huH,&x,&m,&n);if(m>=0&&m<=15&&n>=1&&n<=l6-m)〃判断输入是否合理{i=Oxffff; 〃准备位运算所需逻辑尺i»=m; //确定变换起始位置i«=16-n; 〃确定变换作用长度i»=16-m-n;〃进入变换位置/*注意在移动时要分开进行,否则会由于编译器对运算的简化使部分该被清。的位保留为1*/x&=i;x«=16-m-n;〃左移printf("经过变换得到:%hu",x);}elseprintf("输入错误,请检查您的输入)〃提示输入不合理return0;流程图1-2程序设计题2的算法测试:由于本题中涉及了对错误输入的排除,所以我们需要对程序能否正确排除这些错误的输入进行测试,同时,我们也需要对程序的基本功能进行检查,不过由于本题涉及到位运算,这使得对结果的验证较为困难,我们需要合理的设计测试数据并将其转化二进制数以供验证,再将所得的二进制数转为十进制数并程序输出的十进制数进行比对,以验证程序的正确性(即使采用十六进制输入输出也不够结果也不是十分显然,故不采用),测试数据见表1-2,测试结果见图1・6〜1-8。表1-2编程题2的测试数据或试厚孑物入3论逑累运行逑MSWXmNumi0000000000011001(25)3,H-MigMllOOOeOOOOOO0000K49152的1521101010110000011(54659)161勒入槽次:m(aeTs3?检资脸入用的31101010110000011C54659)135输入Cn(ft£^3)位交帔入对应测试测试用例1的运行结果如图1-6所示输入x(10进制)、m15)和n([〜16-e):2532遂过变换得至49152图1-6编程题2的测试用例一的运行结果对应测试测试用例2的运行结果如图1-7所示。输入X(10进制)、m(0〜15)和n(1〜16-m):54659161输入错误,请密查您的输入图1-7编程题2的测试用例二的运行结果对应测试测试用例3的运行结果如图1-8所示。输入x(1。进制)、m(0〜15)和n(1〜16-m):54659135强入错误,请愈查您的输入图1-8编程题2的测试用例三的运行结果说明上述的运行结果与理论分析吻合,验证了程序的正确性。(3)IP地址通常是4个用句点分隔的小整数(即点分十进制),如32.55.1.102o这些地址在机器中用无符号长整形表示。编写一个程序,以机器存储的形式读入一个互联网1P地址,对其译码,然后用常见的句点分隔的4部分的形式输出。例如,整形676879571二进制表示就是:00101000010110000101110011010011,按照8位一组可表示为:408892211,由于CPU处理数据的差异,它的顺序是颠倒的,所有最终格式为211.92.88.40。解答:首先,这依然是一个涉及到位运算的题目,所以我们依然会用到按位操作与逻辑尺,而逻辑尺的制备与使用均与我们在程序设计题2中所使用的方法大体相同,例如我们使用十六进制数制取逻辑尺,同时尽管从原理上说,我们只需要一个逻辑尺(在每次使用后对其进行移动即可),但这样写成的程序不够明To而在取得了逻辑尺之后,我们再进行按位与运算,以达到取出各二进制位的效果。不过,本题与程序设计题2的不同之处在于,我们需把取出的数进行移动的位数是固定的,但需要注意的时,正如题目中所提到的由于CPU处理数据的差异,我们需要将我们取出的数据进行重新排序,而且,由于我们输出的是IP地址,所以我们需要在输出中添加相应的句点。此外,尽管本题中可能出现非数字输入,但由于我们目前没有有效的手段进行检测,所以我们默认所有的输入都是合理的。其余细节见程序注释,算法见流程图1-3,程序如下。输入无符e长整形数中流程图1-3程序设计题3的算法#include<stdio.h>intmain()iounsignedlongintip,m1,m2,m3,m4,p1,p2,p3,p4;printf("输入长整数形式的ip地址:");scanf("%lu",&ip);ml=OxflTOOOOOO;〃各分段逻辑尺m2=OxOOffDOOO;//各分段逻辑尺m3=OxOOOOfTOO;//各分段逻辑尺m4=OxOOOOOOff;〃各分段逻辑尺pl=(ip&ml)»24;//取出各部分二进制数p2=(ip&m2)»16;〃取出各部分二进制数p3=(ip&m3)»8;//取出各部分二进制数p4=(ip&m4);〃取出各部分二进制数printf("这个ip地址常规形式为:%lu.%lu.%lu.%lu",p4,p3,p2,pl);//按要求格式输出return0;)测试:由于本题默认所有的输入都是合理的,所以我们不对输入的数据是否位整数进行检查(尽管这是必要的,我们会在以后的实验提到如何实现)。同时,我们注意到本题的可能执行情况在正常情况下只有一种(但为了使验证结果具有说服力,我们依然需要数组测试数据),且本题的测试数据相当庞大(特别是将其转化为二进制后),所以我们需要借助计算机将其转化为二进制数并进行相应的人工转化并验证。此外,本题的验证还有一个关键之处,即IP地址的输出顺序是否符合要求,具体测试数据见表1-3,运行结果见图1-9〜1-11。表1-3编程题3的测试数据测试用例程序输入理论结果运行结果长整形形式二进制(十进制)用例14564561300000010⑵10111000(184)01111111(127)00101101(45)45.127.184.245.127.184.2用例212345678900000111(7)01011011(91)11001101(205)00010101(21)21.205.91.721.205.91.7用例378965432100101111(47)00010001(17)00101011(43)00110001(49)49.43.17.4749.43.17.47对应测试测试用例1的运行结果如图1-9所示输入长整数形式的iP地址:45645613这个ip姬址常规形式为:45.127.184.2图1-9编程题3的测试用例一的运行结果对应测试测试用例2的运行结果如图1-10所示。黔球错勰拶巴;梵宽7图1-10编程题3的测试用例二的运行结果对应测试测试用例3的运行结果如图1-11所示。麟球赛勰拜址■鳖舐7图1-11编程题3的测试用例三的运行结果说明上述的运行结果与理论分析吻合,验证了程序的正确性。1.3自设题问题:仿照程序设计题3,设计一段程序,当我们输入一段IP地址(常规形式)时,输出其长整数形式的IP地址。解答:本题中由于需要输入IP地址,而IP地址是由句点分隔的,所以我们需要对格式化输入函数进行相应设置,使之能正常输入IP地址(否则会造成输入域混乱,导致不可预知的错误),而当我们按格式输入了IP地址之后,我们只需要将程序设计题3的程序中的处理顺序逆转即可(由于我们可以先进行按位与运算,再进行移动,所以我们可以只使用一个逻辑尺;此外,关于CPU处理数据顺序的差异,可以在输入时即交换顺序,即用户按实际顺序输入数据,而程序按CPU处理顺序接受数据)。算法见流程图1-4,其余细节见程序注释,程序如下。#include<stdio.h>intmain(){unsignedlongip4,ip3,ip2,ipl,ip; 〃会发生移动,故其最大值并非128,不采用char型ip=0;〃使用前需按需初始化为0printf("请输入常规形式的1P地址:");scanf^s("%lu.%lu.%lu.%lu",&ip4,&ip3,&ip2,&ipl);〃再输入时即按CPU顺序交换了存储顺序
unsignedlongm;m=OxOOOOOOfF;〃在移动之前,仅有前8位需取出〃由于已经发生移动,故此处无需交换顺序ip+=(ipl&m)«24;〃由于已经发生移动,故此处无需交换顺序ip+=(ip2&m)«16;ip+=(ip3&m)«8;ip+=(ip4&m);printf("该IP地址的长整数形式为:%lu\n",ip);return0;流程图1-4流程图1-4自设题的算法测试:本题的测试只需将程序设计题中的测试数据输入输出逆转即可(理论分析由于与程序设计题3完全相同,故略去),测试数据见表1-4,程序运行结果见图1-12,程序运行结果与理论相符,验证了程序的正确性。表1-3编程题3的测试数据测试用例程序输入理论结果运行结果用例145.127.184.24564561345.127.184.2用例221.205.91.712345678921.205.91.7用例349.43.17.4778965432149.43.17.47理论分析由于与程序设计题3完全相同,故略去I测试用例1请输入常规形式的IP地址:45.127.184.2该IP地址的长整数形式为:45645613测试用例2请输入常规形式的IP地址:21.205.91.7该IP地址的长整数形式为:123456789测试用例3请输入常规形式的IP地址:49.43.17.47该IP地址的长整数形式为:789654321图1-12自设题程序的运行结果1.4实验小结这是我第一次撰写的实验报告,自然,会有很多的不完善之处,由于目前的知识有限,诸如流程控制,数组,编译预处理等编程技术都无法使用,而这些技术的使用无疑会给本次实验程序的编制带来极大的方便。诚然,不使用这些手段进行编程的能力也是十分重要的,而本次实验恰好锻炼了我们的此种能力,使我们使用简单而基本的运算与流程,去实现一些稍复杂的程序。而即使是这样较为基本的编程实践中,我也发现了很多自己平时并不注意的问题。比如在最开始我的部分返回值类型不为void的main函数却没有返回值,这使得我的程序在逻辑上并不完整(尽管运行结果看上去是对的)。而除了在编程上的体会之外,我对实验报告的书写也略有感触。这是我第一次书写实验报告,在书写实验报告的过程中,我遇到了很多困难,比如流程图的绘制和图与表格的命名,但在指导老师与助教热心帮助下,我逐一克服了这些困难,并在解决这些困难的同时使自己的能力也得到了相应的提高。实验2流程控制实验2.1实验目的(1)掌握if-else,do-while,switch-case等流程控制语句之用法。(2)能正确理解各流程控制语句所包含的逻辑关系。(3)能正确理解各流程控制语句之间不同,并用这些不同优化自己的程序。(4)能用流程控制语句编写简单的C语言程序。2.2实验内容及要求2.2.1源程序改错下面是计算s=n!的源程序,在这个源程序中存在若干语法和逻辑错误。要求在计算机上对这个例子程序进行调试修改,使之能够正确完成指定任务。例如,8!=40320#include<stdio.h>intmain(void)(inti,n,s=l;printf{nPleaseentern:n);scanfifM%dn,n);fdr(i=l,i<=n,i-H-)s=s*i;printff%d!=%dn,n,s);return0;II}解答:(1)错误修改:1),scanf在输入时应指向单元地址而非单元名称,正确形式为:scanf("%d",&n);2),fbr语句表达式1,2,3之间应用;分隔,正确形式为:(2)错误修改后运行结果:见图2-1(8的阶乘确为40320)Pleaseentern:8Bt-40320图2-1修改后的运行结果2.2.2源程序修改替换(1)修改第1题,分别用while和do-while语句替换for语句。解答:在使用while语句时,其与for语句的主要差异在于没有一个专门的语句为i赋予初值,所以需要在进入循环之前,为i赋予初值1。而在其他的地方,则与经ibr语句的处理基本一致,替换后的程序如下所示:#include<stdio.h>intmain(void)(inti=l,n,s=l;//相较于for语句的关键printf("Pleaseentern:");scanfi("%d",&n);while(i<=n)(s=s*i;iH;)printf("%d!=%d",n,s);return0;}运行结果见图2-2(8的阶乘确为40320)Pleaseentern:77!«5040图2-2while结构下的运行结果在使用do-while语句时,其与while语句的差异特别体现在无论n的值为何值,其都会进行一次循环,但值得注意的是,这一次额外的循环(发生于输入n=0时)在i的初值为1时,并不会改变s的值,从而并不需要进行额外的处理,调换循环体与条件的位置即可,替换后的程序如下所示:#include<stdio.h>intmain(void)inti=l,n,s=l;printf("Pleaseentern:");scanfi("%d",&n);do{s=s*i;i++;}while(i<=n);〃交换条件与循环体的位置printf("%d!=%d",n,s);return0;)运行结果见图2-3(6的阶乘确为720)Pleaseentern:66?=720图2・3do-while结构的运行结果(2)修改第1题,要求输入改为“整数s”,输出改为“满足n!^s的最小整数nwo例如,输入整数为40310,输出结果为n=8。解答:这个问题,从本质上来说,是要找到一个数,使它的阶乘的值大于等于所输入的n的值,且要求这个数的值最小。阶乘的实现,可借助之前编写的程序,并将它作为一个子函数进行调用,使主函数更加简明,数的寻找可借助简明的while循环来实现,程序如下所示,#include<stdio.h>intf(intp){intd=l;inti;fbr(i=l;i<=p;i-H-)d*=i;returnd;)intmain(void){inti,n=l,s=l,sl;print/'Pleaseenters:n);scanf(f,%dM,&sl);while(sl>s)〃比较n++;s=f(n);〃计算阶乘}printf("n=%d\n",n);return0;运行结果见图2-4(40320=8!>40312>7!=5040)Pleaseenters:40312m=8图2-4第2题程序的运行结果2.2.3程序设计(1)假设工资税金按以下方法计算:x<1000元,不收取税金;1000Wx<2000,收取5%的税金;20000x<3000,收取10%的税金;30000x<4000,收取15%的税金;4000<x<5000,收取20%的税金;x>5000,收取25%的税金。编写一个程序,输入工资金额,输出应收取税金额度,要求分别用if语句和switch语句来实现解答:首先对输入的x进行判断,判断其是否是一个合理的工资数目,如果不合理(比如说是负数),就输出提示输入不合理的内容。而如果其输入合理,则通过对x值的判断,决定其对应的税收方式,而后进行计算。需要注意的是,在if-else结构下,对x的区间划分比较显然,但由于switch语句只能选择整数,结合x的分段区间宽度均为1000,于是将x除以1000后再强制转换类型为int在进入各case进行运算,同样重要的是,注意到switch语句的特点,我们可以巧妙的利用其特性,简化程序语句。其余细节见程序注释,算法见流程图2-1与2-2,程序如下。#include<stdio.h>intmain(void)doublex,tax;printf("请输入您的工资金额:,scanf_s("%lf,&x);if(x<0)printf("您输入了错误的工资,请检查您的输入H");〃检查输入是否合理else(if(x<1000)tax=0;elseif(x<2000)tax=(x- 1000)*0.05;elseif(x<3000)tax=(x- 2000)*0.10+ 1000* 0.05;elseif(x<4000)tax=(x- 3000)*0.15+ 1000* (0.10 +0.05);elseif(x<5000)tax=(x- 4000)*0.20+ 1000* (0.05 +0.10+0.15);elsetax=(x-5000)*0.25+1000*(0.05+0.10+0.15+0.20);printf("(IFELSE方式)您须交税:%.21f元\n",tax);tax=0;〃为利用switch语句的特点,会进行累加运算,此处需将tax清零switch(((int)x)/1000)//对switch仅能选择整数的处理(default:tax+=(x-5000)*0.25;x=5000;〃注意到switch的特点case4:tax+=(x-4000)*0.20;x=4000;case3:tax+=(x-3000)*0.15;x=3000;case2:tax+=(x-2000)*0.10;x=2000;case1:tax+=(x-1000)*0.05;x=1000;〃此处的x=1000并不是必要的case0:;}printf("(SWITCH方式)您须交税:%.21f元5",tax);)return0;流程图2-1见下一页。流程图2-1程序设计题1的算法(if-else结构)流程图2-2见下一页。流程图2-2程序设计题1的算法(switch结构)测试:测试数据:见表2-1,在选取测试数据时,我们注意到,首先应检测程序能否正确判断输入的正确性,故我们输入-1(负数)与.(非数字)。其次,我们在各数据段中选取具有代表性且易于人工验算的数据,因此,我们在此处在各工资段中选取了500,1500,2500,3500,4500,5500.同时,选取边界数据0,1000,2000,3000,4000,防止程序无法正常处理边界值,图2-5的运行结果说明结果与理论分析吻合,验证了程序的正确性。
表2-1编程题1的测试数据测试用例1i疗输入您的1:保金额:1错识的测试用例1i疗输入您的1:保金额:1错识的I:俗.清依:令您的输入道输入您的I.货金额:+您检入rtrt设的।:资.谪检化您的蛤入测试川例3晴瑜入您的I:洗金制I:O(IFELSE方式)您须交税:0.00元(SWITCH方式)您须交币兑:0.D。元测试川例4i卉蛤入您的工资金额:500(IFELSE方式)您须交:0.00元(SWITCH方式)您须交税:0.00元测I试用例5入您的工资金额:1000(IFELSE方式)您须交税:0.00元(SWITCH方式)您须交税:0.00元测试用例6储检入您的I:资金额:1500(IFELSE方式)您须交税:25.00元(SWITCH方式)您须交税:25.00元测试川例7i.'i除入您的工资金额:2000(IFELSE方式)您须交税:50.00元(SWITCH方式)您须交税:50.00元测试用例8i行输入您的工资金额:2500(IFELSE方式)您须交税:100.00元(SWITCH方式)色;须「爻税:10600元测试用例9疗输入您的1:资金额:3C00:IFELSE方式)您须交税:150.00元(SWITCH方式)您须交税:150.00元测试用例10疗输入您的1:资金额:3500:IFELSE方式)您须交税:225.00元:SWITCH方式)您须交税:225.00元测试用例11次输入您的工费金额:4C00:IFELSE方式)您须交税:300.00元:SWITCH方式)您须交税:300.00元测试用例12青输入您的工资金额:4500:IFELSE方式;)您须交税:400.00元:SWITCH方式)您须交税:400.00元测试用例13青输入您的工资金额:5C00:IFELSE方式)您须交税:500.00元:SWITCH方式)您须交税:500.00元则试用例14音输入您的工资金额:5500:IFELSE方式)您须交税:625.00元:SWITCH方式)你须学税:625.0071-测试用例.程序输入.理论若果运行结果用例1.••.提示幻误.提示错误.用例2.4-提示命误.提示错误.用例3.0.00元.0.00元.照例4.5co0.00元.0.00元.用例5.10000.00元.0.007C用例6.150025.0(元25.00元.H例7.20005().(M比50.00元.用例8.2500100.0)元.100.00元.用例9.3000150.05元150.00元.用例103500.225.0)元.225.00元“him114000300.0)元.300.00元.用例12.4500400.0)元.400.00元.用例1350)0.500.0)元.500.00元.用例1455*)0.625.0)元.625.00元.图2-5编程题1的测试用例一的运行结果(2)编写一个程序,将输入的一行字符复制到输出,复制过程中将一个以上的空格字符用一个空格代替。解答:这与C语言处理注释文字的方式相似,为此,我们定义两个字符单元,分别用于收集当前收集的字符与上一个收集的字符,当这两个单元都收集到空格字符时,停止输出收集到的字符,否则,正常输出收集到的字符,这样,便可以将一个以上的空格字符用一个空格代替。其余细节见程序注释,算法见流程图2-3,程序如下。#include<stdio.h>intmain()charc,d=0;//搜集当前字符的c单元与前一字符的d单元,注意由于最开始“前一字符”不存在,需给d赋初值while((c=getchar())!=EOF)if(c!=")printf("%c",c);//非空格字符正常输出if(c==")if(d!='')print<"%c",c);〃非连续空格字符正常输出d=c;//记录前一字符return0;流程图2-3程序设计题2的算法测试:为了测试本程序应对各个位置的空格的能力,作者在各处放置了数量不等的空格,特别是首尾两处,其次,为了测试程序是否会错误的少输出字符,作者将所有的非空格字符均设为2个及以上。测试数据:字符串(前有2个空格)1122233llaabb111...3311AAAA444+++///666 (后有2个空格)理论输出结果:(前有1个空格)1122233llaabbxlll...3311AAAA444+++///666(后有1个空格)对应测试测试用例的运行结果如图2-6所示。特别提示,为使程序效果显目,用字母x代表空格。下面的运行结果说明结果与理论分析吻合,验证了程序的正确性。xxll22233xllaabbxxlll...33xxxllAAAA444+++〃/666xxxll22233xllaabbxlll...33x1lAAAA444+++///666x图2-6编程题2的测试用例的运行结果(3)编写一个程序,打印如下的杨辉三角形。1 /*第0行*/TOC\o"1-5"\h\z1 1 /*第 1行 */1 2 1 /*第 2行 */13 3 11 4 6 4 11 5 10 10 5 11 6 15 20 15 6 11 7 21 35 35 21 7 11 8 28 56 70 56 28 8 11 9 36 84 12612684 36 9 1每个数据值可以由组合C/计算(表示第i行第j列位置的值),而C/的计算如下:C,°=l (i=0,l,2,…)C/=C/-'*(i-j+l)/jG=0,l,2,3,...,i)说明:本程序中为了打印出金字塔效果,要注意空格的数目。一位数之间是3个空格,两位数之间有2个空格,3位数之间只有一个空格,程序编制过程中要注意区分。解答:首先,定义一个函数用于生成组合数,题目中提供了一种很好的组合数生成方式,它能避免在计算到17的阶乘时就会造成int溢出的结果使计算结果异常,从而提供了计算范围更大的组合数的可能,当然,在本题中组合结果最大只能是999(否则会出现4位数而无法构成金字塔)。而到了生成金字塔的环节,我们可以将每一个数的单元视作一个长度为4的砖块,这样,我们可以得到一个显然的结论:为了得到金字塔,从最下面一层开始,在其前方输出2个空格,并且每向上一层,就再增加两个空格。最后这个10层的金字塔,塔底有10个数,但值得注意注意的是这是(a+b)9的展开式各项系数而非(a+b严的,程序如下。#include<stdio.h>intzh(inta,intb)〃声明一个新的函数,使程序更简明(intj,i,r=l;if(a==0&&b==0)return1;〃处理c(0,0)的特殊情况for(i=1;i<=a;i++)r=(r*(b-i+l))/i;〃组合数算法returnr;)voidmain(){inti,j,n,k,p;n=9;〃十阶金字塔对应的是(a+b)9的展开式fbr(i=0;i<=n;i++)(fbr(k=2*(n-i);k>0;k-)putchar('');〃生成空格fbr(j=0;j<=i;j++)printf("%4d",zh(j,i));//输出数据,注意%4d的使用满足了题目对空格数的要求putchar('\n');))测试:本题无需输入,输出如下图。111TOC\o"1-5"\h\z12 113 3 11 4 6 4 11 5 10 10 5 11 6 15 20 15 6 11 7 21 35 35 21 7 11 8 28 56 70 56 28 8 19 36 84 126 126 84 36 9 1图2-7编程题3的运行结果(4)编写一个程序,将用户输入的任意正整数逆转,例如,输入1234,输出432lo解答:由于本题明确指出所逆转的对象是正整数,从而首先需要对获得的输入进行判定,以确定其是否是符合题目要求的输入。再确定输入合乎题目要求之后,利用同余除法的特性,求出输入数据除以十的余数并将其输出,而后将输入的数字除以十,由于输入是int型,从而除以十的结果等效于消除了最后一位数字,再求出新的数字除以10的余数,如此循环下去,便可输出被逆转的整数,考虑到循环的逻辑简明,故采用while语句。其余细节见程序注释,算法见流程图2-4,程序如下。流程图2-4程序设计题4的算法#include<stdio.h>intmain()intn,s;printf("请输入一个正整数,本程序会将其逆转:");scanf^s("%d",&n);if(n<=0)printf("本程序只接受正整数输入,请检查您的输入)〃检查输入是否合理elsewhile(n)〃注意,此处只用于判断循环是否结束,不用于判断输入是否合s=n%10;printf("%d",s);〃输出最后一位数n=n/10;〃消除最后一位数)putchar('\n');printf("\t此即为逆转结果");return0;}测试:首先,是对函数基本功能的测试,即测试其能否正确逆转正整数,在此,我们选取一个正常的正整数O,接下来测试程序对异常输入的反应一个异常输入0(非正整数),一个异常输入“。”(非数字),其预期结果与实际结果见表2-2,运行结果见图2-8。表2-2编程题1的测试数据测试用例程序输入理论结果运行结果用例1OOO用例2提示错误提示错误用例30提示错误提示错误测试用例:1请输入一个正整数,本程序会将其逆转:测试结果:测试用例:2请输入一个正整数,本程序会将其逆转:。本程序只接受正整数输入,i疗检畲您的输入测试用例:3请输入一个正整数,本程序会将其逆转:0本程不只接受正整数输入,请检代您的输入图2-8编程题4的运彳丁结果2.2.4选做题编写一个程序,用牛顿迭代法求方程f(x)=3/_4/_5x+13=。满足精度e=10-6的一个近似根,并在屏幕上输出所求近似根。牛顿迭代法求方程近似根的迭代公式为:\x0=alx*+i=xk-f(xk)/f\xk)其中,/'(x)是函数f(x)的导函数。牛顿迭代法首先任意设定的一个实数。来作为近似根的迭代初值xo,然后用迭代公式计算下一个近似根XI。如此继续迭代计算X2,X3,…,Xn,直到氏-%区精度e,此时值x。即为所求的近似根。解答:首先,为了计算Xk+I我们应先计算f(Xk)与F(Xk)而对这两个多项式的计算,我们可以采用秦九韶算法,这样可以减少对计算机而言较复杂的的乘法运算,虽然对单次计算而言,这样的简化效果并不明显,但在多次的迭代计算中(本题中进行了三十三次),这样的简化可大幅提高计算效率。而在解决了f(Xk)与f'(Xk)的值后,为了使程序更加简洁,我们将这两个式子定义为新的函数,与此同时,将迭代过程也定义为一个新的函数。最后在判断Xk+1与Xk的接进程度时,考虑到最初Xk+1并未赋值,我们在此处采用至少循环一次的do-while结构。其余细节见程序注释,算法见流程图2-5,程序如下。#include<stdio.h>#include<math.h>doublefifdoublex)(return(((3*x-4)*x-5)*x+13);〃秦九韶算法)doubledf(doublex){return((9*x-8)*x-5);〃秦九韶算法)doublen(doublex)return(x-f(x)/df(x));〃迭代}voidmain(){doublexk=l,xp=l;intk=0;doxk=xp;xp=n(xk);k++;〃统计计算次数while(fabs(xp-xk)>le-6);printf("方程的根:%lf\n计算次数:%d\n",xk,k);流程图2-5选做题的算法测试:本题无需输入,输出见图2-9。本方程的根为(sqrt(21799)/(2*3A(7/2))-249l/1458)A(l/3)+61/(81*(sqrt(21799)/(2*3A(7/2))-2491/1458)A(l/3))+4/9=-l.548909593下面的运行结果说明结果与理论分析吻合,验证了程序的正确性。方程的根:T.548910计算次数:33图2-9选做题的的运行结果2.3自设题问题:判断一个数是否是质数。解答:为判断一个数是否是质数,我们通常是把小于这个数的每一个数去除这个数直到除到它自身为止(称为1方法),但是这样的效率很低,且会进行大量的重复计算,于是有人提出只需要除到这个数的一半(称为2方法),但事实上这样也会造成重复计算,经过理论分析表明,只需要除到这个数的平方根即可(称为3方法),当然,存在其他更优越的方法,如Solovay-Strassen算法和Miller-Rabin算法,但它们较复杂,也有针对特定环境的方法,例如把一定范围内的质数先生成,在使用进行大小比较即可,但这针对多次查询比较有效。在此,我们将比较1方法,2方法与3方法计算所需要的时间。特别地,对于3方法而言,开根号无论是对于人还是对于计算机都是一项复杂的工作,为提高计算效率,我们采用一个等价描述,即0<加46=加2与〃。这样把需要多次迭代的开方运算变成了乘法运算,能显著提高计算效率。至于计时方面,C语言的time.h中提供了相应的函数,我们可直接调用用来计时,注意到它的精度是毫秒级的,所以它的精度是足够的,其余细节见程序注释。算法(仅包含质数判断)见流程图2-6,程序如下.流程图2-6自设题的算法#include<stdio.h>#include<time.h>〃用于计时#include<math.h>intf(intk,intx);〃索引函数intfl(intx);intf2(intx);intf3(intx);//计算函数voidmain(void){intx;intk=O;〃计数器a:x=100;k++;while(x<le5)〃防止计算过度,限制最大数值为十万(printf("测试方法:%d\n",k);x*=10;printf("现在寻找小于%d的质数\n",x);clocktstart,end;//注意只记录计算质数的时间start=clock();printf("找到%d个质数\n",f(k,x));end=clock();printff用时%.0僵秒\n————=\n",1000*((double)end-start)/(CLKTCK));〃显示时间)if(k<3)gotoa;〃合理使用goto简化程序}intf(intk,intx){if(k=1)returnfl(x);〃l方法if(k=2)returnf2(x);〃2方法if(k=3)returnf3(x);〃3方法)intfl(intx){inti,j,n=0,k=0;for(i=3;i<x;i++)〃注意2肯定是质数,1不是质数也不是合数for(j=2;j<i;j++)(if(i%j=0)n++;//n:合数判断器一旦n不为0输入的数即不为质数if(n){k++;n=0;break;//k:合数计数器return(x-k-2);〃总数减去合数数与1即是质数数}intf2(intx){inti,j,n=0,k=0;for(i=3;i<x;i++)//注意2肯定是质数,1不是质数也不是合数{for。=2;j<=i/2;j++)〃注意到等号是必要的,否则会漏掉形如2P(p为质数)的合数(if(i%j=0)n++;//n:合数判断器一旦n不为0输入的数即不为质数if(n){k++;n=0;break;//k:合数计数器return(x-k-2);〃总数减去合数数与1即是质数数}intf3(intx){inti,j,n=0,k=0;fbr(i=3;i<x;i++)〃注意2肯定是质数,1不是质数也不是合数{for(j=2;j*j<=i;j++)〃注意到等号是必要的,否则会漏掉形如p人2(p为质数)的合数
if(i%j=0)n++;//n:合数判断器一旦n不为0输入的数即不为质if(n)(k++;n=0;break;//k:合数计数器)))return(x-k-2);〃总数减去合数数与1即是质数数测试:本题无需输入,查阅资料可知:1000以内的质数有168个;10000以内的质数有1229个;100000以内的质数有9592个;1000000以内的质数有78498个。结果见图2-10,与理论数目相符,验证了程序的正确性。测试方法:1现在寻找小于1000的质数找至U168个旗数测试方法:1现在寻找小于1000的质数找至U168个旗数小时0宅秒测试方法:1现右寻找小于1OOOO的质数找到1229个历数用时25把秒测试方法:2现在寻找小于100000的质数找到9592个质数用时964毫秒测试方法:1现在J技小厂100000的旗数找到9592个项数用时1637,完秒测试方法:3现在寻找小于1000的质数找到168个质数用时1亳秒测试方法:2现在才找小于1000的历数找到168个质数用时0亳秒测试方法:3现在寻找小于10000的质数找到1229个质数用时1亳秒测试方法:2现在寻找小于10000的质数找到1229个质数用时13亳秒测试方法:3现在寻找小于100000的质数找到9592个质数用时27亳秒图2-10自设题程序运行结果由此可见,算法的优化对程序的运行效率是多么的重要,同样的问题,使用不同的算法,其效率之差可能接近80倍。特别需要指出的是,方法1与方法2都无法正常的寻找小于一百万的质数总数,而方法3处理这个问题仅需740毫秒(见图2-11),充分体现其优越性。测试方法:3现在寻找小于1000000的质数找到78498个质数用时740毫秒图2-11方法3寻找小于一百万的质数总数2.4实验小结在本次实验中,我对各种流程控制语句的使用更加熟悉了,同时也对它们之间的差距与各自的优劣有了更加深刻的认识,比如while语句适合用于简单的循环逻辑;而其衍生语句do-while语句适合用于一定会有循环发生的情形(即至少会执行一次循环体中的内容,如牛顿法求方程的根);而更加复杂的for语句则适合用于某些更加复杂的情况,但这些语句在本质上是一致的,即可使用某一语句实现这三种语句的所有功能(当然这会带来不便)。而另一类型的流程控制语句(带有选择色彩的)if-else语句与switch语句则分别适用于较少选择支与较多的选择支,不过switch语句与if-else语句的最重要区别并不在此;它们的关键区别在于switch语句可用于某些需要满足某一条件后顺序执行之后所有语句的情形。此外,在本次实验中,我也体会到了一个优良的算法对程序执行效率提高的重大作用,如在选做题中我们使用了秦九韶算法提高了多项式求值的效率;而在自设题的质数判断中,一个合适的条件(算法)对程序效率的提升那更是不言而喻的。实验3函数与程序结构实验3.1实验目的(1)熟悉和掌握函数的定义、声明;函数调用与参数传递方法;以及函数返回值类型的定义和返回值使用。(2)熟悉和掌握不同存储类型变量的使用。(3)熟悉多文件编译技术。3.2实验内容及要求3.2.1源程序改错下面是计算s=l!+2!+3!+…+n!的源程序,在这个源程序中存在若干语法和逻辑错误。要求在计算机上对这个例子程序进行调试修改,使之能够正确完成指定任务。#include<stdio.h>intmain(void){intk;fbr(k=l;k<6;k-H-)printf(nk=%d\tthesumis%ld\nn,k,sum_fac(k));return0;)longsum_fac(intn){longs=0;inti;longfac;fbr(i=l;i<=n;i-H-)fac*=i;s+=fac;returns;)解答:(1)错误修改:1)第5行处的循环使得程序只能计算一些固定数的阶乘和,正确形式为:scanf_s("%d",&k);2)第6行处使用了一个新定义的函数sum_fac(),但没有预先声明,正确形式为:(在第1行与第2行之间插入)longsum_fac(intn);3)第15行处使用了一个未初始化的变量fac,正确形式为:longfac=1;4)第15行与16行的计算逻辑有误,这样只能得到n!的值,正确形式为:{fac*=i;s+=fac;}(2)错误修改后运行结果:见图3-1(1!+2!+3!=1+2+6=9)pleasethenunbei*k
k=3thesunis'图3-1修改后的运行结果3.2.2源程序修改替换(1)修改第1题中sumfac函数,使其计算量最小。解答:第1题中sum_fac函数计算量较大主要是由于无论是在求阶乘时还是在求其和时均出现了大量的重复运算,为此,我们使用递归函数来减少计算量为此我们采用了静态变量,注意这样会使用“虚拟”(即计算但不输出)的循环来达到记录之前的阶乘值得目的来简化运算,其余细节见程序注释,程序如下。#include<stdio.h>longsum_fac(intn);intmain(void)(intk,i;printf("pleasethenumberk:");scan匚s("%d",&k);if(k<=0)printf("legalinput!");〃排除非法输入else{for(i=l;i<=k;i++)if(i=k)printf("k=%d\tthesumis%ld\n",i,sum_fac⑴);〃注意longint的占位符elsesumfac(i);〃“虚拟”输出))return0;)〃以下得函数使用静态变量简化了运算staticlongfac=1,sum=0;longsum_fac(intn)(fac*=n;sum+=fac;returnsum;)运行结果见图3-2 (l!+2!+3!+4!=l+2+6+24=33)pleasethenunherk:4
k=4thesunis33图3-2修改后的正常运行结果pleasethenunbei*legalinput!图3-3修改后的异常运行结果(2)修改第1题中sumfhc函数,计算s=1+,+'+...+2!3! 〃!解答:此处只需要每次计算阶乘时改为计算其倒数即可,但特别需要注意的是,计算过程中会出现小数,因此需要改变大部分变量的数据类型,其余细节见程序注释,程序如下。#include<stdio.h>doublesum_fiac(intn);longfac(intn);〃注意数据类型的改变intmain(void){intk;printf("pleasethenumberk:");if(k<=0)printf("legalinput!");〃排除非法输入scanf("%d",&k);printf(,,k=%d\tthesumis%lf\nn,k,sumfac(k));return0;)doublesum_fac(intn){if(n>1)return1.0/fac(n)+sum_fec(n-1);〃注意1,0的使用强制转换了类型elsereturn1;}longfac(intn){if(n>1)returnn*fac(n-1);elsereturn1;)运行结果见图3-4与图3-5-(1+1/2!=1+0,5=1.5)pleasetienumberk:2k・2thesunis1.500000图3-4第2题程序的正常运行结果pleasethenumbei*k:-1legalinput!图3・5第2题程序的异常运行结果3.2.3跟踪调试题下面是计算fabonacci数列前n项和的程序,要求单步执行程序,观察p,i,sum,n值。#include<stdio.h>intmain(void)(inti,k;longsum=0,*p=∑/*声明p为长整型指针,指向sum*/scanf(n%dn,&k);for(i=l;i<=k;i++){sum+=fiabonacci(i);printf(Mi=%d\tthesumis%ld\nM,i,*p);/**p等价于sum*/return0;longfabonacci(intn)(if(n==l||n==2)return1;elsereturnfabonacci(n-1)+fabonacci(n-2);)(以下第1〜3题的分析以输入的n=2为分析基础)(1)刚执行完scanf("%d",&k);语句,p,i值是多少?、答:通过理论分析,由于p被设定为指向sum的指针,故其值与此时sum之值相同,而sum在声明时已经被赋予初值0,从而此时p的值也应为0。而i此时仅被声明而尚未被初始化,从而其值为一个在int范围内的随机数。跟踪的实际结果图3-6所示,与理论分析相符。0*p0 lone*i-858993460 int图3-6步骤(1)的跟踪结果(2)从fabonacci函数返回后光条停留在哪个语句上?答:通过理论分析,由于是从第8行进入fabonacci函数且在进入前第8行的计算尚未完全结束,所以从fabonacci函数返回后应继续未完成的计算,即光标应停在第8行。跟踪的实际结果图3-7所示,与理论分析相符。◊ 8 sum+=fabonacci(i);已用时间<=ims图3-7步骤(2)的跟踪结果(3)进入Fibonacci函数,watch窗口显示的是什么?答:通过理论分析,在第一次进入fabonacci函数时,watch窗口中应显示带入的参数,又此时仅带入了参数i,而参数i的值又为1,从而该窗□应显示n=l。而在第二次进入时,i=2,同理该窗口应显示n=2。跟踪的实际结果图3-8与图3-9所示,与理论分析相符。
自礴口名称直♦nI▼9x类型int自助窗口▼9x类型int图3-8步骤(3)的跟踪结果(第一次进入)自动窗口 7x名称 直 类型。n2 int自动窗口局部变量监视1图3-9步骤(3)的跟踪结果(第二次进入)(4)当i=3,从调用fabonacci函数到返回,n值如何变化?答:通过理论分析,在第一次进入fabonacci函数时,watch窗口中应显示带入的参数,又此时仅带入了参数i,而参数i的值又为3,从而该窗□应显示n=3,此时n不是1或2中的任意一个,故进入else后的语句,该语句中参数分别为2与1,从而该窗口应显示n=2与n=l,之后,会直接进入if后的语句,该语句不会再为fabonacci函数提供参数,所以不再进入fabonacci函数,当然,在完成这些计算后,在return之前,n的值又一次变回3,从而该窗口应显示n=3,此后,n便不复存在。跟踪的实际结果图3-10至图3-14所示,与理论分析相符。自动窗口 7X名称 值 类型・n2 int自动窗口局部变量监视1图3-10步骤(4)的跟踪结果(刚进入)
110%Elongfabonacci(intn)110%{已用时间<=1msif(n==111n«
return1;returnfabonacelsereturnfabonac自动直口局部变量监视1图3-11步骤(4)的跟踪结果(计算自bonacci(2))在动窗口 ▼qx名称值 类型。n1 int自动窗口局部变量监视1图3-12步骤(4)的跟踪结果(计算fabonacci(l))自丽口 ▼Qx名梆值 类型名梆值 类型自初窗口曷部变量监视1图3-13步骤(4)的跟踪结果(return后)自动窗口TOC\o"1-5"\h\z名梆 值0*p 4♦i 4.sum 4图3・14步骤(4)的跟踪结果(退出后)3.2.4程序设计题(1)编程让用户输入两个整数,计算两个数的最大公约数并且输出之(要求用递归函数实现求最大公约数)。同时以单步方式执行该程序,观察递归过程。解答:首先,为了使计算尽量简单,我们使用辗转相减法来计算最大公约数,同时,辗转相减法也是用于单步观察执行过程的优良算法(因其计算结果简单且计算次数较少)并且也可使用递归来提高运算效率,其余细节见程序注释,算法见流程图3-1,程序如下。流程图3-1程序设计题(1)的算法#include<stdio.h>intR);voidmain()inta,b;prin氓"请输入两个正整数(以空格分隔):");scan7%d%d",&a,&b);if(a<=0||b<=0)printf("您输入了非正整数内容,请检查您的输入\n");//检查非法输入elseprint口"它们的最大公约数是:%d\n",f(a,b));intf(inta,intb)//辗转相减法
if(a=b)returna;if(a>b)returnf(a-b,b);if(a<b)returnf(a,b-a);测试:首先,我们应测试程序能否正常运行,为此我们选择了具有多个公因数(非1)的90与60,而后选择具有倍数关系的5与10与相等两数12与12(注意到其拥有多个因数),接着又提供了一组带有1的测试样例7与1,以测试在非常情况下程序的
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025维修电工工作总结(15篇)
- 全国粤教版信息技术七年级下册第二单元第八课《多媒体作品及其界面设计》教学设计
- 储备干部心得体会范文(14篇)
- 库管个人工作计划范文(5篇)
- Unit 2 Sewction A 1a~1d 教学设计- 2024-2025学年人教版(2024)七年级英语上册
- 销售业务员2025工作总结(20篇)
- 生产部个人工作总结(18篇)
- 以感恩主题的小学生演讲稿(14篇)
- 2025年交通安全年度工作总结(6篇)
- 小学语文人教部编版二年级下册5 雷锋叔叔你在哪里教案设计
- 《油气井增产技术》课件-63 拉链式压裂井场布置
- 2025年广东省东莞市中考数学模拟考试试卷及答案解析
- 医疗行业移动医疗设备租赁服务方案
- 事业单位工会管理制度
- 零星工程施工合同2024年
- 震后学校维修合同书
- 2023-2024学年广东省深圳市七年级下册期中语文质量检测试卷(附答案)
- 物业工程竞标方案
- 手术室不良事件警示教育
- 李白:《将进酒》经典省公开课一等奖全国示范课微课金奖课件
- 新课标课堂教学设计与案例分析
评论
0/150
提交评论