A possible way of doing it:
First a function which returns the correct word sequence up to 999 is needed. It should also return if there is an 'and' somewhere in there (look below):
Code:
enum _ghr { HasAnd, NoAnd } GetHundreds(char* buffer, const char* num)
{
_ghr retval = NoAnd;
char* pbuffer = buffer;
char* Numbers[] =
{
"one", "two", "three", "four", "five", "six", "seven",
"eight", "nine", "ten", "eleven", "twelve", "thirteen",
"fourteen", "fifteen", "sixteen", "seventeen", "eightteen",
"nineteen", "twenty", "thirty", "fourty", "fifty", "sixty",
"seventy", "eighty", "ninety"
};
if(num[0] != '0')
{
// xyz, x != 0 (ie: 100)
sprintf(pbuffer, "%s hundred ", Numbers[num[0] - '1']);
pbuffer += strlen(pbuffer);
}
if(num[1] != '0' || num[2] != '0')
{
if(num[0] != '0')
{
strcpy(pbuffer, "and ");
pbuffer += strlen(pbuffer);
retval = HasAnd;
}
if(num[1] == '0')
// x0z, z != 0 (ie: 101)
sprintf(pbuffer, "%s ", Numbers[num[2] - '1']);
else if(num[1] == '1')
// x1z (ie: 111)
sprintf(pbuffer, "%s ", Numbers[num[2] - '1' + 10]);
else if(num[2] != '0')
// xyz, y != 0, y != 1, z != 0 (ie: 121)
sprintf(pbuffer, "%s-%s ", Numbers[num[1] - '2' + 19], Numbers[num[2] - '1']);
else
// xy0, y != 0, y != 1 (ie: 120)
sprintf(pbuffer, "%s ", Numbers[num[1] - '2' + 19]);
}
return retval;
}
Now that we have this, all that is left is to add the appropriate 'milliard', 'million' or 'thousand' where it should be. Of course we should also check for the 'and', since we don't want things like 'one thousand one', but 'one thousand and one'. Also, we'll need a little routine to insert strings for us. Better can be written but this one is small and easy to read:
Code:
char* strins(char* buffer, const char* str)
{
char* temp = new char[strlen(buffer) + 1];
strcpy(temp, buffer);
strcpy(buffer, str);
strcat(buffer, temp);
delete [] temp;
return buffer;
}
// Writes the word equivalent of Number in buffer.
// Returns buffer.
char* UIntToWords(char* buffer, unsigned int Number)
{
char num[13];
char* pbuffer = buffer;
if(Number == 0u)
return strcpy(buffer, "zero");
sprintf(num, "%012u", Number);
bool milliards = (num[0] != '0' || num[ 1] != '0' || num[ 2] != '0');
bool millions = (num[3] != '0' || num[ 4] != '0' || num[ 5] != '0');
bool thousands = (num[6] != '0' || num[ 7] != '0' || num[ 8] != '0');
bool hundreds = (num[9] != '0' || num[10] != '0' || num[11] != '0');
if(milliards)
{
GetHundreds(pbuffer, &num[0]);
strcat(pbuffer, "milliard ");
pbuffer += strlen(pbuffer);
}
if(millions)
{
if(NoAnd == GetHundreds(pbuffer, &num[3]) &&
milliards && !thousands && !hundreds)
strins(pbuffer, "and ");
strcat(pbuffer, "million ");
pbuffer += strlen(pbuffer);
}
if(thousands)
{
if(NoAnd == GetHundreds(pbuffer, &num[6]) &&
(milliards || millions) && !hundreds)
strins(pbuffer, "and ");
strcat(pbuffer, "thousand ");
pbuffer += strlen(pbuffer);
}
if(hundreds)
if(NoAnd == GetHundreds(pbuffer, &num[9]) &&
(milliards || millions || thousands))
strins(pbuffer, "and ");
return buffer;
}
Finally, a routine which gets singed ints:
Code:
char* IntToWords(char* buffer, int Number)
{
char* pbuffer = buffer;
if(Number < 0)
{
strcpy(pbuffer, "minus ");
pbuffer += strlen(pbuffer);
Number = -Number;
}
UIntToWords(pbuffer, (unsigned int)Number);
return buffer;
}
Now to test it:
Code:
#include <cstring>
#include <cstdio>
// Insert other functions here
int main()
{
char buffer[500];
printf("%d - %s\n", -1234567, IntToWords(buffer, -1234567));
return 0;
}
Output is:
-1234567 - minus one million two hundred and thirty-four thousand five hundred and sixty-seven
Most probably not the best solution but a working one.