A1082 Read Number in Chinese

该博客详细介绍了如何实现将整数读作传统中文的过程。首先判断数字的正负,然后通过处理特例0,再将数字转换为字符数组。接着,从后往前遍历数组并结合中文数字单位输出。思路包括两种:一种是逐位处理,另一种是按节处理。优化后的代码更简洁,通过左右指针定位数字节并输出相应中文。博客涉及字符串处理、条件判断和数组操作等编程技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述

Given an integer with no more than 9 digits, you are supposed to read it in the traditional Chinese way. Output Fu first if it is negative. For example, -123456789 is read as Fu yi Yi er Qian san Bai si Shi wu Wan liu Qian qi Bai ba Shi jiu. Note: zero (ling) must be handled correctly according to the Chinese tradition. For example, 100800 is yi Shi Wan ling ba Bai.

输入格式

Each input file contains one test case, which gives an integer with no more than 9 digits.

输出格式

For each test case, print in a line the Chinese way of reading the number. The characters are separated by a space and there must be no extra space at the end of the line.

输入样例1

-123456789
(结尾无空行)

输出样例1

Fu yi Yi er Qian san Bai si Shi wu Wan liu Qian qi Bai ba Shi jiu
(结尾无空行)

输入样例2

100800
(结尾无空行)

输出样例2

yi Shi Wan ling ba Bai
(结尾无空行)

思路

  1. 输入样例先用整数n接收,判断正负,若为特例0则直接输出 ling 结束函数,若为负则先输出 “Fu” 并将n变成正数,得到绝对值n;
  2. do…while 循环将整数每一位依次存放在二维数组num[3][5] 中,每一行放四位,最后以 ‘\0’ 结尾,例如 n = 1234567,则二维数组num[][] = { {“7654”} ,{“321”} };
  3. 从后往前遍历二维数组。每行第 i 个字符输出后再输出对应单位 carry2[i] 。

C语言代码

#include<stdio.h>
#include<string.h>

char carry1[3][7] = {"\0"," Wan"," Yi"};
char carry2[4][7] = {"\0"," Shi"," Bai"," Qian"};
char trans[10][5] = {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};

int main(){
	int n, row = 0, col = 0;
	char num[3][5];
	bool jud = false; //记录n是否是负数
	scanf("%d", &n);
	
//特殊处理特例0	
	if(n==0) { 
		printf("ling"); 
		return 0;
	}
//当n为负数时
	if(n < 0){ 
		printf("Fu");
		jud = true;
		n = -n;
	}
	
//依次将n中每一位数字以字符形式存放在二维数组对应的位置上	
	do{ 
		num[row][col++] = n % 10 + '0';
		if(col % 4 == 0){ //每行存放四个字符,并以'\0'结束
			num[row][col] = '\0';
			col = 0;
			row++;
		}
		n = n / 10;
	}while(n != 0);
	if(col == 0) //位数正好整除4
		num[row-1][5] = '\0';
	else{ //位数取余4不为0时,最后一位的下一个字符赋值'\0'
		num[row][col] = '\0';
		row++;
	}
	
//遍历二维数组,输出对应的中文数字
	for(int i = row-1; i >= 0; i--){
		int len = strlen(num[i]);
		bool carry_out = true;  //记录是否应该输出carry1[]中的单位
		for(int j = len-1; j >= 0; j--){ 
			if(num[i][j] != '0'){ //存放的对应字符不为'0'
				int temp = num[i][j] -'0';
				if(i == row-1 && j == len-1 && jud) //n<0且输出第一个字符时
					printf(" %s", trans[temp]); //前面带空格
				else if(i == row-1 && j == len-1) //n>0且输出第一个字符时
					printf("%s", trans[temp]); //前面不带空格
				else 
					printf(" %s", trans[temp]);//其他情况,字符前面都自带空格
			}
			else if(j == 3){ //第3位置的字符为0时
				if(num[i][2] != '0' || num[i][1] != '0' || num[i][0] != '0') //后面字符不都为'0'时
					printf(" ling");
				else{ //第i行表示的数字为0000时
					carry_out = false;
					break;
				}
			}
			else if(j == 2){ //第2位置的字符为'0'时
				if(num[i][3] != '0' && num[i][1] != '0') //为"X0X-"时
					printf(" ling");
				else if(num[i][3] != '0' && num[i][2] == '0' && num[i][1] == '0' && num[i][0] != '0'){
				//为'X00X'时
					printf(" ling");
					j--;
				}
			}
			else if(j == 1){ //当第1位置的字符为'0'时
				if(num[i][2] != '0' && num[i][0] != '0') //为'-X0X'时
					printf(" ling");
			}
			if(j != 0 && num[i][j] != '0') //每行第0个字符且不为'0'时
				printf("%s", carry2[j]);
		}
		if(row != 0 && carry_out) //第i行字符不为'0000'且不是第0行时
			printf("%s", carry1[i]);
	} 
	return 0;
}

注意:

  1. 因为二维数组每一行的第0个字符若为‘0’不输出 ‘ling’ 所以注意特例0,需要单独考虑;
  2. 对于’0’字符是否需要输出中文读音的问题需要考虑全面;
  3. 对整数进行字符化处理时,注意末尾‘\0’的结束问题。

思路优化

  1. 将数字按照字符串的形式处理,并设置 left 和 right 下标处理数字的每一小节(个节、万节、亿节),left 指向输出的位,right指向输出节的个位;
  2. 对于 ‘ling’ 的输出采用累积形式,首次遇到0令 flag = true表示存在累积的0;遇到非0时,先判断 flag是否为true,若是,则先输出 ‘ling’ 再输出对应中文及位号。处理完一小节再输出万或者亿。

优化C语言代码

#include<stdio.h>
#include<string.h>

char num[10][5] = {"ling","yi","er","san","si","wu","liu","qi","ba","jiu"};
char wei[5][5] = {"Shi","Bai","Qian","Wan","Yi"};

int main(){
	char str[15];
	scanf("%s", str);
	int len = strlen(str);
	int left = 0, right = len - 1;
	if(str[0] == '-'){ //若输入为负数
		printf("Fu"); 
		left++; //left指向下一个字符
	}
	while(left + 4 <= right) //找到第一个节(个节、万节、亿节)
		right -= 4;
	while(left < len){ //循环输出直到left遍历完整个字符串
		bool flag = false; //flag == false 表示没有累积的0
		bool isPrint = false; // isPrint == false 表示给小节没有输出过其中的位
		while(left <= right){ //遍历一小节
			if(left > 0 && str[left] =='0') //如果当前位位0
				flag = true;
			else{
				if(flag == true){ //如果存在累积0
					printf(" ling");
					flag = false;
				}
				if(left > 0) printf(" "); //只要不是正数的首位,都在输出前先输出一个空格
				printf("%s", num[str[left]-'0']); 
				isPrint = true; //至少有一位数字被输出
				if(left != right) 
					printf(" %s", wei[right-left-1]); //除了个位,输出十千百
			}
			left++; //left向右移动一位
		}
		if(isPrint == true && right != len-1) //只要不是个节或没有输出的节,输出万亿
			printf(" %s", wei[(len-1-right)/4 + 2]);
		right += 4; //right向后移动4位
	}
	return 0;
}

对于分区域的字符串遍历可以采用下标 left,right 等形式标记遍历的位置及每一区域的分界处

A1082 Read Number in Chinese原题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值