PAT乙级1037 || 在霍格沃茨找零钱(20)(C++)

这道题很有意思,需要动一下脑筋,值得好好写篇文章

题目描述

如果你是哈利·波特迷,你会知道魔法世界有它自己的货币系统 —— 就如海格告诉哈利的:“十七个银西可(Sickle)兑一个加隆(Galleon),二十九个纳特(Knut)兑一个西可,很容易。”现在,给定哈利应付的价钱P和他实付的钱A,你的任务是写一个程序来计算他应该被找的零钱。

输入描述:

输入在1行中分别给出P和A,格式为“Galleon.Sickle.Knut”,其间用1个空格分隔。这里Galleon是[0, 107]]区间内的整数,Sickle是[0, 
17)区间内的整数,Knut是[0, 29)区间内的整数。

输出描述:

在一行中用与输入同样的格式输出哈利应该被找的零钱。如果他没带够钱,那么输出的应该是负数。

输入例子:

10.16.27 14.1.28

输出例子:

3.2.1

本题考点:

1.输入字符串怎么提取出数字(怎么判断字符是数字+怎么把两个数字字符搞成十进制数)

2.逗号隔开的每一个数字视为一位,两数相减,低位不够高位减一,也就是说要模拟实现减法。

思路图:

注意,输入描述中给出了GSK的范围,这个范围需要在相减的时候用到,不用刻意地在获取到输入之后马上判断范围。

定义int类型G,S,K

取数

要点:判断当前字符是不是数字 if (s[i] - '0' >= 0 && s[i] - '9' <= 0)

取数的功能做成了一个单独的函数,注意点写在注释中

void getnum(int n[3],string s) {//传进来我们用来存放数字的数组和用来提取的字符串
	int carry = 0;//标记取数取到第几个
	for (int i = 0; i < s.length(); i++) {;
		if (s[i] - '0' >= 0 && s[i] - '9' <= 0) {//判断当前字符是不是数字
			n[carry] = n[carry] * 10 + (s[i] - '0');//注意(s[i] - '0')才是我们想要的那个数字,不然会转成ASCII值
		}
		if (s[i] == '.') {//碰到逗号说明取完一个数
			carry++;//改carry值,取下一个数
		}
	}
}

写完取数这个函数记得写个cout输出一下看看运作结果是否正确

第一版代码

拿了4/7的分

#include <iostream>
#include<string>
#include<vector>
using namespace std;
vector<int>vec;

void getnum(int n[3],string s) {
	int carry = 0;//标记取数取到第几个
	for (int i = 0; i < s.length(); i++) {;
		if (s[i] - '0' >= 0 && s[i] - '9' <= 0) {
			n[carry] = n[carry] * 10 + (s[i] - '0');
		}
		if (s[i] == '.') {//碰到逗号说明取完一个数
			carry++;
		}
	}
}

int main() {
	//输入
	string str1,str2;
	cin >> str1 >> str2;

	//取数
	int A[3] = { 0 }, B[3] = { 0 }, C[3] = { 0 };
	getnum(A, str1);
	getnum(B, str2);
	
	//相减
	while (B[2] < 29 && B[2] >= 0 && A[2] < 29 && A[2] >= 0) {
		C[2] = B[2] - A[2];
		if (C[2] < 0) {
			C[2] =29+C[2];//注意29进制
			B[1] -= 1;
			//if (B[1] < 0)B[1] *= (-1);
		}
		C[1] = B[1] - A[1];
		if (C[1] < 0) {
			C[1] = 17+C[1];//注意17进制
			B[0] -= 1;
		}
		C[0] = B[0] - A[0];
		break;
	}

	for (int i = 0; i < 3; i++) {
		if (i == 2)cout << C[i];
		else {
             cout << C[i] << '.';
		}
		
	}

	return 0;
}

这边着重解释一下相减部分的意思,数组下标123分别对应GSK,数组名称AB分别对应输入例子的左右两项,数组C[3]则是我们用来记录相减结果之后要输出的数组。第一版代码中相减部分能正确实现的输入右项大于左项的情况(B-A),那如果说给的输入例子是左大于右呢?整体的代码逻辑不变,把AB位置换一下,两块用于相减的代码模块用if else设置条件隔开,最后输出的时候把C[0]的结果乘上-1就可以了。

这段相减功能的代码其实可以封装成一个函数,这样一来只要传入的形参位子交换一下就ok了,但是,考试时间有限只要能AC那就赶紧转下一题去了,得要快呀呀呀呀呀呀!好吧其实是刷题目写笔记太耗时间,手头还有论文要写,于是作罢。

完整版代码:

#include <iostream>
#include<string>
#include<vector>
using namespace std;
vector<int>vec;

void getnum(int n[3], string s) {
	int carry = 0;//标记取数取到第几个
	for (int i = 0; i < s.length(); i++) {
		;
		if (s[i] - '0' >= 0 && s[i] - '9' <= 0) {
			n[carry] = n[carry] * 10 + (s[i] - '0');
		}
		if (s[i] == '.') {//碰到逗号说明取完一个数
			carry++;
		}
	}
}

int main() {
	//输入
	string str1, str2;
	cin >> str1 >> str2;

	//取数
	int A[3] = { 0 }, B[3] = { 0 }, C[3] = { 0 };
	getnum(A, str1);
	getnum(B, str2);

	//相减
	while (B[2] < 29 && B[2] >= 0 && A[2] < 29 && A[2] >= 0) {
		if (A[0] < B[0] //左值小于右值的时候,从K向G开始算,右减左
			|| (A[0] == B[0]&& A[1] < B[1]) 
			|| (A[0] == B[0] && A[1] == B[1]&& A[2] < B[2])) {
			C[2] = B[2] - A[2];
			if (C[2] < 0) {
				C[2] = 29 + C[2];
				B[1] -= 1;
				//if (B[1] < 0)B[1] *= (-1);
			}
			C[1] = B[1] - A[1];
			if (C[1] < 0) {
				C[1] = 17 + C[1];
				B[0] -= 1;
			}
			C[0] = B[0] - A[0];
		}
		else {//左值大于右值的时候,左减右(也就是A-B,或者说AB互换),最后G值乘上-1
			C[2] = A[2]-B[2] ;
			if (C[2] < 0) {
				C[2] = 29 + C[2];
				A[1] -= 1;
				//if (B[1] < 0)B[1] *= (-1);
			}
			C[1] = A[1]-B[1] ;
			if (C[1] < 0) {
				C[1] = 17 + C[1];
				A[0] -= 1;
			}
			C[0] = A[0]-B[0] ;
			C[0] *= -1;
		}
		
		break;
	}

	for (int i = 0; i < 3; i++) {
		if (i == 2)cout << C[i];
		else {
			cout << C[i] << '.';
		}

	}

	return 0;
}

写在最后

题目是凌晨做的,笔记写了一半扛不住了就好好睡了一觉,起来之后补完的笔记,中间有些内容可能会遗漏、或者说没写清楚什么东西,如有疑问欢迎在评论区留言探讨。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值