// kansuji.cpp --- アラビア数字を漢数字に変換する。
// Created by Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
// License: CC BY
#include <iostream>
#include <string>
#include <vector>
#include <cctype>
static const char *s_jdigits[] =
{
"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"
};
static const char *s_jgroup4[] =
{
"", "万", "億", "兆", "京", "垓", "抒", "穣", "溝", "澗", "正",
"載", "極", "恒河沙", "阿僧祇", "那由多", "不可思議", "無量大数"
};
// 部分文字列の置換。
static void
str_replace(std::string& str, const std::string& from, const std::string& to)
{
size_t i = 0;
for (;;)
{
i = str.find(from, i);
if (i == std::string::npos)
{
break;
}
str.replace(i, from.size(), to);
i += to.size();
}
}
// 文字列の左側の特定の文字を削除する。
template <typename t_string>
inline void
str_trim_left(t_string& str, const t_string& spaces)
{
size_t i = str.find_first_not_of(spaces);
if (i == t_string::npos)
{
str.clear();
}
else
{
str = str.substr(i);
}
}
// 四桁未満の数字を処理する。
static std::string
kansuji_kdigit4(const std::string& str)
{
static const char *s_kdigit4[] = { "", "十", "百", "千" };
std::string ret;
for (size_t i = 4 + 1; i > 0; )
{
--i;
if (str.size() >= i)
{
char ch = str[str.size() - i];
int n = ch - '0';
if (n > 1 || (i == 1 && n == 1))
{
ret += s_jdigits[n];
}
if (n > 0 && i > 0)
{
ret += s_kdigit4[i - 1];
}
}
}
return ret;
}
// 四桁ずつグループ化する。
static void
kansuji_group4(std::vector<std::string>& g4, const std::string& str)
{
g4.clear();
size_t i = str.size() % 4;
g4.push_back(str.substr(0, i));
for (; i < str.size(); i += 4)
{
g4.push_back(str.substr(i, 4));
}
}
// 小数点以下を漢数字に直す。
static std::string
kansuji_shosu(const std::string& str, bool& success)
{
std::string ret = "点";
success = false;
for (size_t i = 0; i < str.size(); ++i)
{
if (!std::isdigit(str[i]))
return ret; // 失敗
ret += s_jdigits[str[i] - '0'];
}
success = true;
return ret;
}
// アラビア数字を漢数字に変換する。
std::string
kansuji_convert(const std::string& str, bool& success)
{
std::string ret;
success = false;
std::string s = str;
// 無視すべき文字を消す。
str_replace(s, " ", "");
str_replace(s, " ", "");
str_replace(s, ",", "");
str_replace(s, "'", "");
// 全角を半角に。
str_replace(s, "0", "0");
str_replace(s, "1", "1");
str_replace(s, "2", "2");
str_replace(s, "3", "3");
str_replace(s, "4", "4");
str_replace(s, "5", "5");
str_replace(s, "6", "6");
str_replace(s, "7", "7");
str_replace(s, "8", "8");
str_replace(s, "9", "9");
str_replace(s, ".", ".");
str_replace(s, "−", "-");
if (s.empty())
{
return ret; // 失敗
}
if (s[0] == '-')
{
return "マイナス" + kansuji_convert(s.substr(1), success);
}
// 左側のゼロを消す。
str_trim_left(s, std::string("0"));
// 空の場合は、ゼロ。
if (s.empty())
{
ret = "零";
success = true;
return ret; // 成功
}
// 小数点の確認。
size_t idot = s.find('.');
if (idot != std::string::npos)
{
std::string shosu = kansuji_shosu(s.substr(idot + 1), success);
if (success)
{
return kansuji_convert(s.substr(0, idot), success) + shosu;
}
return ret; // 失敗
}
// 桁が多すぎないか?
if (s.size() > 73)
{
std::cout << "桁が多すぎます。" << std::endl;
return ret; // 失敗
}
// 数字以外のものがないか?
for (size_t i = 0; i < s.size(); ++i)
{
if (!std::isdigit(s[i]))
return ret; // 失敗
}
// 四桁ごとグループ化。
std::vector<std::string> g4;
kansuji_group4(g4, s);
// 四桁ごと出力。
for (size_t i = 0; i < g4.size(); ++i)
{
std::string kdigit4 = kansuji_kdigit4(g4[i]);
ret += kdigit4;
if (!kdigit4.empty())
{
ret += s_jgroup4[g4.size() - i - 1];
}
}
success = true;
return ret; // 成功
}
int main(void)
{
std::string str, kstr;
std::cout <<
"漢数字変換 by 片山博文MZ\n"
"「quit」で終了できるぞよ。\n" << std::endl;
for (;;)
{
std::cout << "数を入力せよ: ";
std::getline(std::cin, str);
if (str.empty() || str == "exit" || str == "quit" || str == "q")
break;
bool success = false;
kstr = kansuji_convert(str, success);
if (success)
{
std::cout << kstr << '\n' << std::endl;
}
else
{
std::cout << "入力をやり直せ、バカモン。" << std::endl;
}
}
return 0;
}
Ly8ga2Fuc3VqaS5jcHAgLS0tIOOCouODqeODk+OCouaVsOWtl+OCkua8ouaVsOWtl+OBq+WkieaPm+OBmeOCi+OAggovLyBDcmVhdGVkIGJ5IEthdGF5YW1hIEhpcm9mdW1pIE1aIDxrYXRheWFtYS5oaXJvZnVtaS5tekBnbWFpbC5jb20+Ci8vIExpY2Vuc2U6IENDIEJZCiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHZlY3Rvcj4KI2luY2x1ZGUgPGNjdHlwZT4KCnN0YXRpYyBjb25zdCBjaGFyICpzX2pkaWdpdHNbXSA9CnsKICAgICLpm7YiLCAi5LiAIiwgIuS6jCIsICLkuIkiLCAi5ZubIiwgIuS6lCIsICLlha0iLCAi5LiDIiwgIuWFqyIsICLkuZ0iCn07CgpzdGF0aWMgY29uc3QgY2hhciAqc19qZ3JvdXA0W10gPQp7CiAgICAiIiwgIuS4hyIsICLlhIQiLCAi5YWGIiwgIuS6rCIsICLlnpMiLCAi5oqSIiwgIuepoyIsICLmup0iLCAi5r6XIiwgIuatoyIsCiAgICAi6LyJIiwgIualtSIsICLmgZLmsrPmspkiLCAi6Zi/5YOn56WHIiwgIumCo+eUseWkmiIsICLkuI3lj6/mgJ3orbAiLCAi54Sh6YeP5aSn5pWwIgp9OwoKLy8g6YOo5YiG5paH5a2X5YiX44Gu572u5o+b44CCCnN0YXRpYyB2b2lkCnN0cl9yZXBsYWNlKHN0ZDo6c3RyaW5nJiBzdHIsIGNvbnN0IHN0ZDo6c3RyaW5nJiBmcm9tLCBjb25zdCBzdGQ6OnN0cmluZyYgdG8pCnsKICAgIHNpemVfdCBpID0gMDsKICAgIGZvciAoOzspCiAgICB7CiAgICAgICAgaSA9IHN0ci5maW5kKGZyb20sIGkpOwogICAgICAgIGlmIChpID09IHN0ZDo6c3RyaW5nOjpucG9zKQogICAgICAgIHsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQoKICAgICAgICBzdHIucmVwbGFjZShpLCBmcm9tLnNpemUoKSwgdG8pOwogICAgICAgIGkgKz0gdG8uc2l6ZSgpOwogICAgfQp9CgovLyDmloflrZfliJfjga7lt6blgbTjga7nibnlrprjga7mloflrZfjgpLliYrpmaTjgZnjgovjgIIKdGVtcGxhdGUgPHR5cGVuYW1lIHRfc3RyaW5nPgppbmxpbmUgdm9pZApzdHJfdHJpbV9sZWZ0KHRfc3RyaW5nJiBzdHIsIGNvbnN0IHRfc3RyaW5nJiBzcGFjZXMpCnsKICAgIHNpemVfdCBpID0gc3RyLmZpbmRfZmlyc3Rfbm90X29mKHNwYWNlcyk7CiAgICBpZiAoaSA9PSB0X3N0cmluZzo6bnBvcykKICAgIHsKICAgICAgICBzdHIuY2xlYXIoKTsKICAgIH0KICAgIGVsc2UKICAgIHsKICAgICAgICBzdHIgPSBzdHIuc3Vic3RyKGkpOwogICAgfQp9CgovLyDlm5vmoYHmnKrmuoDjga7mlbDlrZfjgpLlh6bnkIbjgZnjgovjgIIKc3RhdGljIHN0ZDo6c3RyaW5nCmthbnN1amlfa2RpZ2l0NChjb25zdCBzdGQ6OnN0cmluZyYgc3RyKQp7CiAgICBzdGF0aWMgY29uc3QgY2hhciAqc19rZGlnaXQ0W10gPSB7ICIiLCAi5Y2BIiwgIueZviIsICLljYMiIH07CgogICAgc3RkOjpzdHJpbmcgcmV0OwogICAgZm9yIChzaXplX3QgaSA9IDQgKyAxOyBpID4gMDsgKQogICAgewogICAgICAgIC0taTsKICAgICAgICBpZiAoc3RyLnNpemUoKSA+PSBpKQogICAgICAgIHsKICAgICAgICAgICAgY2hhciBjaCA9IHN0cltzdHIuc2l6ZSgpIC0gaV07CiAgICAgICAgICAgIGludCBuID0gY2ggLSAnMCc7CiAgICAgICAgICAgIGlmIChuID4gMSB8fCAoaSA9PSAxICYmIG4gPT0gMSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIHJldCArPSBzX2pkaWdpdHNbbl07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKG4gPiAwICYmIGkgPiAwKQogICAgICAgICAgICB7CiAgICAgICAgICAgICAgICByZXQgKz0gc19rZGlnaXQ0W2kgLSAxXTsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICByZXR1cm4gcmV0Owp9CgovLyDlm5vmoYHjgZrjgaTjgrDjg6vjg7zjg5fljJbjgZnjgovjgIIKc3RhdGljIHZvaWQKa2Fuc3VqaV9ncm91cDQoc3RkOjp2ZWN0b3I8c3RkOjpzdHJpbmc+JiBnNCwgY29uc3Qgc3RkOjpzdHJpbmcmIHN0cikKewogICAgZzQuY2xlYXIoKTsKCiAgICBzaXplX3QgaSA9IHN0ci5zaXplKCkgJSA0OwogICAgZzQucHVzaF9iYWNrKHN0ci5zdWJzdHIoMCwgaSkpOwoKICAgIGZvciAoOyBpIDwgc3RyLnNpemUoKTsgaSArPSA0KQogICAgewogICAgICAgIGc0LnB1c2hfYmFjayhzdHIuc3Vic3RyKGksIDQpKTsKICAgIH0KfQoKLy8g5bCP5pWw54K55Lul5LiL44KS5ryi5pWw5a2X44Gr55u044GZ44CCCnN0YXRpYyBzdGQ6OnN0cmluZwprYW5zdWppX3Nob3N1KGNvbnN0IHN0ZDo6c3RyaW5nJiBzdHIsIGJvb2wmIHN1Y2Nlc3MpCnsKICAgIHN0ZDo6c3RyaW5nIHJldCA9ICLngrkiOwogICAgc3VjY2VzcyA9IGZhbHNlOwoKICAgIGZvciAoc2l6ZV90IGkgPSAwOyBpIDwgc3RyLnNpemUoKTsgKytpKQogICAgewogICAgICAgIGlmICghc3RkOjppc2RpZ2l0KHN0cltpXSkpCiAgICAgICAgICAgIHJldHVybiByZXQ7ICAgICAvLyDlpLHmlZcKCiAgICAgICAgcmV0ICs9IHNfamRpZ2l0c1tzdHJbaV0gLSAnMCddOwogICAgfQoKICAgIHN1Y2Nlc3MgPSB0cnVlOwogICAgcmV0dXJuIHJldDsKfQoKLy8g44Ki44Op44OT44Ki5pWw5a2X44KS5ryi5pWw5a2X44Gr5aSJ5o+b44GZ44KL44CCCnN0ZDo6c3RyaW5nCmthbnN1amlfY29udmVydChjb25zdCBzdGQ6OnN0cmluZyYgc3RyLCBib29sJiBzdWNjZXNzKQp7CiAgICBzdGQ6OnN0cmluZyByZXQ7CgogICAgc3VjY2VzcyA9IGZhbHNlOwoKICAgIHN0ZDo6c3RyaW5nIHMgPSBzdHI7CgogICAgLy8g54Sh6KaW44GZ44G544GN5paH5a2X44KS5raI44GZ44CCCiAgICBzdHJfcmVwbGFjZShzLCAiICIsICIiKTsKICAgIHN0cl9yZXBsYWNlKHMsICLjgIAiLCAiIik7CiAgICBzdHJfcmVwbGFjZShzLCAiLCIsICIiKTsKICAgIHN0cl9yZXBsYWNlKHMsICInIiwgIiIpOwoKICAgIC8vIOWFqOinkuOCkuWNiuinkuOBq+OAggogICAgc3RyX3JlcGxhY2UocywgIu+8kCIsICIwIik7CiAgICBzdHJfcmVwbGFjZShzLCAi77yRIiwgIjEiKTsKICAgIHN0cl9yZXBsYWNlKHMsICLvvJIiLCAiMiIpOwogICAgc3RyX3JlcGxhY2UocywgIu+8kyIsICIzIik7CiAgICBzdHJfcmVwbGFjZShzLCAi77yUIiwgIjQiKTsKICAgIHN0cl9yZXBsYWNlKHMsICLvvJUiLCAiNSIpOwogICAgc3RyX3JlcGxhY2UocywgIu+8liIsICI2Iik7CiAgICBzdHJfcmVwbGFjZShzLCAi77yXIiwgIjciKTsKICAgIHN0cl9yZXBsYWNlKHMsICLvvJgiLCAiOCIpOwogICAgc3RyX3JlcGxhY2UocywgIu+8mSIsICI5Iik7CiAgICBzdHJfcmVwbGFjZShzLCAi77yOIiwgIi4iKTsKICAgIHN0cl9yZXBsYWNlKHMsICLiiJIiLCAiLSIpOwoKICAgIGlmIChzLmVtcHR5KCkpCiAgICB7CiAgICAgICAgcmV0dXJuIHJldDsgICAgIC8vIOWkseaVlwogICAgfQoKICAgIGlmIChzWzBdID09ICctJykKICAgIHsKICAgICAgICByZXR1cm4gIuODnuOCpOODiuOCuSIgKyBrYW5zdWppX2NvbnZlcnQocy5zdWJzdHIoMSksIHN1Y2Nlc3MpOwogICAgfQoKICAgIC8vIOW3puWBtOOBruOCvOODreOCkua2iOOBmeOAggogICAgc3RyX3RyaW1fbGVmdChzLCBzdGQ6OnN0cmluZygiMCIpKTsKCiAgICAvLyDnqbrjga7loLTlkIjjga/jgIHjgrzjg63jgIIKICAgIGlmIChzLmVtcHR5KCkpCiAgICB7CiAgICAgICAgcmV0ID0gIumbtiI7CiAgICAgICAgc3VjY2VzcyA9IHRydWU7CiAgICAgICAgcmV0dXJuIHJldDsgICAgIC8vIOaIkOWKnwogICAgfQoKICAgIC8vIOWwj+aVsOeCueOBrueiuuiqjeOAggogICAgc2l6ZV90IGlkb3QgPSBzLmZpbmQoJy4nKTsKICAgIGlmIChpZG90ICE9IHN0ZDo6c3RyaW5nOjpucG9zKQogICAgewogICAgICAgIHN0ZDo6c3RyaW5nIHNob3N1ID0ga2Fuc3VqaV9zaG9zdShzLnN1YnN0cihpZG90ICsgMSksIHN1Y2Nlc3MpOwogICAgICAgIGlmIChzdWNjZXNzKQogICAgICAgIHsKICAgICAgICAgICAgcmV0dXJuIGthbnN1amlfY29udmVydChzLnN1YnN0cigwLCBpZG90KSwgc3VjY2VzcykgKyBzaG9zdTsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHJldDsgICAgIC8vIOWkseaVlwogICAgfQoKICAgIC8vIOahgeOBjOWkmuOBmeOBjuOBquOBhOOBi++8nwogICAgaWYgKHMuc2l6ZSgpID4gNzMpCiAgICB7CiAgICAgICAgc3RkOjpjb3V0IDw8ICLmoYHjgYzlpJrjgZnjgY7jgb7jgZnjgIIiIDw8IHN0ZDo6ZW5kbDsKICAgICAgICByZXR1cm4gcmV0OyAgICAgLy8g5aSx5pWXCiAgICB9CgogICAgLy8g5pWw5a2X5Lul5aSW44Gu44KC44Gu44GM44Gq44GE44GL77yfCiAgICBmb3IgKHNpemVfdCBpID0gMDsgaSA8IHMuc2l6ZSgpOyArK2kpCiAgICB7CiAgICAgICAgaWYgKCFzdGQ6OmlzZGlnaXQoc1tpXSkpCiAgICAgICAgICAgIHJldHVybiByZXQ7ICAgICAvLyDlpLHmlZcKICAgIH0KCiAgICAvLyDlm5vmoYHjgZTjgajjgrDjg6vjg7zjg5fljJbjgIIKICAgIHN0ZDo6dmVjdG9yPHN0ZDo6c3RyaW5nPiBnNDsKICAgIGthbnN1amlfZ3JvdXA0KGc0LCBzKTsKCiAgICAvLyDlm5vmoYHjgZTjgajlh7rlipvjgIIKICAgIGZvciAoc2l6ZV90IGkgPSAwOyBpIDwgZzQuc2l6ZSgpOyArK2kpCiAgICB7CiAgICAgICAgc3RkOjpzdHJpbmcga2RpZ2l0NCA9IGthbnN1amlfa2RpZ2l0NChnNFtpXSk7CgogICAgICAgIHJldCArPSBrZGlnaXQ0OwoKICAgICAgICBpZiAoIWtkaWdpdDQuZW1wdHkoKSkKICAgICAgICB7CiAgICAgICAgICAgIHJldCArPSBzX2pncm91cDRbZzQuc2l6ZSgpIC0gaSAtIDFdOwogICAgICAgIH0KICAgIH0KCiAgICBzdWNjZXNzID0gdHJ1ZTsKICAgIHJldHVybiByZXQ7ICAgICAvLyDmiJDlip8KfQoKaW50IG1haW4odm9pZCkKewogICAgc3RkOjpzdHJpbmcgc3RyLCBrc3RyOwoKICAgIHN0ZDo6Y291dCA8PAogICAgICAgICLmvKLmlbDlrZflpInmj5sgYnkg54mH5bGx5Y2a5paHTVpcbiIKICAgICAgICAi44CMcXVpdOOAjeOBp+e1guS6huOBp+OBjeOCi+OBnuOCiOOAglxuIiA8PCBzdGQ6OmVuZGw7CgogICAgZm9yICg7OykKICAgIHsKICAgICAgICBzdGQ6OmNvdXQgPDwgIuaVsOOCkuWFpeWKm+OBm+OCiDogIjsKICAgICAgICBzdGQ6OmdldGxpbmUoc3RkOjpjaW4sIHN0cik7CiAgICAgICAgaWYgKHN0ci5lbXB0eSgpIHx8IHN0ciA9PSAiZXhpdCIgfHwgc3RyID09ICJxdWl0IiB8fCBzdHIgPT0gInEiKQogICAgICAgICAgICBicmVhazsKCiAgICAgICAgYm9vbCBzdWNjZXNzID0gZmFsc2U7CiAgICAgICAga3N0ciA9IGthbnN1amlfY29udmVydChzdHIsIHN1Y2Nlc3MpOwogICAgICAgIGlmIChzdWNjZXNzKQogICAgICAgIHsKICAgICAgICAgICAgc3RkOjpjb3V0IDw8IGtzdHIgPDwgJ1xuJyA8PCBzdGQ6OmVuZGw7CiAgICAgICAgfQogICAgICAgIGVsc2UKICAgICAgICB7CiAgICAgICAgICAgIHN0ZDo6Y291dCA8PCAi5YWl5Yqb44KS44KE44KK55u044Gb44CB44OQ44Kr44Oi44Oz44CCIiA8PCBzdGQ6OmVuZGw7CiAgICAgICAgfQogICAgfQoKICAgIHJldHVybiAwOwp9Cg==