洛谷P1055题解(全AC)

第一次写题解,请来访的各位大佬多多包涵 awa(完整程序见文末,已验证全AC)

一、大话题目~

每一本正式出版的图书都有一个 ISBN 号码与之对应,ISBN 码包括 9 位数字、1 位识别码和 3 位分隔符,其规定格式如 x-xxx-xxxxx-x,其中符号 - 就是分隔符(键盘上的减号),最后一位是识别码,例如 0-670-82162-4就是一个标准的 ISBN 码。

识别码的计算方法如下:

首位数字*1 加上 次位数字* 2 ……以此类推,用所得的结果  mod11(即%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码进行校对。

那么我们的程序就只需要分成以下几个模块:

  1. 读取:读取ISBN码(A)
  2. 计算:依照9位数字计算ISBN码(B)
  3. 验证:验证A识别码与B识别码是否相等,并输出对应结果

二、开敲代码~~

1、读取

读取就是输入数字嘛,而像我这样的萌新很容易会想到直接导入整型。

scanf("%d-%d%d%d-%d%d%d%d%d-%d",...);

这样造成的问题就是无法正常读取。因为%d对应的并不是数字,而是一个数。也就是说,如果我输入32-456-...哪怕32就会被读取到第一个%d的位置上!

那么正确的思路是什么呢?让我们一起看后面的程序要求

首位数字*1 加上 次位数字* 2 ……

由于第二步中我们会需要对9位数字分别进行对应的乘法运算,所以在程序开头我们需要以字符串的形式输入数据,这样才能对第1、2、3...的数字进行单独的操作。(ps:字符串的输入可省略求址符号&)

9位数字+3位间隔符+1位识别码,总共是13位字符。由于C++编码的特点,我们需要再开一个空间,用于保存字符串输入最后的'\0',即我们结束时按下的回车键。

char a[14];
scanf("%s",a);

但是呢,如果创建a[13],在此程序中也不会出现问题。

那么什么情况下数组缺少空间会出现问题呢?

——在需要多次输入数据的时候。

由于数组长度不够,所以多出来的'\0'会影响下次输入。

可以打上以下代码用于清空scanf的缓存区。

setbuf(stdin,NULL);

回到正题,那么现在我们有了数组a[14],就可以进入计算的模块啦。

2、计算

接下来我们需要做的,就是对9个数字各自做乘法再求和。计算规则是:

第1位数字*1 + 第2位数字*2 + 第3位数字*3 + ... +第9位数字*9,得到总和。后%11得到余数,即识别码。

这里令i为位数,则总和可以表示为

sum = \sum (a[i]*(i+1))                                                                                                (2.1)

之后再对sum求余数即可。

接下来就让我们用程序来实现它吧!

先创建一个int型变量code,用于保存总和。然后使用for循环,按公式(2.1)处理第一位数字到第九位数字,将结果累加给code。

但是在循环的过程中,要把ISBN码位数i数字位数j区分开。否则可能会出现将a[1](即'-')乘以2的滑稽结果。

int code = 0;
int i,j=0;
for(i=0;i<12;i++){
		if(a[i]=='-') continue;
		code += ((a[i]-48)*(j+1));
		j++;
	}

 经过for循环,我们终于成功得到了正确的总和,然后 code %= 11就能得到余数了~

3、验证

验证结果分为“识别码无误,输出RIght”和“识别码错误,输出正确识别码”两种情况。

现在我们需要创建一个数组,用来返回正确的识别码。即:

choice[12] = "0123456789X";

 嘿嘿,现在使用choice[code]就能输出对应的识别码啦。

最后再进行判断就大功告成了!

完整程序如下:

#include <bits/stdc++.h>
int main(){
	//数字
	char a[14],choice[12]="0123456789X";

	//计算识别码
	int code=0;
	scanf("%s",a);
	int i,j=0;
	for(i=0;i<12;i++){
		if(a[i]=='-') continue;
		code += ((a[i]-48)*(j+1));
		j++;
	}
	code %= 11;
	//判断识别码
	if(choice[code]==a[12]) printf("Right");
	else{
		a[12] = choice[code];
		printf("%s",a);	
	} 
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值