C语言入门语法题详解(1)

1.ISBN号码

题目描述:

每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。ISBN码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符“-”之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔之后的五位数字代表该书在出版社的编号;最后一位为识别码。

识别码的计算方法如下:
首位数字乘以1加上次位数字乘以2……以此类推,用所得的结果mod 11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。例如ISBN号码0-670-82162-4中的识别码4是这样得到的:对067082162这9个数字,从左至右,分别乘以1,2,…,9,再求和,即0×1+6×2+……+2×9=158,然后取158 mod 11的结果4作为识别码。

题目任务:

编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出“Right”;如果错误,则输出你认为是正确的ISBN号码。

输入输出要求:

输入要求:只有一行,是一个字符序列,表示一本书的ISBN号码(保证输入符合ISBN号码的格式要求)。

输出要求:共一行,假如输入的ISBN号码的识别码正确,那么输出“Right”,否则,按照规定的格式,输出正确的ISBN号码(包括分隔符“-”)。

输入输出案例:

案例1

输入:0-670-82162-4

输出:Right

案例2

输入:0-670-82162-0

输出:0-670-82162-4

代码实现:

#include <stdio.h>

int main()
{
    //因为涉及到‘X’到数字的转换,所以需要用字符类型接收,我们干脆直接定义一个字符数组
    char arr[13] = { 0 };

    //本人采用循环控制,%c输入的方式输入
    for (int i = 0; i < 13; i++)
    {
       scanf("%c", &arr[i]);
   }

   //暴力法求各位数的和
   int num = (arr[0] - '0') * 1 + (arr[2] - '0') * 2 + (arr[3] - '0') * 3 + 
        (arr[4] - '0') * 4 + (arr[6] - '0') * 5 + (arr[7] - '0') * 6 +
       (arr[8] - '0') * 7 + (arr[9] - '0') * 8 + (arr[10] - '0') * 9;

   //取余
   int mod = num % 11;

   //判断识别码是否为‘X’:如果是,将它的值改为int类型的数字10;如果不是,将字符转换成整型数字。
   int arr_id = arr[12] == 'X' ? 10 : arr[12] - '0';

    //如果识别码不等于余数
    if (mod != arr_id)
    {
        //将余数转换成字符格式:如果mod等于10,就要转化为字符‘X’;若不等于,则要将数字转换成字符。
        arr[12] = mod == 10 ? 'X' : mod + '0';
        printf("%s", arr);
    }
    else
        printf("Right");
    return 0;
}

补充:

这道题的难点在于字符和数值的转换,但当我们了解某些特性,那么解题就能游刃有余。

扫描二维码关注公众号,回复: 14361282 查看本文章

 我们观察ASCLL码表,发现字符0~9有对应的十进制值。那么我们就可以以字符 ‘0’ 为之间量进行加减。例如:字符 ‘1’ - 字符 ‘0’ = 1 。反过来就是 数字1 + 字符 ‘0’ =字符 ‘1’ 。

并且,题目当中使用了多个三目操作符,使我们的代码看起来相对整洁,不那么杂乱。

当然,本题的代码并不是最优解,尤其是注释部分的暴力解法,只是为了理解起来、看起来不那么复杂。

2.统计包含数字9的数的个数

题目描述:

今年是2022年,KiKi想知道1~2022中有多少个包含数字9的数。包含数字的数是指有某一位是“9”的数,例如“2019”、“199”等。

题目任务:

输出1~2022中共有多少个数包含数字9。

输入输出要求:

输入:无

输出:1~2022中共有多少个数包含数字9

代码实现:

#include <stdio.h>

int main()
{
    int i = 0;

    //使用一个变量描述个数
    int count = 0;

    for (i = 1; i <= 2022; i++)
    {

       //要使用i但不改变i的值就用临时变量代替
        int tmp = i;
 
        //个位、十位、百位、千位依次判断是不是数字9
        while (tmp)
        {
            if (tmp % 9 == 0)//也可写成 (tmp % 10 == 9)
            {
                count++;
                break;
            }
            tmp /= 10;
        }

    }
    printf("%d", count);
    return 0;
}

补充:

其实本题并不难,核心的地方在于怎么取到每个数的个位、十位、百位等等,并单独拿出来做判断。我们不妨这样设想:我们定义的是int类型的变量,那么变量存储的数值一定不可能有小数,即2022 / 10 =202 ,202 % 10 = 2 ,这样我们就得到了十位上的数字。重复这个步骤,就能实现功能。

其次我们要掌握一个思想:临时变量。可以看到注释部分:要使用i但不改变i的值就用临时变量代替。当我们写一个循环时,发现要用到循环体的数值,并且可能会进行一些运算改变它的值,那么我们可以发循环体的数值赋值给一个新的变量,用这个新的变量去进行下一步的运算。

3.水仙花数

题目描述:

春天是鲜花的季节,水仙花就是其中最迷人的代表,数学上有个水仙花数,他是这样定义的: “水仙花数”是指一个三位数,它的各位数字的立方和等于其本身,比如:153=1^3+5^3+3^3。 现在要求输出所有在m和n范围内的水仙花数。

题目任务:

判断一个范围内有没有水仙花数,如果有,就依次从小到大打印出来;如果没有,则就输出“no”。(多组输入输出)。

输入输出要求:

输入要求:输入数据有多组,每组占一行,包括两个整数m和n(100 ≤ m ≤ n ≤ 999)。

输出要求:对于每个测试实例,要求输出所有在给定范围内的水仙花数,就是说,输出的水仙花数必须大于等于m,并且小于等于n,如果有多个,则要求从小到大排列在一行内输出,之间用一个空格隔开; 如果给定的范围内不存在水仙花数,则输出no; 每个测试实例的输出占一行。

输入输出案例:

案例1

输入:100 120
            300 380

输出:no
            370 371

代码实现:

#include <stdio.h>
#include <math.h>

int main()
{
    int n = 0;
    int m = 0;
    int i = 0;

    //用一个标记来判断范围内有没有水仙花数,如果但凡有一个,那么flag的值就改为1;如果一个没有,那flag的值不变。
    int flag = 0;

    while (scanf("%d%d", &n, &m) != EOF)
    {
        getchar();
        for (i = n; i <= m; i++)
        {
            if (pow(i % 10, 3) + pow(i / 10 % 10, 3) + pow(i / 100 % 10, 3) == i)
            {
                printf("%d ", i);
                flag = 1;
            }
        }
        if (flag == 0)
           printf("no\n");
    }
    return 0;
}

补充:

这个题也没有太大的难度,无非使用了计算次方的pow函数。pow(a,b),用数学表达为:a^b。例如:pow(2,3),计算的是 2^3 = 8,8作为函数的返回值。

这个题着重在于falg的使用,我们可以自行体会。

4.考官打分

题目描述:

有7位考官,从键盘输入若干组成绩,每组7个分数(百分制),去掉一个最高分和一个最低分,输出每组的平均成绩。(注:本题有多组输入)

题目任务:

输入7个整数(0~100),代表7个成绩,用空格分隔。输出去掉最高分和最低分的平均成绩,小数点后保留2位,每行输出后换行。

输入输出要求:

输入要求:每一行,输入7个整数(0~100),代表7个成绩,用空格分隔。

输出要求:每一行,输出去掉最高分和最低分的平均成绩,小数点后保留2位,每行输出后换行。

输入输出案例:

案例1

输入:99 45 78 67 72 88 60

输出:73.00

代码实现:

#include <stdio.h>

int main()
{
    int arr[7] = { 0 };
    int i = 0;
    while (scanf("%d%d%d%d%d%d%d", &arr[0], &arr[1], &arr[2], &arr[3], &arr[4], &arr[5], &arr[6]) != EOF)
    {
        //每次循环sum、max、min的值都不变。为了不影响下次输入,需要重置数值。
        int sum = 0;
        int max = 0;
        int min = 100;

        for (i = 0; i < 7; i++)
        {
            //判断谁最大
            if (arr[i] > max)
                max = arr[i];

            //判断谁最小
            if (arr[i] < min)
                min = arr[i];

            //求和
            sum += arr[i];
        }

        //整数*浮点数=浮点数
        double num = (sum - max - min) * 1.0 / 5;
        printf("%.2lf\n", num);

    }
    return 0;
}

补充:

这个题要求是多组输入,所以我在scanf函数上下文章。用了一个比较low的方法实现功能。大家也可以用指针,看起来会整洁一些。

本题的核心是:这个程序是不会结束的,即定义的sum、max、min会随着程序往下走改变。我们要做的是一层循环结束后,将sum、max、min的值重置,看起来像是一个“新的程序”。

谁最大谁最小的这个算法,思想很简单,我们可以自行体会。

猜你喜欢

转载自blog.csdn.net/weixin_59913110/article/details/125022947
今日推荐