- 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 条评论
-
admin SU @ 2025-5-28 18:13:42
解题思路
- 编写一个函数用于去除ISBN号码中的分隔符,得到仅包含数字的字符串。
- 编写一个函数根据给定规则计算识别码。
- 在主函数中,读取输入的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; }
代码解释
removeDash
函数:- 接收一个表示ISBN号码的字符串
isbn
作为参数。 - 通过遍历
isbn
字符串,将不是分隔符“-”的字符依次添加到num
字符串中,最后返回去除分隔符后的纯数字字符串。
- 接收一个表示ISBN号码的字符串
calculateChecksum
函数:- 接收一个仅包含数字的字符串
num
(即ISBN号码去除分隔符后的形式)作为参数。 - 使用
for
循环遍历num
字符串的前9个字符,将每个字符转换为数字并乘以对应的权重(从1到9),累加到sum
中。 - 计算
sum
对11取模的结果remainder
,根据remainder
的值返回正确的识别码字符,如果remainder
为10返回'X'
,否则返回对应数字字符。
- 接收一个仅包含数字的字符串
main
函数:- 读取输入的ISBN号码存储在
isbn
字符串中。 - 调用
removeDash
函数得到纯数字字符串pureNum
,再调用calculateChecksum
函数得到正确的识别码correctChecksum
。 - 将计算得到的识别码
correctChecksum
与pureNum
字符串的最后一位(即输入的识别码)进行比较,若相同则输出“Right”,若不同则修改原isbn
字符串的最后一位为正确识别码并输出。
- 读取输入的ISBN号码存储在
-
2025-5-28 18:12:55@
解题思路
- 首先,去除输入字符串中的分隔符“-”,得到仅包含数字的字符串。
- 然后,按照识别码的计算方法,从左至右,让每个数字依次乘以1, 2, …, 9 并求和。
- 接着,对求和结果取模11得到余数。
- 最后,根据余数判断识别码是否正确:
- 如果余数为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; }
代码解释
- 输入与预处理:
- 使用
string
类型变量isbn
接收输入的ISBN号码。 - 通过遍历
isbn
字符串,将非“-”字符存入num
字符串,得到纯数字部分。
- 使用
- 计算加权和:
- 使用
for
循环,从0到8遍历num
字符串的前9个字符(数字)。 - 每次将当前字符转换为数字(
num[i] - '0'
)并乘以对应的权重(i + 1
),累加到sum
中。
- 使用
- 计算并判断识别码:
- 计算
sum
对11取模的结果remainder
。 - 根据
remainder
的值确定正确的识别码correctChecksum
,若remainder
为10则是'X'
,否则是对应数字字符。 - 将计算出的正确识别码与输入ISBN号码中的识别码比较,相同则输出“Right”,不同则修改原
isbn
字符串的最后一位为正确识别码并输出。
- 计算
-
2025-5-28 18:12:44@
- 1