2个月搞定计算机二级C语言——真题(5)解析

1. 前言

本篇我们讲解2个月搞定计算机二级C语言------真题 5

2. 程序填空题

2.1 题目要求

2.2 提供的代码

c 复制代码
#include <stdio.h>

double fun(int n) {
    int    i;
    double s, t;
    /**********found**********/
    s = __1__;
    /**********found**********/
    for (i = 1; i <= __2__; i++) {
        t = 2.0 * i;
        /**********found**********/
        s = s + (2.0 * i - 1) * (2.0 * i + 1) / __3__;
    }
    return s;
}

main() {
    int n = -1;
    while (n < 0) {
        printf("Please input(n>0): ");
        scanf("%d", &n);
    }
    printf("\nThe result is: %f\n", fun(n));
    getchar();
}

2.3 解题思路

这道题就是典型的纸老虎题,它作为编程的第一题定会在考场上压力你一下,在题目上做做文章,搞得这道题好像很难的样子,其实主要的代码都写完了,而且也给出了式子的规律,那么我们只需略微出手,便可拿下此题。

(1) 处填空:

此处是给变量 s 赋值,可以看到在 fun() 函数的末尾是 return s; 将其作为函数返回值返回,由此可以得出 s 是保存前 n 项和的变量,所以这里我们给它赋值为 0,做一个变量初始化,防止程序开始运行时 s 存储的是垃圾值

c 复制代码
s = 0;  // 初始化为 0

(2) 处填空:

这里缺一个循环的条件,在题目所给的式子中是从 1 计算到 n 的,循环中 i 做的就是这件事情,所以 i小于等于形参 n 时符合条件,此处填 n

c 复制代码
for (i = 1; i <= n; i++) {  // 1 ~ n

(3) 处填空:

我们单独看这个式子 (2.0 * i - 1) * (2.0 * i + 1) / __3__,此处可以和题目最后的式子规律一一对应,空缺的第 3 处对应着式子的分母部分 (2*n)²。变量 t 在循环开始时通过 t = 2.0 * i; 已经完成了分母括号里的计算,我们只需使用 t * t 计算平方即可。

c 复制代码
s = s + (2.0 * i - 1) * (2.0 * i + 1) / (t * t);  // 计算 t 乘 t,即 t 的平方

当然计算平方也可以使用 C 语言标准库里的函数------pow 函数,它可以用于计算幂次,定义在 math.h 头文件中,使用需要包含头文件。

c 复制代码
// C 库函数 double pow(double x, double y) 返回 x 的 y 次幂,即 x ^ y
#include <math.h> // 使用 pow 函数时需要包含 math.h 头文件

s = s + (2.0 * i - 1) * (2.0 * i + 1) / pow(t, 2); // 计算 t 的 2 次幂,即 t 的平方

题目要求不要改动其他函数,不得增行或删行,所以这里我继续使用 t * t 计算平方,平时编程时可以直接用 pow 函数。

2.4 代码实现

填写完整的代码:

c 复制代码
#include <stdio.h>

double fun(int n) {
    int    i;
    double s, t;
    /**********found**********/
    s = 0;  // 初始化为 0
    /**********found**********/
    for (i = 1; i <= n; i++) {  // 1 ~ n
        t = 2.0 * i;
        /**********found**********/
        s = s + (2.0 * i - 1) * (2.0 * i + 1) / (t * t);  // 计算 t 乘 t,即 t 的平方
    }
    return s;
}

int main() {
    int n = -1;
    while (n < 0) {
        printf("Please input(n>0): ");
        scanf("%d", &n);
    }
    printf("\nThe result is: %f\n", fun(n));
    getchar();
}

提示:为确保代码正常运行,请在题库编程环境的对应题目中进行测试和运行。

3. 程序修改题

3.1 题目要求

3.2 提供的代码

c 复制代码
#include <stdio.h>
#pragma warning(disable : 4996)

int my_isalpha(char c) {
    if (c >= 'A' && c <= 'Z')
        return 1;
    else if (c >= 'a' && c <= 'z')
        return -1;
    else
        return 0;
}

void a() {
    char ch;
    int  sort;
    printf("本程序判断你从键盘上键入字符的种类,请输入字符(串):\n");
    do {
        ch = getchar();
        if (ch != '\n') {
            sort = my_isalpha(ch);
            /**********************found***********************/
            switch (-1 <= sort && sort <= 1) {
                case 1:
                    printf("%c", '*');
                    break;
                    /**********************found***********************/
                case -1:
                    printf("%c", '#');
                case 0:
                    printf("%c", '?');
            }
        }
        /**********************found***********************/
    } while (ch == '\n');
    printf("%c", '\n');
}

void main() {
    a();
}

3.3 解题思路

这道题主要考察 switch 语句的用法。

(1) 处修改:

switch 括号中的表达式(即控制表达式)必须是整型或能转换为整型的类型。case 标签也必须是常量表达式,并且必须与 switch 的控制表达式类型兼容。

所以不需要那一堆的关系、逻辑运算,只需放入 sort 就好,它存储着 my_isalpha 函数的返回值。

c 复制代码
switch (sort) {

(2) 处修改:

switch 语句中,break 语句用于终止当前 case 分支的执行,并跳出 switch 语句,避免程序继续执行后续的 case 分支。

在改好第一处后,运行程序输入一个小写字母,返回的是 #?,这是因为此处的 case -1: 的分支没有加 break 语句,导致不能跳出 switch 语句,在执行完 case -1: 分支后又执行了 case -1: 分支,显然我们程序没有按照我们的想法运行。

这时我们需要将两个分支分别加上 break 语句即可。

我们在后续的程序开发中可以再加上 default 分支,用来执行不在条件内的操作,从而增强程序的健壮性。

c 复制代码
case -1:
    printf("%c", '#');
    break;
case 0:
    printf("%c", '?');
    break;

(3) 处修改:

do while 语句会先执行一遍循环中的程序,再判断循环条件是否为真,真则继续循环,否则执行循环后面的程序。

ch 存储的是键盘输入的单个字符,'\n' 是一个转义序列,用于表示换行符,对应键盘上的回车键(Enter)。

这里我没找出什么错误,提供的代码是 while (ch == '\n');,改的话只能改成 while (ch != '\n');,这两个代码我分别提交后都可以得满分。

分别运行这两个程序,如果按照要求先输入字符再敲回车这两个程序是没有任何区别的。

但是没有先输入字符直接敲回车,那么区别就来了:while (ch == '\n'); 不论你敲多少次回车,这个循环都不停止,因为符合ch == '\n'这个条件,它会一直循环到你输入不是回车的字符。

c 复制代码
do {
    ch = getchar();
    if (ch != '\n') {
        // ......
    }
    /**********************found***********************/
} while (ch == '\n');

while (ch != '\n');呢?如果你第一次敲回车此时ch存储的是回车的转义字符'\n',循环条件是ch != '\n',由于循环条件不符合,所以不会进行下一次循环,而是执行while下面的语句了。

c 复制代码
do {
    ch = getchar();
    if (ch != '\n') {
        // ......
    }
    /**********************found***********************/
} while (ch != '\n');

这就是它俩的区别所在,大家以后编程时需要注意循环/判断的条件哦。

3.4 代码实现

修改后的代码:

c 复制代码
#include <stdio.h>
#pragma warning(disable : 4996)
int my_isalpha(char c) {
    if (c >= 'A' && c <= 'Z')
        return 1;
    else if (c >= 'a' && c <= 'z')
        return -1;
    else
        return 0;
}
void a() {
    char ch;
    int  sort;
    printf("本程序判断你从键盘上键入字符的种类,请输入字符(串):\n");
    do {
        ch = getchar();
        if (ch != '\n') {
            sort = my_isalpha(ch);
            /**********************found***********************/
            switch (sort) {
                case 1:
                    printf("%c", '*');
                    break;
                    /**********************found***********************/
                case -1:
                    printf("%c", '#');
                    break;
                case 0:
                    printf("%c", '?');
                    break;
            }
        }
        /**********************found***********************/
    } while (ch != '\n');
    printf("%c", '\n');
}
void main() {
    a();
}

提示:为确保代码正常运行,请在题库编程环境的对应题目中进行测试和运行。

4. 程序设计题

4.1 题目要求

4.2 提供的代码

c 复制代码
#include <stdio.h>
#pragma warning(disable : 4996)
double fun(int n) {
}
main() {
    int    n;
    double s;
    void   NONO();
    printf("Input n:  ");
    scanf("%d", &n);
    getchar();
    s = fun(n);
    printf("s=%f\n", s);
    NONO();
    getchar();
}
void NONO() { /* 请在此函数内打开文件,输入测试数据,调用 fun 函数,输出数据,关闭文件。 */
    FILE * rf, *wf;
    int    n, i;
    double s;
    rf = fopen("in.dat", "r");
    wf = fopen("out.dat", "w");
    for (i = 0; i < 10; i++) {
        fscanf(rf, "%d", &n);
        s = fun(n);
        fprintf(wf, "%lf\n", s);
    }
    fclose(rf);
    fclose(wf);
}

4.3 解题思路

题目要求计算多项式的值,给定多项式的第一项为 1,第二项到第 n 项是计算阶乘倒数的和。

我们可以用Sn作为存储累加和的变量,之后通过循环累乘得到阶乘的值,最后计算每一项阶乘的倒数并累加至Sn

在提交时出现了一点小问题,程序可以正常运行,但提交时判为 0 分。经过测试只要把 main 函数里的NONO();语句注释再提交就好了。

4.4 代码实现

填写完整的代码:

c 复制代码
#include <stdio.h>
#pragma warning(disable : 4996)
double fun(int n) {
    int           i         = 0;
    double        Sn        = 1.0;  // 存储累加和,多项式的第一项为 1
    unsigned long factorial = 1;

    for (i = 1; i <= n; i++) {  // 遍历 1~n,注意 i 从 1 开始
        factorial *= i;         // 分别计算从 1~n 的阶乘
        Sn += 1.0 / factorial;  // 计算阶乘的倒数,并加到累加和变量中
    }

    return Sn;
}
main() {
    int    n;
    double s;
    void   NONO();
    printf("Input n:  ");
    scanf("%d", &n);
    getchar();
    s = fun(n);
    printf("s=%f\n", s);
    NONO();	// 如果评分没过,把这句注释了再提交就可以了
    getchar();
}
void NONO() { /* 请在此函数内打开文件,输入测试数据,调用 fun 函数,输出数据,关闭文件。 */
    FILE * rf, *wf;
    int    n, i;
    double s;
    rf = fopen("in.dat", "r");
    wf = fopen("out.dat", "w");
    for (i = 0; i < 10; i++) {
        fscanf(rf, "%d", &n);
        s = fun(n);
        fprintf(wf, "%lf\n", s);
    }
    fclose(rf);
    fclose(wf);
}

提示:为确保代码正常运行,请在题库编程环境的对应题目中进行测试和运行。

5. 后记

本篇博客到这就结束了,如果您有疑问或建议欢迎您在留言区留言。