• C++
  • NOI / 1.7编程基础之字符串 29:ISBN号码

  • @ 2025-5-28 18:12:36

NOI / 1.7编程基础之字符串 题目 排名 状态 提问 29:ISBN号码 查看提交统计提问 总时间限制: 1000ms 内存限制: 65536kB 描述 每一本正式出版的图书都有一个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

样例 #2: 0-670-82162-0 样例输出 样例 #1: Right

样例 #2: 0-670-82162-4 来源 NOIP2008复赛 普及组 第一题

3 条评论

  • @ 2025-5-28 18:13:42

    解题思路

    1. 编写一个函数用于去除ISBN号码中的分隔符,得到仅包含数字的字符串。
    2. 编写一个函数根据给定规则计算识别码。
    3. 在主函数中,读取输入的ISBN号码,调用上述两个函数进行处理,然后比较计算得到的识别码和输入的识别码,根据比较结果输出相应内容。

    代码实现(C++)

    #include <iostream>
    #include <string>
    using namespace std;
    
    // 函数功能:去除字符串中的分隔符'-',返回纯数字字符串
    string removeDash(const string& isbn) {
        string num = "";
        for (char c : isbn) {
            if (c != '-') {
                num += c;
            }
        }
        return num;
    }
    
    // 函数功能:根据ISBN号码前9位数字计算识别码
    char calculateChecksum(const string& num) {
        int sum = 0;
        for (int i = 0; i < 9; i++) {
            sum += (num[i] - '0') * (i + 1);
        }
        int remainder = sum % 11;
        if (remainder == 10) {
            return 'X';
        } else {
            return remainder + '0';
        }
    }
    
    int main() {
        string isbn;
        cin >> isbn;
        string pureNum = removeDash(isbn);
        char correctChecksum = calculateChecksum(pureNum);
        if (correctChecksum == pureNum[9]) {
            cout << "Right" << endl;
        } else {
            isbn[isbn.length() - 1] = correctChecksum;
            cout << isbn << endl;
        }
        return 0;
    }
    

    代码解释

    1. removeDash函数
      • 接收一个表示ISBN号码的字符串isbn作为参数。
      • 通过遍历isbn字符串,将不是分隔符“-”的字符依次添加到num字符串中,最后返回去除分隔符后的纯数字字符串。
    2. calculateChecksum函数
      • 接收一个仅包含数字的字符串num(即ISBN号码去除分隔符后的形式)作为参数。
      • 使用for循环遍历num字符串的前9个字符,将每个字符转换为数字并乘以对应的权重(从1到9),累加到sum中。
      • 计算sum对11取模的结果remainder,根据remainder的值返回正确的识别码字符,如果remainder为10返回'X',否则返回对应数字字符。
    3. main函数
      • 读取输入的ISBN号码存储在isbn字符串中。
      • 调用removeDash函数得到纯数字字符串pureNum,再调用calculateChecksum函数得到正确的识别码correctChecksum
      • 将计算得到的识别码correctChecksumpureNum字符串的最后一位(即输入的识别码)进行比较,若相同则输出“Right”,若不同则修改原isbn字符串的最后一位为正确识别码并输出。
    • @ 2025-5-28 18:12:55

      解题思路

      1. 首先,去除输入字符串中的分隔符“-”,得到仅包含数字的字符串。
      2. 然后,按照识别码的计算方法,从左至右,让每个数字依次乘以1, 2, …, 9 并求和。
      3. 接着,对求和结果取模11得到余数。
      4. 最后,根据余数判断识别码是否正确:
        • 如果余数为10 ,识别码应为 'X' ;
        • 如果余数不为10 ,识别码就是余数对应的数字字符。
        • 将计算得到的正确识别码与输入的ISBN号码中的识别码进行比较,若相同则输出“Right”,否则输出正确的ISBN号码。

      代码实现(C++)

      #include <iostream>
      #include <string>
      using namespace std;
      
      int main() {
          string isbn;
          cin >> isbn;
          string num = "";
          // 去除分隔符,提取数字部分
          for (char c : isbn) {
              if (c != '-') {
                  num += c;
              }
          }
          int sum = 0;
          for (int i = 0; i < 9; i++) {
              sum += (num[i] - '0') * (i + 1);
          }
          int remainder = sum % 11;
          char correctChecksum;
          if (remainder == 10) {
              correctChecksum = 'X';
          } else {
              correctChecksum = remainder + '0';
          }
          if (correctChecksum == num[9]) {
              cout << "Right" << endl;
          } else {
              isbn[isbn.length() - 1] = correctChecksum;
              cout << isbn << endl;
          }
          return 0;
      }
      

      代码解释

      1. 输入与预处理
        • 使用string类型变量isbn接收输入的ISBN号码。
        • 通过遍历isbn字符串,将非“-”字符存入num字符串,得到纯数字部分。
      2. 计算加权和
        • 使用for循环,从0到8遍历num字符串的前9个字符(数字)。
        • 每次将当前字符转换为数字(num[i] - '0')并乘以对应的权重(i + 1),累加到sum中。
      3. 计算并判断识别码
        • 计算sum对11取模的结果remainder
        • 根据remainder的值确定正确的识别码correctChecksum,若remainder为10则是'X',否则是对应数字字符。
        • 将计算出的正确识别码与输入ISBN号码中的识别码比较,相同则输出“Right”,不同则修改原isbn字符串的最后一位为正确识别码并输出。
      • 1