BC76 [NOIP2008]ISBN号码

该博客主要介绍了如何编写程序来验证ISBN号码的校验码是否正确。通过解析ISBN的格式和校验码计算方法,作者详细展示了如何将输入的ISBN号码分解并计算校验码。代码中,作者采用了模块化设计,包括反转数字、计算权重和校验的过程。最后,程序会判断输入的识别码是否正确,并根据结果输出校验结果或修正后的ISBN号码。
摘要由CSDN通过智能技术生成

描述

每一本正式出版的图书都有一个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号码。

题目来源:牛客网 - 找工作神器|笔试题库|面试经验|实习招聘内推,求职就业一站解决_牛客网 (nowcoder.com)

我采用的是模块化设计,将本题分解成了几个块,拼接在一起完成了本题.

以下有说不对的地方,敬请指出😅😅

首先,我们看到题目非常长,所以要提炼题目精华,粗略一扫得出

ISBN码包括9位数字        1位识别码和3位分隔符       规定格式如“x-xxx-xxxxx-x”       “-”是分隔符,最后一位是识别码

识别码的计算方法如下:
用所得的结果mod 11     所得的余数即为识别码        果余数为10,则识别码为大写字母X。

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

虽然还是有点多     ,但大概意思是 一串数    ,最后一位是识别码(我理解为校验位),      识别方式为    第一位*1+...+第九位*9 的和(权重)     对 11    取余(校验方式)

再判断校验是否正确,正确返回"Right" ,否则返会正确的这一串数(修正校验位);

题目意思懂了,那首先考虑怎么将这一串数分解出来,所以我采用了每一个间隔符前的所有数为一个整形

int a, b, c;
char x, x1;
scanf("%d-%d-%d-%c", &a, &b, &c, &x);

注: 最后一位为字符,因为 10 = X 所以将最后的识别码转为字符将是最后的对比

然后,开始考虑怎么将 第一位*1+...+第九位*9 的和 求出,因为我把这一串数拆分成了四个整形,所以方便我对每一个整形进行修改

于是,我想到了设计一个函数来求出这个整形的和,再将三个整形(最后一个是标识符)的和加在一起就是 第一位*1+...+第九位*9 的和 

设计这个函数需要  一个数(a,b,c) 和 它的权重(1,2~4,5~9) 暂定这两个.

//      数据    权重
int fin(int number, int dis) { //每位乘
    if (number != 0)
        return fin(number / 10, dis + 1) + number % 10 * dis;
    else
        return 0;
}

我用的是递归的写法 但是我发现这样写虽然简单,但是求出的和却不是我想要的, 因为题目是从左向右乘以权重的,而我是从右到左

所以需要翻转数字(你以为我会重写??开玩笑😎😎)

于是...

//       数据      
int renum(int number) { //反转数字
    int result = 0, num = number;
    while (num) {
        result = result * 10 + num % 10;
        num /= 10;
    }
    return result;
}

将这两个结合就可以完成  第一位*1+...+第九位*9的和了
 

接下来将求出的标识符存放在 X1 中

x1 = (a * 1 + fin(renum(b), 2) + fin(renum(c), 5)) % 11;

但此时x1为整形,还不能与x(识别码)做对比,因此再做一下判断,因为x可能是'X'(10)

x1 = x1 == 10 ? 'X' : x1 + '0';

注:一个整形加上'0'就可以变成对应的字符(int->char,0~9)

1 + '0' = '1'

9 + '0' = '9'

接下来做判断就可以了

if (x == x1)
        printf("Right");
    else
        printf("%d-%d-%d-%c", a, b, c, x1);

完整代码

#include <stdio.h>
//           数据      
int renum(int number) { //反转数字
    int result = 0, num = number;
    while (num) {
        result = result * 10 + num % 10;
        num /= 10;
    }
    return result;
}
//          数据      权重
int fin(int number, int dis) { //每位乘
    if (number != 0)
        return fin(number / 10, dis + 1) + number % 10 * dis;
    else
        return 0;
}
int main() {
    int a, b, c;
    char x, x1;
    scanf("%d-%d-%d-%c", &a, &b, &c, &x);
    x1 = (a * 1 + fin(renum(b), 2) + fin(renum(c), 5)) % 11;
    x1 = x1 == 10 ? 'X' : x1 + '0';
    if (x == x1)
        printf("Right");
    else
        printf("%d-%d-%d-%c", a, b, c, x1);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值