C++将数字转换为文字

5

我在一本书中发现了一个将数字转换为文字的程序。该初始程序可以转换1-1000之间的数字,但是你需要修改程序以接受高达1,000,000的数字。我已经让它可以处理20,999以内的数字,但无法处理更大的数字。我整天都在调试它,并查看了很多在线程序示例,但我看到的每个示例都使用了超出我作为初学者的技术。任何建议都将不胜感激。以下是我目前的代码。

#include <iostream>
#include <string>
using namespace std;

string digitName(int digit);
string teenName(int number);
string tensName(int number);
string intName(int number);


int main()
{
    int input;

    do
    {

    cout << "Please enter a positive integer: ";

    cin >> input;

    cout << "\n" << intName(input) << endl;

    cout << "\n\n" << endl;

    }while (input > 0);

    return 0;
}

string digitName(int digit)
{
    if (digit == 1) return "one";
    if (digit == 2) return "two";
    if (digit == 3) return "three";
    if (digit == 4) return "four";
    if (digit == 5) return "five";
    if (digit == 6) return "six";
    if (digit == 7) return "seven";
    if (digit == 8) return "eight";
    if (digit == 9) return "nine";

    return "";
}

string teenName(int number)
{
    if (number == 10) return "ten";
    if (number == 11) return "eleven";
    if (number == 12) return "twelve";
    if (number == 13) return "thirteen";
    if (number == 14) return "fourteen";
    if (number == 15) return "fifteen";
    if (number == 16) return "sixteen";
    if (number == 17) return "seventeen";
    if (number == 18) return "eighteen";
    if (number == 19) return "nineteen";

    return "";
}

string tensName(int number)
{
    if (number >= 90) return "ninety";
    if (number >= 80) return "eighty";
    if (number >= 70) return "seventy";
    if (number >= 60) return "sixty";
    if (number >= 50) return "fifty";
    if (number >= 40) return "fourty";
    if (number >= 30) return "thirty";
    if (number >= 20) return "twenty";

    return "";
}

string intName(int number)
{
    int part = number;
    string name;

    if (part >= 20000)
    {
        if (part % 10000 == 0)
        {
            name = tensName(part / 1000) + " thousand ";
            part = part % 1000;

        }else
        {
            name = tensName(part / 1000) + " ";
            part = part % 10000;
        }
    }

    if (part >= 10000)
    {
        name = teenName(part / 1000) + " thousand ";
        part = part % 1000;
    }

    if (part >= 1000)
    {
        name = digitName(part / 1000) + " thousand ";
        part = part % 1000;
    }

    if (part >= 100)
    {
        name = name + digitName(part / 100) + " hundred";
        part = part % 100;
    }

    if (part >= 20)
    {
        name = name + " " + tensName(part);
        part = part % 10;

    }else if (part >= 10)
    {
        name = name + " " + teenName(part);
        part = 0;
    }

    if (part > 0)
    {
        name = name + " " + digitName(part);
    }

    return name;
}

1
使用递归来避免重复太多的代码。 - Fengyang Wang
@FengyangWang 我知道有很多更简洁的编码方式可以得到相同的结果,我已经在这里看了一些。然而,我是个初学者,书上当前介绍的就是这种方式。 - RootFire
1
为什么不获取字符串的长度,这样就可以知道它是十万还是一百万。然后你可以使用 digitname 开始说“五十万……” - macroland
2
@iriejams -- 尝试这种方法。你需要知道如何将数字从1到999转换。其他任何事情都只是在每组三个数字之间放置十亿、百万和千的单词。现在,你已经硬编码了20000、10000等等,这是不必要的。只需专注于三位数,你就完成了90%的工作。 - PaulMcKenzie
另外,你可以将这些字符串放入查找表中,而不是无休止地使用 if 语句。例如,string units [] = {"", "one", "two", "three"..},当你想要打印单词“three”时,只需使用 units[3] - PaulMcKenzie
显示剩余5条评论
1个回答

12

两件事:如果您只是索引到数组中,可以节省很多输入。如果意识到在百位之后它会重复出现,那么您可以更普遍地解决这个问题。千、万、亿、兆和京都遵循完全相同的模式,因此可以进行递归处理。

    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;

    string digitName(int digit);
    string teenName(int number);
    string tensName(int number);
    string intName(int number);

    vector<string> ones {"","one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
    vector<string> teens {"ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen","sixteen", "seventeen", "eighteen", "nineteen"};
    vector<string> tens {"", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety"};

    string nameForNumber (long number) {
        if (number < 10) {
            return ones[number];
        } else if (number < 20) {
            return teens [number - 10];
        } else if (number < 100) {
            return tens[number / 10] + ((number % 10 != 0) ? " " + nameForNumber(number % 10) : "");
        } else if (number < 1000) {
            return nameForNumber(number / 100) + " hundred" + ((number % 100 != 0) ? " " + nameForNumber(number % 100) : "");
        } else if (number < 1000000) {
            return nameForNumber(number / 1000) + " thousand" + ((number % 1000 != 0) ? " " + nameForNumber(number % 1000) : "");
        } else if (number < 1000000000) {
            return nameForNumber(number / 1000000) + " million" + ((number % 1000000 != 0) ? " " + nameForNumber(number % 1000000) : "");
        } else if (number < 1000000000000) {
            return nameForNumber(number / 1000000000) + " billion" + ((number % 1000000000 != 0) ? " " + nameForNumber(number % 1000000000) : "");
        }
        return "error";
    }

    int main()
    {
        long input;
        do
        {
            cout << "Please enter a positive integer: ";    
            cin >> input;
            cout << "\n" << nameForNumber(input) << endl;
            cout << "\n\n" << endl;
        }while (input > 0);
        return 0;
    }

1
我一直在想这种方法是否可以跨越不同的语言使用。我希望像 Boost::Locale 这样的工具已经集成了将数字转换为名称(反之亦然)的功能。看起来 Boost::Locale 的 as::spellout 可以解决这个问题。 - SMGreenfield

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接