PAT Basic 1002
本题代码可以参考这里。
原题: 1002. 写出这个数 (20)
读入一个自然数n,计算其各位数字之和,用汉语拼音写出和的每一位数字。
输入格式:
每个测试输入包含1个测试用例,即给出自然数n的值。这里保证n小于10100。
输出格式:
在一行内输出n的各位数字之和的每一位,拼音数字间有1 空格,但一行中最后一个拼音数字后没有空格。
输入样例:
1234567890987654321123456789
输出样例:
yi san wu
注意
时间限制: 400 ms
内存限制: 65536 kB
代码长度限制: 8000 B
判题程序: Standard
作者: CHEN, Yue
题目分析
-
输入
输入视作字符串,而不是整数
-
因为输入上限是10^100,所以字符串长度最大为100
-
将每个字符转化为数字,求和得到sigma
由于字符串长度最大为100,每一位最大数字是9,可得sigma最大为9×100=900
-
-
输出
建立一个字符串数组
num_pinyin
,每个元素是0~9的拼音const char *num_pinyin[] = {"ling", "yi", "er", "san", "si", "wu", "liu", "qi", "ba", "jiu"};
-
普通解法
输入求和得到sigma
scanf("%s", us_num); while( us_num[i]!='\0' ){ sigma += (us_num[i++]-'0'); }
获取sigma各数位的数字
p_hundreds = sigma / 100; sigma = sigma - p_hundreds*100; p_tens = sigma / 10; sigma = sigma - p_tens*10; p_units = sigma;
输出逻辑
- a. 从高到低,
- b. 高位非零,低位全打
- c. 高位为零,内嵌if,下一位作为高位,回到b
if( 0!=p_hundreds ) printf("%s %s %s", num_pinyin[p_hundreds], num_pinyin[p_tens], num_pinyin[p_units]); else if( 0!=p_tens ) printf("%s %s", num_pinyin[p_tens], num_pinyin[p_units]); else printf("%s", num_pinyin[p_units]);
-
高阶写法
参考这里,如果掌握了
int(), str(), map(), sum()
,则可以用python写出更精妙的代码:num_pinyin = ['ling', 'yi', 'er', 'san', 'si', 'wu', 'liu', 'qi', 'ba', 'jiu'] us_num = raw_input() us_num = map(int, us_num) sigma = sum(us_num) sigma = str(sigma) for i in range(len(sigma)): print num_pinyin[int(sigma[i])],
只有10行左右,而且逻辑清晰。我们也可以参考这个思路,改写C的代码。对应
sigma = str(sigma)
sprintf(us_num, "%d", sigma);
对应后两行,则有
while(us_num[i+1]!='\0') printf("%s ", num_pinyin[us_num[i++]-'0']); printf("%s", num_pinyin[us_num[i]-'0']);
-
更新1—增加cpp的实现
-
时间效率略逊于C,但是属于同一数量级,应该说是几乎相同。
-
用
string类
代替char数组
,以保存字符串。会根据需要自动分配内存空间,不需要手动申请最大空间。自带多种操作方法,如.size()
等。注意string类
不是以'\0'
结尾,用长度.size()
判断结尾。 -
stringstream
代替sprintf()
,将数字转变成字符串#include <sstream> string num2string(int num){ stringstream ss; ss << num; return ss.str(); }
-
附加两个将字符串变成数字的方法。第一个需要在编译的时候加上
-std=c++11
int num=0; string us_str="123"; num = stoi(us_str);
第二个则仍是利用
sstream
库#include <sstream> int string2num(string us_str){ int num=0; stringstream ss; ss << us_str; // stringstream ss(us_str); ss >> num; return num; }
-
部分测试用例:
-
test1
测试用例 1234567890987654321123456789 输出 yi san wu
-
test2
测试用例: 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 输出: si wu ling
-
test3
测试用例: 999999999999 输出: yi ling ba
参考
-
字符串数组的声明与初始化
const char *num[]={"one", "two", "three"};
-
获取字符串输入
char num[10]; gets(num); //可能溢出 fgets(num, 10, stdin); //会保存作为输入确认的'\n' scanf("%s", num); //遇到空格结束
python中字符串可以用单引号
'
,也可以用双引号"
。用惯了python,就容易忘记C的语法要求。。C中单引号只能包裹字符,双引号包裹的是字符串。字符串是以空字符
'\0'
结尾的char数组
。 -
sprintf()
在
stdio.h
中声明。原型为int sprintf(char *str, const char *format, ...);
不同于
printf()
的打印输出,它的作用是将内容保存为字符串,类似于python中的str()
函数,比如char us_num[10]; int sigma = 12345; sprintf(us_num, "%d", sigma); printf("%s", us_num);
则
us_num
的内容就变成了”12345”。
—更新cpp参考—
(END)