【蓝桥杯】 C++ 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:

#include<bits/stdc++.h>
#include<string>
#include<iostream>
using namespace std;
int caculate(string a)
{
    int checksum=0;
    int sum=0;
    sum=(a[0]-'0')+2*(a[2]-'0')+3*(a[3]-'0')+4*(a[4]-'0')
        +5*(a[6]-'0')+6*(a[7]-'0')+7*(a[8]-'0')+8*(a[9]-'0')+9*(a[10]-'0');
    checksum=sum%11;
    return checksum;
}
int main()
{
    string ISBN;
    // 根据输入的前几位先算正确数据
    // 如果和输入的不一样,输出正确ISBN
    // 一样的话输出“Right”
    cin>>ISBN;
    string checksum;
    checksum=to_string(caculate(ISBN));
    if(checksum=="10")
    {
        checksum="X";
    }
    if(checksum[0]==ISBN[12])
    {
        cout<<"Right"<<endl;
    }
    else
    {
        for(int i=0;i<ISBN.length()-1;i++)
        {
            cout<<ISBN[i];
        }
        cout<<checksum<<endl;
    }

}

代码2:

#include<bits/stdc++.h>
using namespace std;

int main()
{
    string isbn;
    cin>>isbn;
    int crc=0,sum=0;

    string isbn_num;
    isbn_num=isbn.substr(0,1)+isbn.substr(2,3)+isbn.substr(6,5);
    int slen=isbn_num.length(); // 从 0 开始

    for(int i=0;i<slen;i++)
    {
        sum=sum+(isbn_num[i]-'0')*(i+1);
    }
    crc=sum%11;

    if((isbn[12]-'0')==crc)
    {
        cout<<"Right";
    }
    else if(((isbn[12]-'0')=='X'-'0') && crc==10)
    {
        cout<<"Right";
    }
    else
    {
        for(int i=0;i<isbn.length()-1;i++)
        {
            cout<<isbn[i];
        }
        if(sum==10)
        {
            cout<<'X';
        }
        else
        {
            cout<<crc;
        }
    }

}

解题思路

首先根据输入的数计算正确的校验码是多少,然后再用输入的校验码和计算出来正确的校验码比对,如果一致的话就输出“Right”,不一致就输出正确的 ISBN。

注意点

看题要仔细,① 开始的时候没看见当 checksum 是 10 的时候要换成 X,导致出了错,② 而且 checksum 的类型用了string,在第二个判断 checksum[0]==ISBN[12] 的时候想了很久才发现这个错误。

知识点

  • string 的用法,来源于文章 C++ string详解

    1. 需要知道字符串长度时,可以调用 string 类提供的 length() 函数。
      输出结果为22。由于 string 的末尾没有’\0’字符,所以 length() 返回的是字符串的真实长度,而不是长度 +1。
      string s = "http://c.biancheng.net";
      int len = s.length();
      cout<<len<<endl;
      
    2. string 字符串也可以按照下标来访问其中的每一个字符。string 字符串的起始下标仍是 从 0 开始
      运行结果:
      1 2 3 4 5 6 7 8 9 0
      1234557890
      #include <iostream>
      #include <string>
      using namespace std;
      
      int main(){
          string s = "1234567890";
          for(int i=0,len=s.length(); i<len; i++){
              cout<<s[i]<<" ";
          }
          cout<<endl;
          s[5] = '5';
          cout<<s<<endl;
          return 0;
      }
      
  1. string 截取部分用 substr(begin,length) ,可以加起来。
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值