fork download
  1. // kansuji.cpp --- アラビア数字を漢数字に変換する。
  2. // Created by Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
  3. // License: CC BY
  4. #include <iostream>
  5. #include <string>
  6. #include <vector>
  7. #include <cctype>
  8.  
  9. static const char *s_jdigits[] =
  10. {
  11. "零", "一", "二", "三", "四", "五", "六", "七", "八", "九"
  12. };
  13.  
  14. static const char *s_jgroup4[] =
  15. {
  16. "", "万", "億", "兆", "京", "垓", "抒", "穣", "溝", "澗", "正",
  17. "載", "極", "恒河沙", "阿僧祇", "那由多", "不可思議", "無量大数"
  18. };
  19.  
  20. // 部分文字列の置換。
  21. static void
  22. str_replace(std::string& str, const std::string& from, const std::string& to)
  23. {
  24. size_t i = 0;
  25. for (;;)
  26. {
  27. i = str.find(from, i);
  28. if (i == std::string::npos)
  29. {
  30. break;
  31. }
  32.  
  33. str.replace(i, from.size(), to);
  34. i += to.size();
  35. }
  36. }
  37.  
  38. // 文字列の左側の特定の文字を削除する。
  39. template <typename t_string>
  40. inline void
  41. str_trim_left(t_string& str, const t_string& spaces)
  42. {
  43. size_t i = str.find_first_not_of(spaces);
  44. if (i == t_string::npos)
  45. {
  46. str.clear();
  47. }
  48. else
  49. {
  50. str = str.substr(i);
  51. }
  52. }
  53.  
  54. // 四桁未満の数字を処理する。
  55. static std::string
  56. kansuji_kdigit4(const std::string& str)
  57. {
  58. static const char *s_kdigit4[] = { "", "十", "百", "千" };
  59.  
  60. std::string ret;
  61. for (size_t i = 4 + 1; i > 0; )
  62. {
  63. --i;
  64. if (str.size() >= i)
  65. {
  66. char ch = str[str.size() - i];
  67. int n = ch - '0';
  68. if (n > 1 || (i == 1 && n == 1))
  69. {
  70. ret += s_jdigits[n];
  71. }
  72. if (n > 0 && i > 0)
  73. {
  74. ret += s_kdigit4[i - 1];
  75. }
  76. }
  77. }
  78.  
  79. return ret;
  80. }
  81.  
  82. // 四桁ずつグループ化する。
  83. static void
  84. kansuji_group4(std::vector<std::string>& g4, const std::string& str)
  85. {
  86. g4.clear();
  87.  
  88. size_t i = str.size() % 4;
  89. g4.push_back(str.substr(0, i));
  90.  
  91. for (; i < str.size(); i += 4)
  92. {
  93. g4.push_back(str.substr(i, 4));
  94. }
  95. }
  96.  
  97. // 小数点以下を漢数字に直す。
  98. static std::string
  99. kansuji_shosu(const std::string& str, bool& success)
  100. {
  101. std::string ret = "点";
  102. success = false;
  103.  
  104. for (size_t i = 0; i < str.size(); ++i)
  105. {
  106. if (!std::isdigit(str[i]))
  107. return ret; // 失敗
  108.  
  109. ret += s_jdigits[str[i] - '0'];
  110. }
  111.  
  112. success = true;
  113. return ret;
  114. }
  115.  
  116. // アラビア数字を漢数字に変換する。
  117. std::string
  118. kansuji_convert(const std::string& str, bool& success)
  119. {
  120. std::string ret;
  121.  
  122. success = false;
  123.  
  124. std::string s = str;
  125.  
  126. // 無視すべき文字を消す。
  127. str_replace(s, " ", "");
  128. str_replace(s, " ", "");
  129. str_replace(s, ",", "");
  130. str_replace(s, "'", "");
  131.  
  132. // 全角を半角に。
  133. str_replace(s, "0", "0");
  134. str_replace(s, "1", "1");
  135. str_replace(s, "2", "2");
  136. str_replace(s, "3", "3");
  137. str_replace(s, "4", "4");
  138. str_replace(s, "5", "5");
  139. str_replace(s, "6", "6");
  140. str_replace(s, "7", "7");
  141. str_replace(s, "8", "8");
  142. str_replace(s, "9", "9");
  143. str_replace(s, ".", ".");
  144. str_replace(s, "−", "-");
  145.  
  146. if (s.empty())
  147. {
  148. return ret; // 失敗
  149. }
  150.  
  151. if (s[0] == '-')
  152. {
  153. return "マイナス" + kansuji_convert(s.substr(1), success);
  154. }
  155.  
  156. // 左側のゼロを消す。
  157. str_trim_left(s, std::string("0"));
  158.  
  159. // 空の場合は、ゼロ。
  160. if (s.empty())
  161. {
  162. ret = "零";
  163. success = true;
  164. return ret; // 成功
  165. }
  166.  
  167. // 小数点の確認。
  168. size_t idot = s.find('.');
  169. if (idot != std::string::npos)
  170. {
  171. std::string shosu = kansuji_shosu(s.substr(idot + 1), success);
  172. if (success)
  173. {
  174. return kansuji_convert(s.substr(0, idot), success) + shosu;
  175. }
  176. return ret; // 失敗
  177. }
  178.  
  179. // 桁が多すぎないか?
  180. if (s.size() > 73)
  181. {
  182. std::cout << "桁が多すぎます。" << std::endl;
  183. return ret; // 失敗
  184. }
  185.  
  186. // 数字以外のものがないか?
  187. for (size_t i = 0; i < s.size(); ++i)
  188. {
  189. if (!std::isdigit(s[i]))
  190. return ret; // 失敗
  191. }
  192.  
  193. // 四桁ごとグループ化。
  194. std::vector<std::string> g4;
  195. kansuji_group4(g4, s);
  196.  
  197. // 四桁ごと出力。
  198. for (size_t i = 0; i < g4.size(); ++i)
  199. {
  200. std::string kdigit4 = kansuji_kdigit4(g4[i]);
  201.  
  202. ret += kdigit4;
  203.  
  204. if (!kdigit4.empty())
  205. {
  206. ret += s_jgroup4[g4.size() - i - 1];
  207. }
  208. }
  209.  
  210. success = true;
  211. return ret; // 成功
  212. }
  213.  
  214. int main(void)
  215. {
  216. std::string str, kstr;
  217.  
  218. std::cout <<
  219. "漢数字変換 by 片山博文MZ\n"
  220. "「quit」で終了できるぞよ。\n" << std::endl;
  221.  
  222. for (;;)
  223. {
  224. std::cout << "数を入力せよ: ";
  225. std::getline(std::cin, str);
  226. if (str.empty() || str == "exit" || str == "quit" || str == "q")
  227. break;
  228.  
  229. bool success = false;
  230. kstr = kansuji_convert(str, success);
  231. if (success)
  232. {
  233. std::cout << kstr << '\n' << std::endl;
  234. }
  235. else
  236. {
  237. std::cout << "入力をやり直せ、バカモン。" << std::endl;
  238. }
  239. }
  240.  
  241. return 0;
  242. }
  243.  
Success #stdin #stdout 0s 15256KB
stdin
0
123
12345
100000
1258666
777777777777789
-123.58
100000000000000000000000023

stdout
漢数字変換 by 片山博文MZ
「quit」で終了できるぞよ。

数を入力せよ: 零

数を入力せよ: 百二十三

数を入力せよ: 一万二千三百四十五

数を入力せよ: 十万

数を入力せよ: 百二十五万八千六百六十六

数を入力せよ: 七百七十七兆七千七百七十七億七千七百七十七万七千七百八十九

数を入力せよ: マイナス百二十三点五八

数を入力せよ: 百抒二十三

数を入力せよ: