参考资料:高教版《全国计算机等级考试二级教程——C语言程序设计》
P69 填空题
5.15
题目:
有以下程序段:
s = 1.0;
for( k = 1; k <= n; k++ )
s = s + 1.0 / ( k * ( k + 1 ) );
printf( "%f\n", s );
请填空,使下面的程序段的功能与之完全等同。
s = 0.0;
[1];
k = 0;
do
{
s = s + d;
[2];
d = 1.0 / ( k * ( k + 1 ) );
}
while([3]);
printf( "%f\n", s );
题解:
相比原来的程序段,给出的程序段缺少的部分应实现的功能如下:
在第一次循环时使s = 1.0;
每循环一次,k加1;
判断条件,即for语句中的k <= n这部分。
所以应该这样填写:
- 观察程序段发现没有给d赋值,而且在第一次循环的时候要让s = 1.0,所以[1]处应该是d = 1.0;
- 在[2]处填写k++实现每循环一次k加1的功能;
- 由于do-while循环的条件是:while后面的语句为真时,执行循环体,所以[3]处直接填入k <= n。
最终的程序段如下:
s = 0.0;
d = 1.0; //给变量d赋值1.0
k = 0;
do
{
s = s + d;
k++; //每循环一次,k的值增加1
d = 1.0 / ( k * ( k + 1 ) );
}
while( k <= n ); //判断条件
printf( "%f\n", s );
5.16
题目:
以下程序的功能是:从键盘上输入若干学生的成绩,统计并输出最高成绩和最低成绩,当输入负数时结束输入。请填空。
(注:本人轻度代码洁癖,所以稍微改下原题的代码,最核心的部分没动,只是改了空行,左花括号,缩进,main函数的写法,加return 0等。总之改了也不影响题意,当然如果介意的话可以私信我。)
#include <stdio.h>
int main( void )
{
float x, amax, amin;
scanf( "%f", &x );
amax = x;
amin = x;
while( [1] )
{
if( x > amax )
amax = x;
if( [2] )
amax = x;
scanf( "%f", &x );
}
printf( "\namax = %f\namin = %f\n", amax, amin);
return 0;
}
题解:
首先题目中提到“当输入为负数时结束输入”,所以控制循环的表达式应该有判断输入是否为负的情况。题目中还提到要输出最低成绩,所以应该有判断最低成绩的语句。将实现这个功能的语句分别填到[1]和[2]处就可以了。
最终的程序如下:
#include <stdio.h>
int main( void )
{
float x, amax, amin;
scanf( "%f", &x );
amax = x;
amin = x;
while( x >= 0 ) //判断输入是否为负数,如果是就结束输入
{
if( x > amax )
amax = x;
if( x < amin ) //记录最低成绩
amax = x;
scanf( "%f", &x );
}
printf( "\namax = %f\namin = %f\n", amax, amin);
return 0;
}
P69 编程题
5.17
题目:
编写程序,求1-3+5-7+……-99+101的值。
题解:
应该设置一个变量k和一个变量j,每循环一次k的值加1,i的值加2,当i大于101的时候退出循环。当循环次数为奇数(即k的值为奇数)时,j加i,当循环次数为偶数(k的值为偶数)时,j减i。
程序如下:
#include <stdio.h>
int main(void)
{
int i = 1, j = 0, k = 1;
//这个for循环用来计算表达式的值
for( i = 1; i <= 101; i += 2 ) //每循环一次,i的值增加2,当i大于101时结束循环
{
//循环次数为奇数时,j加i;循环次数为偶数时,j减i
if (k % 2 == 0)
j -= i;
else
j += i;
k++; //变量k用于计算循环次数
}
printf( "%d", j );
return 0;
}
输出:
51
5.18
题目:
编写程序,求e的值,e≈1+1/1!+1/2!+1/3!+1/4!……
- 用for循环,计算前50项。
- 用while循环,要求直到最后一项的值小于10^-6。
题解:
这里还没学到函数的递归调用,其实算阶乘可以用函数的递归调用来实现,但这里就根据章节和题目要求用循环来实现了。精度要求比较高,就使用double类型了。
第一问:
计算前五十项,最后一项就是1/49!。因为公式的第一项和第二项都是1,所以初始化变量的时候应该让e等于1。
程序如下:
#include <stdio.h>
int main(void)
{
double e = 1, j = 1; //公式中第一项为1,所以将e的值初始化为1
//这个for循环用来计算阶乘,进而通过阶乘的倒数的和估算e的值
for (int i = 1; i <= 49; i++)
{
j = j * i; //计算阶乘
e += 1 / j; //通过计算阶乘的倒数的和估算e的值
}
printf("%lf", e);
return 0;
}
输出:
2.718282
第二问:
要求使用while循环,那么判断条件就是最后一项的值小于10^6。
跟上一问差不多的办法。
程序如下:
#include <stdio.h>
int main(void)
{
double e = 1, j = 1, s = 0, i = 1;
while ((1 / j) >= 1e-6) //判断最后一项的精度是否小于10^-6
{
j = j * i; //通过这一句和下面的"i++"计算阶乘
s = 1 / j; //将阶乘保存在变量中(这一句也可以不写,把下一句改成“e += 1 / j就行”
e += s; //计算e的估计值
i++;
}
printf("%lf", e);
return 0;
}
输出:
2.718282
5.19
题目:
编写程序,输出从公元2000年至公元3000年所有闰年的年号,每输出10个年号换一行。判断公元年是否为闰年的条件是:
- 公元年数如能被4整除,而不能被100整除,则是闰年。
- 公元年数能被400整除也是闰年。
题解:
使用for循环,判断年数是不是能被4整除且不能被100整除(可以被400整除的情况除外),如果是的话就输出,同时定义一个变量记录输出的个数,如果个数能被10整除就输出一个回车符。
程序如下:
#include <stdio.h>
int main(void)
{
int count = 0;
for (int i = 2000; i <= 3000; i++) //定义年份的范围和循环的条件
{
//判断年份是否为闰年,如果是,输出闰年的年份
if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
{
printf("%d ", i);
count++;
if (count % 10 == 0) //输出10个年份之后输出一个换行符
//还没学到字符型的话可以用printf()函数来输出,即printf("\n");
putchar('\n');
}
}
return 0;
}
输出:
2000 2004 2008 2012 2016 2020 2024 2028 2032 2036
2040 2044 2048 2052 2056 2060 2064 2068 2072 2076
2080 2084 2088 2092 2096 2104 2108 2112 2116 2120
2124 2128 2132 2136 2140 2144 2148 2152 2156 2160
2164 2168 2172 2176 2180 2184 2188 2192 2196 2204
2208 2212 2216 2220 2224 2228 2232 2236 2240 2244
2248 2252 2256 2260 2264 2268 2272 2276 2280 2284
2288 2292 2296 2304 2308 2312 2316 2320 2324 2328
2332 2336 2340 2344 2348 2352 2356 2360 2364 2368
2372 2376 2380 2384 2388 2392 2396 2400 2404 2408
2412 2416 2420 2424 2428 2432 2436 2440 2444 2448
2452 2456 2460 2464 2468 2472 2476 2480 2484 2488
2492 2496 2504 2508 2512 2516 2520 2524 2528 2532
2536 2540 2544 2548 2552 2556 2560 2564 2568 2572
2576 2580 2584 2588 2592 2596 2604 2608 2612 2616
2620 2624 2628 2632 2636 2640 2644 2648 2652 2656
2660 2664 2668 2672 2676 2680 2684 2688 2692 2696
2704 2708 2712 2716 2720 2724 2728 2732 2736 2740
2744 2748 2752 2756 2760 2764 2768 2772 2776 2780
2784 2788 2792 2796 2800 2804 2808 2812 2816 2820
2824 2828 2832 2836 2840 2844 2848 2852 2856 2860
2864 2868 2872 2876 2880 2884 2888 2892 2896 2904
2908 2912 2916 2920 2924 2928 2932 2936 2940 2944
2948 2952 2956 2960 2964 2968 2972 2976 2980 2984
2988 2992 2996
5.20
题目:
编写程序,打印以下图形:
*
***
*****
*******
*****
***
*
题解:
设行号为i,前四行每行输出4-i个空格和2*i-1个星号;四行后重新把行号i设为1,后三行每行输出i-1个空格和7-2*i个星号。
程序如下:
#include <stdio.h>
int main(void)
{
int i = 0, j = 0, k = 0, l = 0;
//打印前四行
for ( i = 1; i <= 4; i++)
{
j = 4 - i; //定义每行空格的数量
l = 2 * i - 1; //定义每行星号的数量
for (k = 1; k <= j; k++)
putchar(' '); //每行打印4-i个空格
for (k = 1; k <= l; k++)
putchar('*'); //每行打印2*i-1个星号
//还没学到putchar()的话,可以用printf("*")来输出
putchar('\n'); //每行打印完成后,输出一个换行符来换行
}
//重新计算行号,打印后四行
for ( i = 1; i <= 3; i++)
{
j = 7 - 2 * i; //定义每行星号的数量
l = i - 1; //定义每行空格的数量
for (k = 0; k <= l; k++)
putchar(' '); //每行打印i-1个空格
for (k = 0; k < j; k++)
putchar('*'); //每行打印7-2*i个星号
putchar('\n'); //换行
}
return 0;
}
输出:
*
***
*****
*******
*****
***
*
P80 编程题
6.19
题目:
请编写程序,输入一行字符(用回车结束),输出每个字符以及与之对应的ASCII码值,每行输出三个。
题解:
char类型实际存储的是ASCII码,所以输出对应的ASCII码值只需要在输出时改变一下格式控制就可以。同时,还要设置一个计数变量,实现输出三个之后换行的功能。
程序如下:
#include <stdio.h>
int main(void)
{
char c;
int i = 0;
while ((c = getchar()) != '\n') //判断输入的是否为换行符,如果是则结束输入
{
printf("character: %c, ASCII: %d ", c, c);
i++; //计算输出的数量
if (i % 3 == 0) //每输出三个,换一行
putchar('\n');
}
return 0;
}
输入和输出:
aqwsedrf
character: a, ASCII: 97 character: q, ASCII: 113 character: w, ASCII: 119
character: s, ASCII: 115 character: e, ASCII: 101 character: d, ASCII: 100
character: r, ASCII: 114 character: f, ASCII: 102
6.20
题目:
请编写程序,输入一行数字字符(用回车结束),每个数字字符的前后都有空格。请编程,把这一行中的数字转换成一个整数。
样例输入:
2 4 8 3
样例输出:
2483
题解:
可以用getchar()的返回值是否为回车来判断输入结束,也可以判断是否为空格,如果不是,则输出。
程序如下:
#include <stdio.h>
int main(void)
{
char c;
while ((c = getchar()) != '\n') //判断输入的是否为换行符,如果是则结束输入
{
//判断输入的是否为空格,如果不是则输出数字字符
if ((c != ' '))
putchar( c );
}
return 0;
}
输入和输出:
1 2 3 4
1234
6.21
题目:
请编写程序统计输入的行数,用!号结束输入,!号所在的行不计入行数。
题解:
跟上一题差不多,也是用一个while循环和一个if语句来实现。
程序如下:
#include <stdio.h>
int main(void)
{
char c;
int count = 0; //声明一个计数的变量
while ((c = getchar()) != '!') //通过输入是否为“!”来判断是否结束输入
{
//统计换行符的个数
if ((c == '\n'))
count++;
}
printf("count = %d", count); //输出行数
return 0;
}
输入输出:
a
b
c
d
e
!
count = 5
6.22
题目:
请编写程序统计输入的一行中小写字母的个数。
题解:
判断是否为小写字母可以使用char类型,读入字符的方法与上面两题相同。
程序如下:
#include <stdio.h>
int main(void)
{
char c;
int count = 0; //声明一个计数的变量
while ((c = getchar()) != '\n') //当输入换行符时,结束输入
{
if (c >= 'a' && c <= 'z') //判断输入的字符是否为小写字母,并统计小写字母的个数
count++;
}
printf("count = %d", count);
return 0;
}
输入输出:
AaBbCcDdEeFfGg
count = 7
6.23
题目:
请编写输出以下图案的程序,图案的行数由输入的整数值确定(每行中字符之间没有空格)
A
BBB
CCCCC
DDDDDDD
EEEEEEEEE
题解:
这道题跟上面那道画菱形的有些相似,只是图案的行数是通过输入确定的,而且每一行的字符也不一样。每输出一行换一个字符可以通过将输出的字符声明为char类型,并且每循环一次将这个字符的值加1(实际上就是ASCII码表中这个字符的下一个字符)来实现。
这道题的隐含条件应该是行数是大于0小于26的,要不然就出Bug了……
程序如下:
#include <stdio.h>
int main(void)
{
int i = 0, j = 0, k = 0, l = 0, m = 0;
char c = 'A'; //声明要输出的字符,并将其初始化为A
scanf("%d", &j); //输入行数
for (i = 1; i <= j; i++)
{
k = j - i; //定义每一行的空格数量
l = 2 * i - 1; //定义每一行的字符数量
for (m = 1; m <= k; m++)
putchar(' ');
for (m = 1; m <= l; m++)
putchar( c );
c++; //每输出一行,字符的值加1
putchar('\n');
}
return 0;
}
输入和输出:
5
A
BBB
CCCCC
DDDDDDD
EEEEEEEEE
10
A
BBB
CCCCC
DDDDDDD
EEEEEEEEE
FFFFFFFFFFF
GGGGGGGGGGGGG
HHHHHHHHHHHHHHH
IIIIIIIIIIIIIIIII
JJJJJJJJJJJJJJJJJJJ