币值转换
PTA基础编程题目集7-23
输入一个整数(位数不超过9位)代表一个人民币值(单位为元),请转换成财务要求的大写中文格式。如23108元,转换后变成“贰万叁仟壹百零捌”元。为了简化输出,用小写英文字母a-j顺序代表大写数字0-9,用S、B、Q、W、Y分别代表拾、百、仟、万、亿。于是23108元应被转换输出为“cWdQbBai”元。
输入格式:
输入在一行中给出一个不超过9位的非负整数。
输出格式:
在一行中输出转换后的结果。注意“零”的用法必须符合中文习惯。
输入样例1:
813227345
输出样例1:
iYbQdBcScWhQdBeSf
输入样例2:
6900
输出样例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测试点: