币值转换

币值转换

PTA基础编程题目集7-23

输入一个整数(位数不超过9位)代表一个人民币值(单位为元),请转换成财务要求的大写中文格式。如23108元,转换后变成“贰万叁仟壹百零捌”元。为了简化输出,用小写英文字母a-j顺序代表大写数字0-9,用S、B、Q、W、Y分别代表拾、百、仟、万、亿。于是23108元应被转换输出为“cWdQbBai”元。

输入格式:
输入在一行中给出一个不超过9位的非负整数。

输出格式:
在一行中输出转换后的结果。注意“零”的用法必须符合中文习惯。

输入样例1813227345
输出样例1:
iYbQdBcScWhQdBeSf
输入样例26900
输出样例2:
gQjB

思路
本题我基本采用“暴力”的方法进行解答,没有想到太好的解决办法,就试着用暴力的方法写了题解。(ps:可能过程比较复杂,不容易理解,方法不唯一,仅提供个人观点)
个人认为本题难点在于“读数”这一环节,环环相扣,很多点不容易想到。
具体实现:
把这个整数拆分进数组;
对小写英文字符进行一 一匹配;
读数;

在具体的实现可以看代码,附有注释;

//币值转换
//给定整数-->转化为 大写中文格式-->转化为要求的简便格式
//读数的方法:
/*
	按照 四位分级 的原则,我国的读数法则是:
	    1.四位以内的数,按照数位顺序,从高位读起.
  		2.四位以上的数,先从右向左四位分级,
		   然后从最高级起,顺次读出各级里的数和它们的级名.
  		3.如果一个数末尾有“0”,末尾的“0”不读;每一级末尾的“0”也不读;
		   其他数位上,不论连续有几个“0”,只读一个零
*/
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

int Active_int_length(int *p);	//该整数数组的长度
int  length_num(int p); 	//计算该整数的长度
void divide_num(long int num, int *p);	//把整数拆分进数组
void exchange(int *p, char *storage, int len); //将数子转换成小写英文字符
void read_1(int *p, char *q, int len); //小于=4位
void read_2(int *p, char *q, int len); //大于于4位,小于=8位
void read_3(int *p, char *q, int len); //大于8位
void read_test(int *p, char *q, int num);	//读数终端

int main(void) {
	int i, j;
	char *storage;
	long int num;
	scanf("%ld", &num);
	int *Storage_num = (int *)malloc(sizeof(int) * length_num(num));	//动态内存分配
	divide_num(num, Storage_num);	//整数拆分
	int len = length_num(num);		//整数长度
	storage = (char *)malloc(sizeof(char) * len);
	exchange(Storage_num, storage, len);		//将拆分的整数的每一位转换成小写字母
	read_test(Storage_num, storage, num);		//读数
	free(Storage_num);		//释放内存
	free(storage);
	/*
	//验证数字是否存进数组
	for(i=0;i<length_num(num);i++){
		printf("%d ",Storage_num[i]);
	}
	*/
}

int  length_num(int p) {	//该数字的长度
	int len = 0;
	int mask;
	while (p > 9) {
		p /= 10;
		len++;
		if (p <= 9) {		//之所以在下文设置if判断,是为了考虑 数字 是 0 - 9这个范围
			len++;
			return len;
		}
	}
	if (p <= 9) {
		len++;
	}
	return len;		//返回该数字的长度
}

void divide_num(long int num, int *p) {	//把整数拆分进数组
	int i, j;
	int mask = (int)pow(10.0, (double)length_num(num)) / 10;		//10的位数阶乘
	int temp;
	for (i = mask, j = 0; i >= 1; i /= 10, j++) {
		temp = num % i;		//由后向前一次得到整数的数字
		*(p + j) = num / i;		//得到后面的第一位数字
		num = temp;
	}
}

void exchange(int *p, char *storage, int len) {	//将数字p转换成小写英文字符
	char character[10] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'};
	int i;

	for (i = 0; i < len; i++) {
		storage[i] = character[p[i]];		//类似case,这样写更简便
	}
}

void read_1(int *p, char *q, int len) { //小于=4位
	int i;
	char range[6] = {'\0', 'S', 'B', 'Q', 'W', 'Y'};		//先将“十,佰,千,万,亿”存放进range数组
	/*
	之所以采用这样的range数组,是为了凑齐 ,个 十 百 千 万 亿 ,这一顺序,因为个位不读,但不能为空,
	所以这里选择用'\0'代替,后续打印时要注意
	*/
	if (len <= 2) {		//当传送进来的是两位数时,执行以下步骤
		if (len == 1) {		//当长度为1时
			printf("%c", *(q + 0));
			return ;
		}
		for (i = 0; i < len; i++) {			//两位数
			if (i == 0 && p[i] == 1) {		//特殊情况:1 X
				if (p[1] == 0) {		//再考虑为 10 的情况
					printf("%c", range[1]);	// 10 读 十
					return;	//返回
				} else {				//再考虑 类似 12 的这种情况
					printf("%c", range[1]);		//只读一个 十,2再后面判断
				}
			} else {					//如果十位数不为1
				if (p[1] == 0) {		//个位数为0,类似 50
					printf("%c", q[i]);
					printf("%c ", range[1]);
					return ;
				} 					//正常情况 ,类似 56
				printf("%c", q[i]);
				printf("%c", range[len - 1 - i]);
			}

		}
		return ;
	}
//	printf("当前 *p = %d,p+1 = %d,p+2 = %d , p+3 = %d ,*q = %c\n", *(p + 0), *(p + 1), *(p + 2), *(p + 3), *(q + 0));
	for (i = 0; i < len; i++) {				//正常情况,类似111111111
		/*该部分多次对 0 这一特殊情况进行判断*/
		if (*(p + 0) == 0) {			//大于4位的情况传入时,第一位为0 (该部分用多个if主要是对,超过四位的数字,进行判断)
			if (*(p + 1) == *(p + 0)) {					//一二位为0
				if (*(p + 1) == 0 && *(p + 2) == 0) {	//一二三位为0
					if (*(p + 3) == 0) {		//全为0		-0000
						//全为0,不读
					} else {					// -0005
						printf("%c", *(q + 0));			//只有最后一位,读一个0
						printf("%c", *(q + 3));
						return ;
					}
				} else {				//因为条件比较多,索性就在if里面直接出结果
					if (*(p + 2) == 1) {				//最后两位不为0
						if (*(p + 3) == 0) {			//第三位不为0,第四位为0	//-0010
							printf("%c", *(q + 0));
							printf("%c", range[1]);
							return ;
						} else {					// -0015
							printf("%c", *(q + 0));
							printf("%c", range[1]);
							printf("%c", *(q + 3));
							return ;
						}
					} else {
						if (*(p + 3) == 0) {			//-0050
							printf("%c", *(q + 0));
							printf("%c", *(q + 2));
							printf("%c", range[1]);
							return ;
						} else {					//-0054
							printf("%c", *(q + 0));
							printf("%c", *(q + 2));
							printf("%c", range[1]);
							printf("%c", *(q + 3));
							return ;
						}
					}
				}
			} else {									//只有第一位为0	//-0123
				if (*(p + 2) == 0 && *(p + 3) == 0) {	// -100
					printf("%c", *(q + 0));	//0
					printf("%c", *(q + 1));
					printf("%c", range[2]);
					return ;
				} else if (*(p + 2) == 1) {
					if (*(p + 3) == 0) {		//-110
						printf("%c", *(q + 0));	//0
						printf("%c", *(q + 1));
						printf("%c", range[2]);
						printf("%c", *(q + 2));
						printf("%c", range[1]);
						return ;
					} else {			//-0312
						printf("%c", *(q + 0));	//0
						printf("%c", *(q + 1));
						printf("%c", range[2]);
						printf("%c", *(q + 2));
						printf("%c", range[1]);
						printf("%c", *(q + 3));
						return ;
					}
				} else {
					if (*(p + 3) == 0) {
						printf("%c", *(q + 0));	//0
						printf("%c", *(q + 1));
						printf("%c", range[2]);
						printf("%c", *(q + 2));
						printf("%c", range[1]);
						return ;
					} else {
						printf("%c", *(q + 0));	//0
						printf("%c", *(q + 1));
						printf("%c", range[2]);
						printf("%c", *(q + 2));
						printf("%c", range[1]);
						printf("%c", *(q + 3));
						return ;
					}
				}
			}
		} else {							//正常情况,四位以下及四位以上的正常情况
			if (*(p + i) == 0) {		//如果当前位有0
				if (*(p + i) == *(p + len - 1)) {	//当前位和最后一位都为0,则不读
					//不读
				} else if (*(p + i) == *(p + i + 1) ) {		//当前位 和下一位都为0,则只读一个0,跳过下一位
					printf("%c", q[i]);
					i++;
				} else if (*(p + i) != *(p + i + 1)) {		//当前位和下一位不相等(不为0),正常读
					printf("%c", q[i]);
				}
			} else {		//当前位没0
				printf("%c", q[i]);
				if (range[len - 1 - i] == '\0') {
					//因为range数组的range[0] = '\0',代表结束,因此读到该位置时,可以直接跳过
				} else {
					printf("%c", range[len - 1 - i]);		//正常读
				}

			}
		}
	}
}

void read_2(int *p, char *q, int len) { //大于4,小于=8位
	int i, temp;
	char range[6] = {'\0', 'S', 'B', 'Q', 'W', 'Y'};
	temp = len - 4;

	if (len <= 5) {		//因为万位在第5位置,所以这里进行特殊考虑
		for (i = 0; i < temp; i++) {
			printf("%c", q[i]);
			printf("%c", range[len - 1 - i]);
		}

	} else {
		read_1(p, q, len - 4);
		printf("%c", range[4]);
	}
	read_1(p + temp, q + temp, 4);	//特殊情况考虑结束后,传入剩下的位数
}

void read_3(int *p, char *q, int len) { //大于8位
	int i, temp;
	char range[6] = {'\0', 'S', 'B', 'Q', 'W', 'Y'};
	temp = len - 8;				//因为题目要求最大为9位,所以这里不进行过多考量,直接判断
	printf("%c", q[temp - 1]);
	printf("%c", range[5]);
	read_2(p + temp, q + temp, 8);		//传入剩下的位数
}

void read_test(int *p, char *q, int num) {		//读数终端
	int len = length_num(num);
	/*测试*/
//	int i;
//	for (i = 0; i < len; i++) {
//		printf("%d %c\n", *(p + i), *(q + i));
//	}
	if (len <= 4) {		//当该数字的位数小于=4位时
		read_1(p, q, len);

	} else if (len > 4 && len < 8 || len == 8) {	//该整数的位数>4且<=8位时
		read_2(p, q, len);

	} else if (len > 8) {		//该整数的位数大于8位时
		read_3(p, q, len);
	}
}

PTA测试点:
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值