• 305.36 KB
  • 2022-04-22 11:15:55 发布

《全国计算机等级考试二级教程 C语言程序设计》课后习题详细答案.pdf

  • 34页
  • 当前文档由用户上传发布,收益归属用户
  1. 1、本文档共5页,可阅读全部内容。
  2. 2、本文档内容版权归属内容提供方,所产生的收益全部归内容提供方所有。如果您对本文有版权争议,可选择认领,认领后既往收益都归您。
  3. 3、本文档由用户上传,本站不保证质量和数量令人满意,可能有诸多瑕疵,付费之前,请仔细先通过免费阅读内容等途径辨别内容交易风险。如存在严重挂羊头卖狗肉之情形,可联系本站下载客服投诉处理。
  4. 文档侵权举报电话:19940600175。
'《全国计算机等级考试二级教程——C语言程序设计》习题分析与详细解答第一章程序设计基本概念习题分析与解答1.1【参考答案】EXE1.2【参考答案】[1].C[2].OBJ[3].EXE1.3【参考答案】[1]顺序结构[2]选择结构[3]循环结构第二章C程序设计的初步知识习题分析与解答一、选择题2.1【参考答案】B)2.2【参考答案】D)2.3【参考答案】B)2.4【参考答案】A)2.5【参考答案】C)2.6【参考答案】A)2.7【参考答案】B)2.8【参考答案】B)2.9【参考答案】D)2.10【参考答案】C)2.11【参考答案】B)2.12【参考答案】B)2.13【参考答案】A)二、填空题2.14【参考答案】[1]11[2]122.15【参考答案】[1]4.2[2]4.22.16【参考答案】[1]{[2]}[3]定义[4]执行2.17【参考答案】[1]关键字[2]用户标识符2.18【参考答案】[1]int[2]float[3]double2.19【参考答案】floata1=1.0,a2=1.0;或floata1=1,a2=1;(系统将自动把1转换为1.0)2.20【参考答案】存储单元2.21【参考答案】3.52.22【参考答案】[1]a*b/c[2]a/c*b[3]b/c*a2.23【参考答案】把10赋给变量s2.24【参考答案】[1]位[2]1位二进制数据(0或1)2.25【参考答案】[1]8[2]127[3]01111111[4]-128[5]100000002.26【参考答案】[1]32767[2]-32768[3]10000000000000002.27【参考答案】[1]十[2]八[3]十六三、上机改错题2.28【分析与解答】第1行的错误:(1)include是一个程序行,因此在此行的最后不应当有分号(;)。1 第2行的错误:(1)main()是主函数的起始行,不是语句,因此最后不应当有分号(;)。(2)在同一行上的/*mainfunction*/显然是注释;C语言规定:注释由/*开头,由*/结束,但在*号和/之间不得插入任何空格,而在此处“/*”和“*/”之间存在空格,因此,/*mainfunction*/的写法是错误的,而应写成:/*mainfunction*/。第3行的错误:(1)在主函数的起始行main()的后面是函数体,函数体由左花括号({}开始。但在函数体的第一行:float的前面缺少了左花括号({}。(2)在同一行上的/*/*risradius*/,/*sisareaofcircular*/*/显然是注释;C语言规定:注释由/*开头,由*/结束,并且开头的/*将去找最近的*/去配对,因此在/*/*risradius*/中,第一个/*与radius后的那个*/配上了对,结果紧跟在后面的那个逗号(,)落在了注释的外面,而构成了一个多余符号,为此,在编译时将报告“语法错”。/*sisareaofcircular*/*/中第一个*/就结束了注释,第一个*/就成了多余的了。第6行的错误:(1)printf(″%f\n″,s)应当是一条输出语句,但在最后缺少了一个分号。(2)printf(″%f\n″,s);是程序的最后一条语句,程序应当结束;但缺少了程序体结束所需的右花括号());此右花括号可以放在printf(″%f\n″,s);的后面,也可以放在printf(″%f\n″,s);的下一行上。2.27【分析与解答】第2行的错误:在main的后面缺少一对圆括号。第4行的错误:在c=4.0的后面缺少分号。第6行的错误:在printf(″%f\n″,v)的后面缺少分号。第三章顺序结构习题分析与解答一、选择题(单选题)3.1【参考答案】C)3.2【参考答案】C)3.3【参考答案】D)3.4【参考答案】C)3.5【参考答案】D)3.6【参考答案】B)3.7【参考答案】C)3.8【参考答案】D)3.9【参考答案】A)3.10【参考答案】B)3.11【参考答案】C)3.12【参考答案】D)3.13【参考答案】D)3.14【参考答案】A)3.15【参考答案】C)3.16【参考答案】C)3.17【参考答案】C)3.18【参考答案】D)把D的答案修改为:scanf(“%8f”,&c);3.19【参考答案】C)3.20【参考答案】B)2 二、填空题3.21【参考答案】(1)-200,2500(2)i=-200,j=2500(3)i=-200j=25003.22【参考答案】[1]12[2]0[3]03.23【参考答案】[1]一条语句[2]分号(或;)3.24【参考答案】分号(;)3.25【参考答案】[1]:10025.811.89234[2]:10025.811.89234[3]:10025.811.892343.26【参考答案】x=127,x=127,x=177,x=7f,x=1273.27【参考答案】x=127,x=127,x=$127,x=$000127,x=%06d3.28【参考答案】a=513.789215,a=513.79,a=513.78921500,a=513.78921500三、编程题和改错题3.29【分析与解答】(1)主函数名main后应有一对圆括号。(2)第三行的printf语句用以提示输入,但是原样输出的字符串没有用双引号括起来;另外,从输入的形式看,输入的数据紧跟在提示之后,因此,printf格式串中最后不应该有换行符——\n。(3)因为输入项a、b、c从定义和计算结果来看都是double类型,因此,第四行scanf语句格式串中的格式说明不应当用%d而应当用%lf;且每一个变量之前应该加地址运算符&。(4)第七行的printf语句中应当把%d都改成%lf或%f;按输出要求在格式串中应添加相应的原样输出的字符;因为下一个printf的输出从新的一行开始,因此在本输出语句的格式串的最后应当加换行符——\n。(5)第八行的printf语句中应当把格式串整理合并放在输出项的前面,输出项放在后面,%d都改成%lf或%f;中间的\n删去。(6)请同学们自己写出修改后的程序,并上机调试。3.30【分析与解答】(1)分析:可用算术式560÷60把分钟换算成小时和分钟,商数就是小时数,余数就是分钟数。(2)确定变量的名字和定义变量的类型:在程序中把小时数放在变量h中,把分钟数放在变量m中。这两个变量的类型可以是整型(本题中采用整型),也可以是实型。(3)确定所用算法:求560÷60的商数,在C语言中可以用整除的算法,语句是h=560/60;。求余数可用求余运算符%:560%60,其值放入变量m中的语句是:m=560%60;。(4)设计输出格式。若输出的形式定为:小时:分钟,则按此形式设计输出语句。(5)把以上内容放在主函数的一对花括号中。(6)编写程序如下:main(){inth,m;h=560/60;m=560%60;3 printf(″Theresult:%3d:%3d\n″,h,m);}运行结果是:Theresult:9:203.31【分析与解答】(1)确定变量的名字和定义变量的类型。若用a存放1500,用b存放350;用q存放商数,用r存放余数,所有变量应定义成int类型。(2)设计输入语句从终端输入1500和350;在输入语句之前,应当设计一个输出语句,用以提示输入。(3)可用整除求商数,结果放在变量q中。可用求余运算符%求两数之余数,结果放在变量r中。(4)设计输出语句。输出a、b、q、r。(5)把以上内容放在主函数的一对花括号中。本题的程序与3.30相似,请大家参考上题并根据本题的解释自己编程,并上机调试。3.32【分析与解答】(1)定义4个双精度变量a、b、c和ave,变量a、b、c分别存放读入的3个双精度数,ave存放它们的平均值。(2)设计输入语句,以及在此之前用于提示输入的(printf)语句。(3)设计求平均值的算法,把所求得的平均值放入变量ave中。(4)设计把变量ave中的数,从小数点后第二位数进行四舍五入的算法。现举例说明:若ave中的数为123.4644,为了保留此值小数点后一位,可用表达式:(int)(123.4644*10)/10.0;依次推算,为了保留此值小数点后二位,可用表达式:(int)(123.4644*100)/100.0;其他依此类推。(5)若要求对小数点后第二位数进行四舍五入,则可对原数加0.05后再进行以上运算。如要求保留123.4644小数点后一位且对第二位数进行四舍五入,可用表达式:(int)((123.467+0.05)*10)/10.0。注意:分母一定要用实数10.0而不能用整数10,否则就变成整除了;若要求保留123.4644小数点后两位且对第三位数进行四舍五入,可用表达式:(int)((123.467+0.005)*100)/100.0;其他依此类推。(6)设计输出语句。输出a、b、c和ave。(7)把以上内容放在主函数的一对花括号中。(8)编写程序如下:main(){doublea,b,c,ave;printf(″Entera,b,c:″);scanf(″%lf%lf%lf″,&a,&b,&c);ave=(a+b+c)/3;printf(″ave=%f\n″,ave);/*用以比较四舍五入前后的数据*/ave=(int)((ave+0.05)*10)/10.0;/*上句也可写成ave=(int)(ave*10+0.5)/10.0;*/printf(″a=%f,b=%f,c=%f,ave=%f\n″,a,b,c,ave);}3.33【分析与解答】(1)关于对变量中的数进行交换的算法请参考3.7题中的解释和《教程》中有关的例题。(2)定义4个整型变量a、b、c和t,变量a、b、c分别存放读入的3个整数,t用作临时存储单元。4 (3)设计输入语句,以及在此之前用于提示输入的(printf)语句。(4)输出a、b、c中的值,以便于比较。(5)交换的步骤如下:①把c中的值赋给t。②把b中的值赋给c。③把a中的值赋给b。④把t中的值赋给a。经过以上步骤,已按要求进行了交换。(6)输出a、b、c中的值。(7)编写程序如下:main(){inta,b,c,t;printf(″Entera,b,c:\n″);scanf(″%d%d%d″,&a,&b,&c);printf(″(1)a=%d,b=%d,c=%d\n″,a,b,c);t=c;c=b;b=a;a=t;printf(″(2)a=%d,b=%d,c=%d\n″,a,b,c);}第四章选择结构习题分析与解答一、选择题4.1【参考答案】A)4.2【参考答案】B)4.3【参考答案】A)4.4【参考答案】D)4.5【参考答案】C)4.6【参考答案】A)4.7【参考答案】B)4.8【参考答案】C)4.9【参考答案】D)4.10【参考答案】D)二、填空题4.11【参考答案】[1]非零[2]零4.12【参考答案】<、>、<=、>=、==、![KG-*2]=4.13【参考答案】[1]![2]&&[3][JB>1|][JB>1|]4.14【参考答案】[1]:![KG-*2](逻辑非)[2]:<、>、<=、>=(小于、大于、小于等于、大于等于)[3]:==、![KG-*2]=(等于、不等)[4]:&&(逻辑与)[5]:[JB>1|][JB>1|](逻辑或)。4.15【参考答案】!4.16【参考答案】[1]a=b或a1|]x[JB>1|]>44.17【参考答案】14.18【参考答案】[1]x<=0[2]14.19【参考答案】[1]3[2]2[3]24.20【参考答案】*#5 三、编程题4.21【分析与解答】相关内容请参考《教程》4.2节和4.4节。(1)改写如下:switch(a/10){default:m=5;break;case0:case1:case2:m=1;break;case3:m=2;break;case4:m=3;break;case5:m=4;break;};(2)本题中对a的判断条件有一定的规律可寻;关键是,在switch语句后的表达式中利用了a/10,从而简化了case标号。4.22【分析与解答】编写本题的程序,首先要解决如何计算学生当前的年龄(设存放实足年龄的变量是age)。(1)如果当前的月份大于生日的月份,则学生的实足年龄age=y1-y0。(2)如果当前的月份等于生日的月份,就要看日数,当前的日数大于或等于生日的日数,则学生的实足年龄age=y1-y0。(3)如果不满足以上的条件,就可断定当前的日期没有超过生日日期,就是说学生的年龄应当是age=y1-y0-1。以上3条,用C语言可以描述如下:if((m1>m0)[JB>1|][JB>1|](m1==m0&&d1>=d0))age=y1-y0;elseage=y1-y0-1;读者可以参考以上语句写出程序,也可以根据分析写出与此形式不同的语句和程序。4.23【分析与解答】(1)若输入的整数a是奇数,输出:oddnumber,是偶数输出:evennumber。(2)若一个a是偶数,它就能被2除尽,即a%2==0,输出evennumber;若是奇数,它就不能被2除尽,即a%2!〖KG-*2〗=0,输出oddnumber。读者可以参考以上给出的算法,写出相应的C语句,并编写出完整的程序。4.24【分析与解答】本题的主要算法是从3个数中找出最大的那个数。假定始终把最大的数放在变量max中。(1)假定a中的数最大,把a赋给max。(2)用b去和max比较,若b大于max,则把b赋给max;若不大于max,则什么也不做。(3)用c去和max比较,若c大于max,则把c赋给max;若不大于max,则什么也不做。(4)经过以上操作,max中已放入了a、b、c三个数中的最大数,输出max即可。读者可以参考以上给出的算法,写出相应的C语句,并编写出完整的程序。4.25【分析与解答】(1)本题已给出了非常明确的条件,只要写出正确的条件判断语句就可基本完成程序的编写。(2)由给出的函数可知,只有x的值在规定的范围内时,才求出y的值,因此程序应当对输入的x进行判断,若超过范围就不求y的值。(3)现以使用if[CD#*2]else语句为例写出程序供参考。main(){intx,y;printf(″Enterx:″);scanf(″%d″,&x);if(x>-5&&x<10){if(x==0)y=x-1;6 elseif(x<10&&x>0)y=x+1;elseif(x<0&&x>-5)y=x;printf(″x=%dy=%d\n″,x,y);}printf(″***END***\n\n″);}第五章循环结构习题分析与解答一、选择题(单选题)5.1【参考答案】D)5.2【参考答案】C)5.3【参考答案】B)5.4【参考答案】C)5.5【参考答案】C)5.6【参考答案】B)5.7【参考答案】D)5.8【参考答案】A)5.9【参考答案】D)5.10【参考答案】D)二、填空题5.11【参考答案】[1]5[2]4[3]65.12【参考答案】程序段无限循环,没有输出结果5.13【参考答案】-15.14【参考答案】115.15【参考答案】[1]d=1.0[2]k++[3]k<=n5.16【参考答案】[1]x>=0[2]x=1e-4){t=t/i;e+=t;i++;}(6)请读者自己对变量做出正确的定义,设计输出语句,完善程序;也可以参考此程序段,按照自己的思路独立地完成程序。(7)e的值应当是:2.71828。(8)根据以上分析,读者已不难用for循环来实现求e值的计算。(9)注意:在完成此程序时,不要对分母中的阶乘值进行单独计算,因为17!的值已超过long类型的最大值,更无法求到50!。5.19【分析与解答】(1)从1880年至2000年的年数可用一个for循环来取得。(2)对每一年,用以上指定的条件来进行判断,若满足条件即为闰年,进行输出。(3)按输出的要求,需要设一个变量用于统计一行中输出的个数,若在一行上已连续输出了5个年数,就需输出一个换行符,使下一个输出项在新的一行上开始;若用变量n来做此统计,则当表达式n%5==0时就应输出一个换行符,同时使n重新置0值。(4)若变量y代表年数,if语句的逻辑表达式可以写成如下:(y%4==0&&y%100!=0[JB>1|][JB>1|]y%400==0)(5)以下程序段供参考:for(y=1880;y<=2000;y++)if(y%4==0&&y%100![KG-*2]=0[JB>1|][JB>1|]y%400==0){printf(″%d″,y);n++;if(n%5==0){printf(″\n″);n=0;}}(6)请读者自己对变量做出正确的定义并赋初值,完善程序;也可以参考此程序段,按照自己的思路独立地完成程序。从1880年至2000年有30个闰年。5.20【分析与解答】(1)不难理解利用以下的for循环可以在一行上连续输出n个*号:for(i=1;i<=n;i++)printf(″*″);printf(″\n″);若n的值是6,则连续输出6个*号。(2)以上图形是在各行上输出数目不等的*号,只是*号的数目依次有规律地变化。在上半部分各行依次是1、3、5、7个,因此可以用以下的程序段来实现这样的输出:for(k=1;k<=7;k++,k++){for(i=1;i<=k;i++)printf(″*″);8 printf(″\n″);}在下半部依次是5、3、1个;因此可以用以下的程序段来实现这样的输出:for(k=5;k>=1;k--,k--){for(i=1;i<=k;i++)printf(″*″);printf(″\n″);}以上程序段从第一列起输出的结果如下:*************************现在我们已完成了在每行输出指定数目的*号。(3)输出结果与题目要求不同,它们的区别是:按题目每一行之前有不同的空格,而这里则是所有的行都在第一列上开始输出*号;所以接着就应当解决这一问题。(4)分析题目要求,每行第一个*号位置的缩进是有规律的,假定中间这一行第一个*号位置是在第一列,则可看出,第一至第三行的缩进分别是3、2、1个空格;而图形下半部的缩进数则刚好相反。这可在以上循环中添加输出连续空格的for循环来实现,对于上半部程序如下:b=3;for(k=1;k<=7;k++,k++){for(j=1;j<=b;j++)printf(″″);b--;for(i=1;i<=k;i++)printf(″*″);printf(″\n″);}(5)请读者在理解以上给出的示例的基础上,自己添加下半部空格的输出。第六章字符型数据习题分析与解答一、选择题6.1【参考答案】B)6.2【参考答案】D)6.3【参考答案】A)6.4【参考答案】A)6.5【参考答案】B)6.6【参考答案】D)6.7【参考答案】D)6.8【参考答案】B)6.9【参考答案】A)6.10【参考答案】A)6.11【参考答案】C)二、填空题9 6.12【参考答案】-16.13【参考答案】16.14【参考答案】ctype.h6.15【参考答案】06.16【参考答案】10A20B30C40D或:10A20B30C40D6.17【参考答案】7.29101.298AB或:7.29101.29AB6.18【参考答案】A7.29B101.2986.19【参考答案】ABC三、编程题6.20【分析与解答】(1)在进行字符输入时,即使一次输入了一行字符(最后用回车结束输入),字符也只能一个一个地读入。若ch已定义为char型变量,可以用以下的程序段来完成操作:ch=getchar();while(ch![KG-*2]=′\n′){……ch=getchar();}当读入的是一个回车符时,循环就结束。循环体内的“……”符号表示需要在循环体内完成的其他操作。(2)在循环内要求进行的操作之一是:输出每个字符以及与之对应的ASCII代码值。因此可用以下语句来实现。printf(″%c:%d″,ch,ch);(3)在循环内要求进行的另一个操作是:每行只能输出3对字符和与之对应的ASCII代码值。若n已定义为int型变量,则可用来作计数器;使n的初值为0,每输出一次,n的值增1,当n的值为3的整数倍时,额外输出一个换行符。例如:n++;if(n%3==0)putchar(′\n′);(4)把(2)和(3)中给出的语句放在循环体内,并按要求给出正确的定义和初值,就可完成题目所要求的操作。(5)也可以在while后的一对括号中来完成字符的读入,如while((ch=getchar())![KG-*2]=′\n′)。这时,循环内、外的“ch=getchar();”语句应当去掉。6.21【分析与解答】(1)一行字符的读入,请参照题6.20(1)和(5)中的解释。循环体内的“……”符号表示需要在循环体内完成的其他操作。ch=getchar();while(ch![KG-*2]=′\n′)10 {……ch=getchar();}(2)在本题中循环体内需要把读入的所有数字字符转换成一个整数。若用变量n来存放这个整数,为了保证有效的存放,应当把它定义成long类型。(3)要把输入的一串数字字符转换成一个整数,首先需要判断当前读入的字符是否是数字字符,若不是则什么也不做;若是,则进行以下操作:①把当前读入的一个字符转换成一个一位整数,这可由语句“d=ch-′0′;”来实现,在这里d是一个整型变量;②把d中的一位数归并到n的低位中,这可用语句“n=n*10+d;”来实现。这里所述的操作可由以下语句来完成:if(ch>=′0′&&ch<=′9′){d=ch-′0′;n=n*10+d;}if语句后一对括号中的判断表达式可以调用字符函数isdigit来实现:if(isdigit(ch)){d=ch-′0′;n=n*10+d;}if子句的两个语句可以合并成:n=n*10+ch-′0′;。(4)把(3)中的语句放入循环中:ch=getchar();while(ch![KG-*2]=′\n′){if(ch>=′0′&&ch<=′9′)n=n*10+ch-′0′;ch=getchar();}(5)请自己写出定义语句并赋初值。注意,最后输出n时,应当使用格式说明%ld,而不能使用%d。6.22【分析与解答】(1)行数的统计可通过统计输入的′\n′符的个数来完成。(2)统计的过程应当放在一个while循环体中;判断循环是否进行的条件可以用:((ch=getchar())==EOF)。若用整型变量n作为计数器对′\n′符进行统计,只要读入的字符是′\n′,则n增1。如:while((ch=getchar())![KG-*2]=EOF)if(ch==′\n′)n++;(3)EOF是在stdio.h中预定义了的标识符,在TURBOC的环境下,键入Ctrl+Z(即按住键盘上的Ctrl键,同时按字母Z键)后,敲Enter键,即输入了EOF。6.23【分析与解答】(1)本题要求的操作同样可在while循环中完成:while((ch=getchar())!=′\n′){……}(2)若用整型变量n作为计数器对小写字母进行统计,只要读入的字符是小写字母,则n增1。如:if(ch>=′a′&&ch<=′z′)n++;(3)在退出循环后,输出n的值。(4)请自己完善程序。6.24【分析与解答】(1)若图案的行数输入到变量L中。(2)按要求L决定了图形的行数,因此可通过循环来实现L行的输出:for(i=1;i<=L;i++)11 {……}循环体中的“……”号,代表输出L行的操作。(3)假定ch中存放了一个字符,我们知道,通过以下循环可以在一行上输出n个字符:for(j=1;j<=n;j++)putchar(ch);putchar(′\n′);注意,在循环后putchar(′\n′);语句不可少,它用以换行。(4)现在应当解决如何按要求给出每行输出的字符。由图分析,行数(或行号)为1时输出字符A,行数为2时输出字母B……若输出的字母放在变量ch中,行号取决于外循环的控制变量i,则输出的字母和行号的关系可用表达式:ch=′A′+i-1来表示。当i为1时ch中被赋予字母A,当i为2时ch中被赋予了字母B,其他依此类推。因此,在此表达式后,利用(3)中的循环就解决了各行上输出的字母。(5)按要求每行输出的字母的个数不同,第二行输出3个字母,第三行输出5个字母,第四行输出7个字母……(3)中for循环体的执行次数取决于n的值,也就是说n的值决定了每行输出字母的个数。其实,n的值与行号有着密切的关系:n=2*i-1,当i为1时n的值是1、当i的2时n的值是3、当i的3时n的值是5、当i的4时n的值是7。因此在(3)中for循环之前可用此表达式求出n的值。(6)总结以上分析,我们可得到以下的程序段:for(i=1;i<=L;i++){ch=′A′+i-1;n=2*i-1;for(j=1;j<=n;j++)putchar(ch);putchar(′\n′);}若所用的变量都已正确定义,通过输入L的值为5,则程序段在第一列起有以下的输出结果:ABBBCCCCCDDDDDDDEEEEEEEEE和题目的要求比较已趋接近,不同的是在每行没有适当的缩进。(7)现在来解决每行的缩进问题。由题中给出的图形可知,若指定输出5行,第一行缩进5个空格,第二行则缩进4个空格,第三行则缩进3个空格,第四行则缩进2个空格,第五行则缩进1个空格。这同样可以由以下的for循环来实现:for(k=L;k>=i;k--)putchar(′′);把此循环放在i控制的循环体内、输出每行字符的循环之前即可。(8)请读者自己补充有关的include行、语句和变量的定义,以完成整个程序。注意,如果有能力可在某些地方作些简化。第七章函数习题分析与解答一、选择题7.1【参考答案】C)7.2【参考答案】C)7.3【参考答案】B)7.4【参考答案】C)7.5【参考答案】A)12 7.6【参考答案】D)7.7【参考答案】A)二、填空题7.8【参考答案】127.9【参考答案】9.0(或9.000000)7.10【参考答案】47.11【参考答案】[1]n=1[2]s7.12【参考答案】[1]<=y[2]z*x7.13【参考答案】[1]1[2]s*i[3]0[4]f(k)三、程序调试和编程题7.14【分析与解答】(1)fun函数判断传给形参n的数是否为素数,若是函数返回1,否则返回0。(2)函数的原意是用变量yes作为判断n是否为素数的标志,是素数,其值为1,否则为0。而所给函数的实际流程却不能实现这一功能,例如,若n的值为15(明显不是素数)时,在for循环中,当k的值为3时,就会执行if子句,yes得0,但for循环并没有终止,接着k为4时就会执行else子句,又使yes得1,由此可见此程序段并不能准确地判断一个数是否为素数;最后确定yes为何值的是for循环的终止值n/2,当n为15时,k的值为n/2等于7,在循环体内将又一次执行else子句,使yes得1,这时循环结束,函数返回1。由此可见所给fun函数不能起到预想的作用。(3)由上分析可知,对于n的值为15时而言,问题是在一旦yes的值为0,已判断n中的值不是素数时,没有及时退出循环,返回0;因此,若在if子句中添加一条语句:break;就能解决这一问题,把if语句改写如下:if(n%k==0){yes=0;break;}elseyes=1;(4)在所给fun函数中,当n的值为2、3时(都是素数),因为n/2的值为1(大于k中的2),所以不会进入for循环,而直接执行return语句,细心的读者应该可以发现,这时yes没有赋过值,也就是说,返回的是一个不确定的值,这将会导致错误;因此,应当在定义语句中给yes赋初值1:intk,yes=1;至此fun函数能正确运行。(5)总结:因为一旦if语句中的表达式:n%k==0的值为1(即可被某数整除),则可以确定n不是素数,因此即可返回,不必再执行函数其他部分,if子句可改成:if(n%k==0){yes=0;returnyes;}elseyes=1;也可简化成:if(n%k==0)return0;elseyes=1;又可进一步不用变量yes,并去掉else,简化成(请参考例7.4):for(k=2;k<=n/2;k++)if(n%k==0)return0;return1;7.15【分析与解答】(1)若用整型变量c存放余数,则求a被b除后的余数可用表达式:c=a%b。(2)本题要求编写函数mymod用以求a被b除后的余数即:13 c=mymod(a,b);(3)只要把a%b作为函数值返回即可完成操作(请参考例7.1):intmymod(inta,intb){returna%b;}(4)总结:本题在算法上十分简单,只是要求读者能够掌握编写函数的基本知识。7.16【分析与解答】(1)本题所要采用的算法是累加。分析可见,所有累加项的分子都是1,而分母部分逐项增1;只是累加项的符号交叉变化。因此处理好符号的变化是完成操作的关键之一。(2)若函数名为funa,传送到函数的参数是整型值,假定形参命名为n;函数的返回值应当是浮点型,为此函数的首部可以是:doublefuna(intn)(3)接着写函数体。累加放在一个for循环中来完成,若循环控制变量为k,可利用循环控制变量作为累加项t的分母,累加值放在add中:for(k=1;k<=n;k++){……t=s*1.0/k;add=add+t;}此处,s用作符号变量,在1和-1之间交叉变化,乘以1.0/k后,t的值也将按要求变化符号。注意,表达式1.0/k不可以写成1/k,因为每一项的绝对值必定是小于1的小数。(4)现在需要确定s的值。最简单的可用表达式:s=-s来实现(请参考例5.2),若赋值号右边s中的值为-1,则赋值号左边s中的值就得1;若赋值号右边s中的值为1,则赋值号左边s中的值就会得-1;则每循环一次就使s改变了一次符号。当然还可有多种方法。把以上表达式添加到循环体中:for(k=1;k<=n;k++){s=-s;t=s*1.0/k;add=add+t;}(5)最后注意应当给各变量赋以适当的初值,并返回函数值。(6)请编写主函数。当传给形参的值为10时,函数的返回值应当是:0.645635。(7)总结:本题的算法并不复杂,但是需要读者掌握编写函数的基本知识。掌握需要传入函。数的参数及其类型,掌握需要返回的值及其类型。在此基础上,其他方面与先前在主函数中编写的程序没有什么区别。7.17【分析与解答】(1)此题与7.18相似。函数的返回值为浮点型,函数只有一个形参,为整型。(2)函数的基本算法是累加,只是除第一项外其余各项都用减法;每一项的分子都是1,分母部分为k2,k的值逐项增1,由2变化到m。因此,算法可以用一个循环来实现。(3)当m的值为12时,函数值应是:0.435023。7.18【分析与解答】(1)若函数取名为fun,按题意,x作为形参,由调用函数传入,其类型不应当用整型;表达式x2-5x+4的值作为函数值返回,函数值的类型应为浮点型。因此,很容易写出函数:doublefun(doublex){returnx*x-5*x+4;}(2)若在调用函数时,x和y2已正确定义,且x已有确定的值,则可用以下函数调用语句得14 到y2的值:y2=fun(x+15);(3)同样,若在调用函数时,x和y3已正确定义,且x已有确定的值,则可用以下函数调用语句得到y3的值:y3=fun(sin(x));注意,因为在程序中调用了C语言提供的库函数sin,因此应当在程序的最前面包含以下命令行:#include″math.h″(4)参考(2)和(3)应不难写出求y1的语句,请读者自己完成。(5)y1的值应是:-2.0。当x的值为5时,y2的值应是:304.0。当x的值为0.5时,y3的值应是:1.832721。(6)总结:①本题已给出了函数需要求值的表达式,读者只需确定函数的类型和形参的类型,就可以写出函数,就像例7.1中求两数之和的函数一样简单。②在给定了函数之后,调用函数时,函数的实参应当是一个与形参类型一致的任意合法的表达式。例如,可以是常量、算术表达式,也可以是函数等。就像例7.1中求两数之和的add函数一样,可以用add(3,4);来求3+4;当x、y有确定值时,可以用add(x*x,y*y);来求x2+y2;当x、y有确定值时,可以用add(sin(x+y),cos(x+y));来求sin(x+y)+cos(x+y),这同样可以通过add(sin(add(x,y)),cos((add(x,y)));来求得。第八章指针习题分析与解答一、选择题8.1【参考答案】A)8.2【参考答案】B)8.3【参考答案】B)8.4【参考答案】C)8.5【参考答案】B)8.6【参考答案】B)8.7【参考答案】C)8.8【参考答案】D)8.9【参考答案】B)8.10【参考答案】C)8.11【参考答案】C)8.12【参考答案】C)二、填空题8.13【参考答案】1108.14【参考答案】718.15【参考答案】char*p,*p=ch,p=&ch;scanf(“%c/n”p,);ch=*p;p=&ch;printf(“%c/n”,*p);8.16【参考答案】*s=*(p+3),*(s-2),50,*s=*(a+1),2,10,20,30,40三、编程题8.17【分析与解答】(1)若函数名为fun,按题意,函数不返回函数值;函数的形参需要接受传送过来的两个浮点数,因此需要有两个double类型的形参;另外要把它们的和值与差值,通过形参传送回去,这就要求有两个double类型的形参指针,接受传送过来的地址,以便通过指针把和值与差值传送给所指的主函数中的变量。因此函数的首部应当是:15 voidfun(doublea,doubleb,double*p1,double*p2)这里,a、b、p1、p2是自己取的名。(2)假设把a、b的和值传送给p1所指的存储单元,可用语句:*p1=a+b;把a、b的差值传送给p2所指的存储单元,可用语句:*p2=a-b;。(3)因此函数可写成:voidfun(doublea,doubleb,double*p1,double*p2){*p1=a+b;*p2=a-b;}(4)在主函数中,若有定义语句:doublex,y,z1,z2;,且x、y已赋值,则调用fun函数的语句可以是:fun(x,y,&z1,&z2);。(5)总结:本题所要求的算法极简单,但它要求有两个值返回,用return语句就不可能返回两个函数值。要求读者能利用形参指针把要求的值间接地传回调用函数。8.18【参考答案】(1)若函数名为maxandmin,按题意,函数不返回函数值;函数将接受3个数(假定为int类型),并需要通过指针指向主函数中的两个int型变量,以便把最大值和最小值放入指针所指的存储单元中。因此函数的首部应当是:voidmaxandmin(inta,intb,intc,int*pmax,int*pmin)(2)函数体中需要实现求3个数的最大值和最小值的算法,此算法应当在学习第四章时已经掌握(可参考例4.2和习题4.24)。如果把a、b、c中的最大值暂时放在max中,把最小值放在min中,可用以下算法找到最大值:①假定a中的数最大,把a赋给max。②用b去和max比较,若b大于max,则把b赋给max;若不大于max,则什么也不做。③用c去和max比较,若c大于max,则把c赋给max;若不大于max,则什么也不做。④经过以上操作,max中已放入了a、b、c三个数中的最大数。⑤可模仿以上算法找到最小值:min=a;if(b行;也可用:ch>[KG-*3]=′0′&&ch<[KG-*3]=′9′。(3)若用num数组元素来进行统计,当ch中是数字“0”时,使num[0]增1、当ch中是数字“1”时,使num[1]增1……num的下标表达式可用:ch-′0′。(4)注意,在定义数组时,数组的大小应符合使用的要求。在利用数组元素作为计数器时,不要忘记首先应该给数组元素赋0值。(5)总结:通过本题的编程,要求掌握利用数组元素作为计数器的基本算法。9.28【分析与解答】本题的编程请参考例9.8。(1)若有以下10个整数:0123456789要求从第5个元素依次向前移,则移动之后的数列应该是:012456789第5个元素不是指下标为5的元素,而是指排列的顺序,对此数列而言是指数值为4的那个。(2)完成移动后,数列中的数据个数减1。(3)若进行指定操作的函数名为moves,则函数的首部可如下:voidmoves(int*a,intn,int*m)这里a用以指向一维数组的首地址,n接受开始移动的元素的位置,m指向主函数中存放元素个数的变量,因为没有函数值返回,因此函数的类型定义为void。(4)可用以下for循环完成指定的移动:for(i=n-1;i<*m;i[KG-*3]+[KG-*3]+)a[i-1]=a[i];17 注意,应当先把第n个元素(下标为n-1)移到第n-1个元素(下标为n-2)的位置上,依次从前到后向前移动。(5)完成移动之后,应使m所指变量中的值减1,表示数列中的数据少了一个;这可由于句:*m=*m-1;来完成。(6)可设计一个输出函数,在移动前、后调用此函数输出数组中的数据,以便验证操作是否正确。若输出函数名为:outarr,则函数首部可写成:voidoutarr(inta[],intnum)形参a指向待输出的数组,num接受数组中元素的个数。输出操作可由一个for循环来完成:for(i=0;i[KG-*3]=j;i--)a[i+1]=a[i];(5)第三个步骤是把x放入a[j]中:a[j]=x;(6)第四步是使存放数据个数的变量中的数增1:*n=*n+1;插入过程到此结束。(7)可利用习题9.28中的outarr函数,在插入前和插入后两次输出数组元素,以判断操作是否正确。(8)请编写主函数,定义所需的数组和变量,给数组输入一组有序数,正确调用函数。(9)请按题目要求至少对程序运行3次,判断程序是否在各种情况下都能得到正确的结果。(10)总结:插入算法是程序设计中的一种最基本的算法,希望读者在理解的基础上编写程序。9.32【分析与解答】19 (1)若函数名为change,函数首部如下:voidchange(intx,int*a,int*n)形参x中存放一个待转换的十进制数,指针a指向一个一维数组,数组中每一个元素中存放一个0或1代表一位二进制数,指针变量n指向一个整型变量,其中存放在一维数组中二进制位的个数。(2)函数中定义一个指针变量s,并把a所指的数组的首地址赋给它以便保留。把x每次被2除后的余数放在a当前所指的数组元素中,然后移动指针a指向下一个元素,并使x的值除2;重复此过程,直到x的值为0。可用以下的while循环来进行转换:s=a;while(x){*a=x%2;a+[KG-*3]+;x=x/2;}退出循环时,已把转换后的二进制数的每一位上的数放入主函数的数组元素中,但是应当注意,在a[0]中放的是二进制数的最低位,最后放入的是最高位。例如,整数8转换成的二进制数为100,则在a[0]、a[1]中存放的是0,而a[2]中存放的是1。(3)函数中最后用:*n=a-s;把存放在一维数组中二进制位的个数放入n所指的变量中。因为s已指向主函数中数组的第一个元素(下标为0);在循环中,指针a不断后移,最后指向存放二进制数最高位的元素;所以a-s的值就是已存入数据的元素的个数。(4)在主函数中输入待转换的十进制数,调用change函数后输出数组元素中的值,注意,因为在a[0]中放的是二进制数的最低位,因此输出的顺序应该从a[n]到a[0]。9.33【分析与解答】(1)若函数名为getone,形参指针a指向主函数中存放指定数据的数组。函数的首部如下:voidgetone(inta[])(2)函数中变量x用来存放得到的一个随机数,变量n用来存放数组中已放入的不同的随机数的个数,变量i用作下标变量。(3)所有的工作在一个while循环中完成:while(n<15){……}当不同的随机数的个数n的值等于15时退出循环。(4)在以上while循环中需要进行以下4项步骤:①x=rand()%20;得到一个小于20的随机整数。②i=0;准备从下标为0的元素开始去查找数组中是否有与x相同的数,若没有,就把x中的数加入到数组中(放在最后),若有,就什么也不做。③用以下while循环从头到尾去检查数组中是否有与x值相同的元素:while(istrlen(s)||pos<[KG-*3]=0)return0;(5)在删除操作前,应该纪录下被删的那个字符,以便作为函数值返回:c=s[pos-1];。(6)请编写主函数,定义所需的数组和变量,输入字符串和输入删除的位置,调用函数后输出删除后的字符串,并对各种情况进行测试,以检查程序是否正确。(7)总结:删除算法是程序设计中的基本算法,虽然,在细节的要求上可能有所不同,例如对于一维数组中的数据,需要变动数据的个数,而字符串则要求重新设置字符串结束标志。10.22【分析与解答】(1)若函数名为dels,函数首部如下:voiddels(char*s)形参s是一个指向字符串的指针变量。(2)函数中先完成删除字符串中最后的所有空格。这只要在最后一个非空格字符的后面加上字符串结束标志(′\0′),就使得最后所有的空格都被删除了。但完成这一操作需要通过三个步骤:第一,找到字符串的最后一个空格的位置;第二,往回找到字符串的最后一个非空格的位置;第三,在最后一个非空格的位置的后面加上字符串结束标志。①找到字符串的最后一个空格的位置可用以下语句来完成,函数中另定义一个指针变量p,并把s的值赋给它,使它指向字符串的开始。以下while循环和语句使p指向最后的一个字符(′\0′的前面)。while(*p)p++;p--;也可以调用求字符串长度的库函数:p=s+strlen(s)-1;使p指向最后的一个字符。②往回找到字符串的最后一个非空格的位置可用以下语句来完成:while(*p==′′)p--;以上while循环中,只要p所指存储单元中是空格,就使p移动指向前一个字符,当p所指存储单元中不是空格时立刻退出循环;这时p指向字符串中最后一个非空格字符。③请读者自己把字符串结束标志放在最后一个非空格的位置的后面。(3)函数接着删除字符串中的前导空格。这只要把前导空格后的第一个非空格字符移到字符串的开头,其后的字符依次前移即可。完成这一操作,首先需要知道第一个非空格字符的位25 置(下标);然后把其后的字符串移到字符数组的开头。若用变量i来表示第一个非空格字符的下标,i的初值为0,以下循环可以完成此操作:while(s[i]==′′)i++;只要s[i]是空格,就使i增1,直到遇到第一个非空格字符。以下循环把前导空格后的第一个非空格字符移到数组的开头,其后的字符依次前移,直到遇到字符串结束标志。变量j的初值为0,移动完成后,j就是最后一个字符后面元素的下标。请读者自己把字符串结束标志放在其中。while(s[i]){s[j]=s[i];j++;i++;}(4)请自己编写主函数,给出定义语句。在调用dels函数之后,建议用以下语句输出结果:printf(″\nTheresult:\n%s″,str);printf(″****END″);最后的****END紧跟在字符串之后进行输出,以便观察字符串最后的空格是否已删除。(5)总结:在dels函数中用了移动指针和改变下标两种方法,来引用字符串中的元素。无论是删最后的空格或删前导空格,都可用这两种引用的方法。第十一章对函数的进一步讨论习题分析与解答一、选择题11.1【参考答案】D)11.2【参考答案】B)11.3【参考答案】A)11.4【参考答案】C)二、填空题11.5【参考答案】IJKLEFGHABCD11.6【参考答案】711.7【参考答案】811.8【参考答案】[1]*(s+j);[2]i+1;[3]i11.9【参考答案】1711.10【参考答案】[1](*fun)(double)[2](*fun)(a+i*h)[3]mypoly三、编程题11.11【分析与解答】(1)无论命令行的内容是什么,总是要求程序需要输出字符串中的一部分连续的字符,因此可将这一部分的功能放在output函数中完成。函数的首部如下:output(char*s,intb,inte)其中,s指向字符串,b为从s中开始输出的字符的下标,e为结束输出的字符的下标。只要确定了开始输出的字符的下标和结束输出的字符的下标,在一个for循环中就可以完成输出。请自己完成此函数体。(2)在主函数中读入一行字符串放在s数组中,求出s串的长度放在len变量中。另外用变量n存放要输出的字符的个数。(3)主函数的首部写成:main(inta,char*[KG-*3]c[])其中的第一个参数a将存入命令行中的字符串的个数,当命令行中没有其他参数时,a的值为1;因此按题目要求,此时输出字符的个数n应等于10。(4)主函数中的第二个参数是一个指向字符串的指针数组。当命令行为:outch-2这时,c[0]中存放了字符串outch的首地址,c[1]中存放了字符串-2的首地址。存储单26 元*[KG-*3]c[1](即*(c[1]+0)或c[1][0])中是字符-;存储单元*(c[1]+1)(或c[1][1])中是字符2。同理,当命令行为:outch+6这时,c[1]中存放了字符串+6的首地址。存储单元*[KG-*3]c[1](即*(c[1]+0))中是字符+;存储单元*(c[1]+1)中是字符6。(5)根据以上分析,可用以下语句来得到待输出的字符个数放在n中:if(a>1)n=*(c[1]+1)-′0′;elsen=10;(6)按题目规定,如果a的值为1或者*[KG-*3]c[1]中的字符是′-′号时,输出s字符串的最后若干字符,这时调用output函数,把s数组的地址传给形参指针s,把开始输出的元素的下标len-n传给形参b,把最后一个输出的元素下标len-1传给形参e。可用以下语句来实现:if(a==1||*[KG-*3]c[1]==′-′)output(s,len-n,len-1);(7)如果*[KG-*3]c[1]中的字符是′+′号时,将从字符串s的最前面开始输出,除了把s数组的地址传给output函数的形参指针s外,把开始输出的元素的下标0传给形参b,把最后一个输出的元素下标n-1传给形参e。if(*[KG-*3]c[1]==′+′)output(s,1,n-1);(8)总结:读者按以上所述写出相应的代码,存入OUTCH.C文件。在TurboC的环境下进行编译调试、运行,生成一个OUTCH.EXE文件。最后退出TurboC,在OUTCH.EXE文件所在目录下,打入如题所示的命令行,在程序运行时输入一字符串,观察运行结果是否正确,如果不正确,则需回到TurboC中进行修改。11.12【分析与解答】习题9.32已经给出了把一个整数转换为二进制数的算法,这是一个把十进制整数不断被2除的过程,每次被2除的余数即是一个二进制位上的数(1或0)。转换的方法是一样的,只是每次转换的数被2除,这可用递归来完成,递归函数的部分内容可表示如下:outbinary(inta){intd;d=a%2;……outbinary(a/2);……}当a的值不为0时,递归继续;结束递归的条件应当是a等于0。因此应该在函数中给出递归进行的条件:outbinary(inta){intd;d=a%2;if(a!=0){outbinary(a/2);……}}剩下的是输出每次得到的二进制位上的数。可以在d=a%2;之后立刻输出d,但是先得到的余数是二进制数的低位,这样输出的二进制数与正确的数是逆着的;因此要求能把先得的数后输出才是正确的转换后的二进制数。把以上函数写成:27 outbinary(inta){intd;d=a%2;if(a![KG-*4/5]=0){outbinary(a/2);printf(″%d″,d);}}这就达到了后得的数先输出的目的。11.13【分析与解答】(1)在主函数中输入n的值。(2)这是一个累加的过程,若从n开始逐个累加,而每次的加数比前一个减1,可用以下函数实现:sum(intn){returnn+sum(n-1);}(3)递归算法的主要一条是需要有递归结束条件,否则递归会无限进行。由题目可知,当累加项为0时,累加应当结束。所以在函数中应该添加条件语句:sum(intn){if(n![KG-*4/5]=0)returnn+sum(n-1);}11.14【分析与解答】以上F(n)函数已经给出了明确的递归算法,所以只要把它用C语言来表达就可以了:f(intn){if(n==0||n==1)return1;return(f(n-1)+f(n-2));}+第十二章C语言中用户标识符的作用域和存储类习题分析与解答一、选择题12.1【参考答案】B)12.2【参考答案】B)12.3【参考答案】A)12.4【参考答案】C)12.5【参考答案】D)12.6【参考答案】B)12.7【参考答案】A)12.8【参考答案】D)二、填空题12.9【参考答案】2,5,1,2,3,-212.10【参考答案】2468第十三章编译预处理和动态存储分配习题分析与解答28 一、选择题13.1【参考答案】A)13.2【参考答案】C)13.3【参考答案】B)13.4【参考答案】C)13.5【参考答案】D)13.6【参考答案】D)13.7【参考答案】D)二、填空题13.8【参考答案】ar=9ar=9ar=1113.9【参考答案】[1]int*[2]s[3]*b三、编程题13.10【分析与解答】(1)此命令行如下:#defineMYALPHA(a)(((a)>=′A′&&(a)<=′Z′)||((a)>=′a′&&(a)<=′z′))(2)可用以下程序段来验证,此处s中存放了字符串,num中统计大、小写字母的个数:for(i=0;inext[2]m>p->data(或p->datanum或(*(ps+i)).num等形式引用主函数st数组元素中的成员,因为在函数中,形参ps是一个指针变量。(4)在readrec函数中,可以在一个for循环中输入结构体数组每个元素中的数据:for(i=0;inum,(*(ps+i)).name);当然输出项也可以写成:ps[i].num、ps[i].name。和在readrec函数中一样,用一个内嵌的for循环输出四项成绩,最后输出ps[i].ave。(7)在readrec函数中请添加输入提示,以便正确输入;在writerec函数中请添加有关的输出文字,使输出内容更清晰。(8)请自己编写主函数,写出定义语句和调用语句。(9)总结:本题的算法十分简单,仅是输入和输出,但要求能够掌握结构体数组在函数之间的数据传递,要求对结构体变量中成员能正确引用。在调试程序时,为了便于输入,可把define行改为:#defineN2这样只需输入两组数据,也同样可以对程序的正确性进行验证。14.13【分析与解答】(1)本题所要求编写的函数可参考本章习题14.10。(2)为了能对链表进行操作,必须建立链表,建立链表的函数可参考本章习题14.11。输出链表可参考教材第四章例14.7。(3)本题第二个函数要求返回的是最大值所在结点的地址,若此函数名为maxadd,函数首部可以如下:structnode*maxadd(structnode*head)此处,structnode是链表结点的类型。函数的基本算法和习题14.10基本相同,只是需要另定义一个基类型为structnode的指针,假定此指针名为pmax,则每次当把最大值放入m时,同时也把此结点的地址放入pmax中,最后返回pmax即可。基本的程序段如下:p=head->next;m=p->data;pmax=p;for(p=p->next;p;p=p->next)if(mdata){m=p->data;pmax=p;}(4)在主函数中也需要定义一个基类型为structnode的指针,若定义该指针名为:maxnode,则应当把函数maxadd的返回值赋给它:maxnode=maxadd(head);,此处head指向链表的头结点。可用:printf(″%d\[KG-*3]n″,maxnode->data);输出maxnode所指结点中的数据域,以验证maxnode是否指向链表中的最大值所在的结点。(5)总结:函数的类型可以是指向结构体的指针类型,也可以是结构体类型。读者也可编写一个函数,把最大值所在的结点放在一个结构体变量中作为函数值返回。第十五章位运算习题分析与解答一、选择题15.1【参考答案】D)15.2【参考答案】A)31 15.3【参考答案】B)15.4【参考答案】A)二、填空题15.5【参考答案】11110000;15.6【参考答案】a=a&0;15.7【参考答案】a=a|07777;15.8【参考答案】a=a|0177400;15.9【参考答案】a=012500>>2;15.10【参考答案】ch=ch|32;第十六章文件习题分析与解答一、选择题16.1【参考答案】B)16.2【参考答案】C)二、填空题16.3【参考答案】[1]3[2]!feof(f1)[3]f2[4]fclose(f1)[5]fclose(f2)16.4【参考答案】[1]fopen(fname,″w″)[2]ch16.5【参考答案】[1]″r″[2](!feof(fp))[3]fgetc(fp)16.6【参考答案】AAAABBBBCCCC三、编程题16.7【分析与解答】(1)因为指定为10个字符串,并假定每个字符串不会超过20个字符,为方便起见,在程序的前面定义以下命令行:#defineN10#defineM22(2)假定字符串输出到名为myfile.dat的文件中;程序中字符串放在名为s的字符数组中。(3)按照题义程序应有以下步骤:①首先为“写”而打开文件:fp=fopen(″myfile.dat″,″w″);②从终端输入字符串,输入一个字符串,就立即把它输出到文件中,因为有N个字符串,因此需要放在循环中来完成:for(i=1;i<[KG-*3]=N;i[KG-*3]+[KG-*3]+){printf(″Enterastring:″);gets(s);fputs(s,fp);fputc(′\[KG-*3]n′,fp);}函数fputs(s,fp)把刚从终端读入的字符串s输出到fp所指的文件中。请注意函数fputs(s,fp)的输出特点:在输出时它将只输出字符串中的字符而不输出字符串的结束标志到文件中,因此在文件中,连续输出的字符串之间将头尾相接,在文件中储存了一个接一个的字符,分不清哪是哪个字符串,其结果就使得不再可能从其中读入各个字符串了。为了分清各个字符串,因此在每输出一个字符串时,就接着输出一个′\[KG-*3]n′符,以区分各字符串,在此由fputc(′\[KG-*3]n′,fp);来完成。③关闭因“写”而打开的文件:fclose(fp);④为“读”而打开文件:fp=fopen(″myfile.dat″,″r″);32 ⑤从文件中输入字符串并把刚读入的字符串输出到终端屏幕:fgets(s,M-1,fp);while(!feof(fp)){c=s[strlen(s)-1];if(c==′\[KG-*3]n′)s[strlen(s)-1]=0;puts(s);fgets(s,M-1,fp);}fgets(s,M-1,fp)从fp所指文件中输入M-1个字符串放入s的地址中;如果在未读满M-1个字符之前读到了一个换行符,则结束本次操作,系统在字符串最后自动加入′\0′。注意,如果未读满M-1个字符,这时已把换行符读入,并作为字符串最后一个字符(在′\0′之前)。在此,先判断s[strlen(s)-1]是否为′\[KG-*3]n′,若是,则用语句:s[strlen(s)-1]=0;来消除此换行符,把字符串结束标志前移了一个位置,strlen(s)求出字符串的长度,strlen(s)-1是最后一个字符的下标。然后用puts(s);进行输出。fgets(s,M-1,fp);作为循环体内最后的语句,当读到文件的结束标志时,函数feof(fp)的值为1,循环立即结束。⑥关闭文件:(4)请读者自己完成其他相关的语句和定义。(5)总结:在用fgets和fputs函数进行输入和输出时,请注意它们的特点,以便使字符串的输入和输出正确进行。16.8【分析与解答】(1)按题意程序需要两次把数据输出到文件中,第一次是把从键盘输入的数据输出到文件中,第二次是把修改过的数据再次输出到文件中。为此编写一个函数来完成此项任务,以避免重复编码。同理,程序需要两次从文件中输入数据,因此也用一个函数来完成此任务。另外程序需要两次把从文件输入的数据输出到屏幕上,因此也用一个函数来完成。(2)因为指定为10个双精度数,为方便起见,在程序的前面定义以下命令行:#defineN10(3)为了便于操作,无论是输入的数据还是输出的数据,程序都把它们放在一个数组中。(4)若程序把输出的数据放在mybin.dat文件中,在函数binput中把数据输出到mybin.dat文件,binput函数的首部应是:binput(double*a)形参a是一个基类型为double的指针,它接受存放数据的实参数组的首地址。函数中需要包含以下步骤:①打开输出文件:fp=fopen(″mybin.dat″,″wb″);fp是文件指针,mybin.dat是输出文件名,″wb″规定此次是为“写”而打开一个二进制文件。②输出数据到二进制文件中:for(i=0;i