1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
#include <iostream>
#include <string>
#include <algorithm>
// the german names of the numbers
const std::string from_0_to_9[] = { "Null", "ein", "zwei", "drei", "vier", "fuenf", "sechs", "sieben", "acht", "neun" };
const std::string from_10_to_19[] = { "zehn", "elf", "zwoelf", "dreizehn", "vierzehn", "fuenfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn" };
const std::string from_20_step_10[] = { "zwanzig", "dreissig", "vierzig", "fuenfzig", "sechzig", "siebzig", "achtzig", "neunzig" };
const std::string from_100[] = { "hundert", "tausend", "million", "milliarde", "billion", "billiarde", "trillion", "trilliarde",
"quadrillion", "quadrilliarde", "quintillion", "quintilliarde", "sextillion", "sextilliarde", "septillion", "septilliarde",
"oktillion", "oktilliarde", "nonillion", "nonilliarde", "dezillion", "dezilliarde", "undezillion", "undezilliarde", "dodezillion",
"dodezilliarde", "tredezillion", "tredezilliarde", "quattuordezillion", "quattuordezilliarde", "quindezillion", "quindezilliarde",
"sedezillion", "sedezilliarde", "septendezillion", "septendezilliarde", "dodevigintillion", "dodevigintilliarde", "undevigintillion",
"undevigintilliarde", "vigintillion", "vigintilliarde", "trigintillion", "trigintilliarde", "zentillion", "zentilliarde" };
// this function makes sure that only digits are processed
// (avoids crash in case of wrongful input)
int GetValue(const std::string &num, const int offs)
{
int result = 0;
if(offs < num.size()) // offset must not exceed the number
result = isdigit(num[offs]) ? // only digits are allowed
(num[offs] - '0') : 0;
return result;
}
// this returns the string for the 2 digits value
std::string GetBelowHundred(const std::string &num, const int offs)
{
std::string result;
if(offs < num.size()) // offset must not exceed the number
{
// gets the first digit
const int value_from_0_to_9 = GetValue(num, offs);
// checks if a second digit exists
// (a single digit may have another name / null may exists)
bool more = ((offs + 1) < num.size());
if(more) // ok there're two digits
{
// gets the second digit
const int value_from_10 = GetValue(num, offs + 1);
if(value_from_10 > 0) // only non null are taken into account
{
if(1 == value_from_10) // the value is 10+
result += from_10_to_19[value_from_0_to_9]; // the least significant digit determines the name
else // the value is 20+
{
// name wise the least significant digit is placed in front!
if(value_from_0_to_9 > 0) // only least significant digits >0 are taken into account
{
result += from_0_to_9[value_from_0_to_9]; // adds the name of the digit
result += "und"; // here the connecting word 'und' is required
}
result += from_20_step_10[value_from_10 - 2]; // 0/1 are treated diffently hence -2
}
}
else if(value_from_0_to_9 > 0) // leading digits means different treatment
{
result += "und"; // the connecting word 'und' is required then
more = false; // but it's considered a single digit
}
}
if(!more) // when it's a single digit it's not been treated yet
{
if((value_from_0_to_9 > 0) || (1 == num.size())) //the name 'null' is allowed only if there's just 1 digit
{
result += from_0_to_9[value_from_0_to_9]; // the name of the least signigicant digit
if(1 == value_from_0_to_9) // with no leading digits the value one
result += 's'; // needs 's' to be appended
}
}
}
return result;
}
// gets the name und value for hundreds
std::string GetHundred(const std::string &num, const int offs)
{
std::string result;
if(num.size() > (offs + 2)) // the offset is expected at the beginning of the hundred
{
const int value_100 = GetValue(num, offs + 2); // gets the hundred digit
if(value_100 > 0) // if there actually is hundred
result = from_0_to_9[value_100] + from_100[0]; // both appear: the value of hundred and the word hundred itself
}
return result;
}
// Removes characters from the string (all -> whether just a series or all)
int RemoveChar(std::string &str, const char ch, const bool all)
{
int result = 0; // holds the amount of chars removed
std::string::iterator it = str.begin(); // gets the start of the string
while(it != str.end()) // as long as it's not at end
{
if(ch == (*it)) // checks if it's a char to remove
{
it = str.erase(it); // remove the char
++result; // count the chars removed
}
else if(all) // whether all characters should be removed
++it; // just continue
else
break; // the series ends
}
return result;
}
int main()
{
std::cout << "Number to Words" << std::endl << "q - quit" << std::endl;
bool q = false;
while(!q)
{
std::string num;
std::cout << "Enter number:" << std::endl;
std::getline(std::cin, num);
q = ("q" == num);
if(q)
; // do nothing if quit
else
{
RemoveChar(num, ' ', true); // remove all blanks
const int minus = RemoveChar(num, '-', false); // remove and count minus
const int zero = RemoveChar(num, '0', false); // remove leading zero
bool is_nondigit = false;
for(std::string::size_type i = 0; i < num.size(); ++i) // check for correctness of the number
{
is_nondigit = (0 == isdigit(num[i])); // check the digit
if(is_nondigit) // whether it's invalid
break; // stop here
}
if(is_nondigit)
std::cout << "Invalid number: digits only" << std::endl;
else
{
std::reverse(num.begin(), num.end()); // reverse the string for convenience
const int size = num.size(); // get the size
if((size > 0) and (size < (((sizeof(from_100) / sizeof(*from_100)) * 3) + 2))) // check the amount of digits
{
std::string result = GetHundred(num, 0) + GetBelowHundred(num, 0); // get the name of the lowes hundert
const int size_3 = (size + 2) / 3; // this is the number of following hundreds
for(int i = 1; i < size_3; ++i) // calculates every three digits above hundert
{
// gets the three names for the three digits
result = GetHundred(num, i * 3) + GetBelowHundred(num, i * 3) + from_100[i] + result; // must be prepended!
}
if(1 == minus % 2) // whether a minus appeared
std::cout << "minus "; // show minus
std::cout << result << std::endl; // The final output
}
else if(num.empty() && (zero > 0)) // There's only zero
std::cout << from_0_to_9[0] << std::endl;
else // Invalid input
std::cout << "Invalid number: 1 to " << ((sizeof(from_100) / sizeof(*from_100)) * 3) + 2 << " digits" << std::endl;
}
}
}
return 0;
}
|