Any way to trim this down?

As part of an assignment that I have to do in class, I need to write a module that can turn a float number into a text string (ie 123.45 = "ONE HUNDRED AND TWENTY-THREE 45/100").

In the data used for the assignment, the float number will always be below 1000. This is the code that I came up with:

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
#include <cstdio>
#include <cstdlib>
#include <cstring>

void GetDigitText(int digit, char text[])
{
    switch (digit)
    {
        case 1:
            strcpy(text, "ONE");
            break;
        case 2:
            strcpy(text, "TWO");
            break;
        case 3:
            strcpy(text, "THREE");
            break;
        case 4:
            strcpy(text, "FOUR");
            break;
        case 5:
            strcpy(text, "FIVE");
            break;
        case 6:
            strcpy(text, "SIX");
            break;
        case 7:
            strcpy(text, "SEVEN");
            break;
        case 8:
            strcpy(text, "EIGHT");
            break;
        case 9:
            strcpy(text, "NINE");
            break;
        default:
            strcpy(text, "");
    }
}

void GetNumText(float num, char text[])
{
    int dollars, cents;
    char temp[10];

    dollars = (int)num;
    cents = int(num * 100) % 100;

    int hundreds = dollars / 100;
    GetDigitText(hundreds, text);
    if (strlen(text) > 0)
        strcat(text, " HUNDRED");

    if (dollars % 100)
        strcat(text, " AND");

    int tens = (dollars % 100) / 10;
    switch (tens)
    {
        case 9:
            strcat(text, " NINETY");
            break;
        case 8:
            strcat(text, " EIGHTY");
            break;
        case 7:
            strcat(text, " SEVENTY");
            break;
        case 6:
            strcat(text, " SIXTY");
            break;
        case 5:
            strcat(text, " FIFTY");
            break;
        case 4:
            strcat(text, " FORTY");
            break;
        case 3:
            strcat(text, " THIRTY");
            break;
        case 2:
            strcat(text, " TWENTY");
            break;
    }

    int ones;
    if (dollars % 100 < 20)
        ones = dollars % 100;
    else
        ones = dollars % 10;

    if (ones > 0)
    {
        if (tens > 1)
            strcat(text, "-");
        else
            strcat(text, " ");
    }

    GetDigitText(ones, temp);
    if (strlen(temp) > 0)
        strcat(text, temp);
    else
    {
        switch (ones)
        {
            case 10:
                strcat(text, "TEN");
                break;
            case 11:
                strcat(text, "ELEVEN");
                break;
            case 12:
                strcat(text, "TWELVE");
                break;
            case 13:
                strcat(text, "THIRTEEN");
                break;
            case 14:
                strcat(text, "FOURTEEN");
                break;
            case 15:
                strcat(text, "FIFTEEN");
                break;
            case 16:
                strcat(text, "SIXTEEN");
                break;
            case 17:
                strcat(text, "SEVENTEEN");
                break;
            case 18:
                strcat(text, "EIGHTEEN");
                break;
            case 19:
                strcat(text, "NINETEEN");
                break;
        }
    }
    itoa(cents, temp, 10);
    strcat(text, " ");
    strcat(text, temp);
    strcat(text, "/100");
}

int main()
{
    float num;
    char text[100];

    printf("Enter a number: ");
    scanf("%f", &num);

    while(num > 0)
    {
        GetNumText(num, text);
        printf("%s\nEnter a number: ", text);
        scanf("%f", &num);
    }

    return 0;
}


Is there any way to trim this down? I also need to provide documentation for everything I code, so the shorter and simpler this is the less work I would have to do on a flowchart. This is a C language class and we are not allowed to use C++ functions/objects.
Last edited on
Is there any way to trim this down?

Sure. You can move the strcpy / strcat calls outside your switch statements.
Also, you can replace the switch statements themselves with array lookup.
Use look-up tables instead of switch-case constructs, perhaps?
1
2
3
static const char* const digits[] = { "zero", "one", "two", /* etc... */ "eight", "nine" } ;
static const char* const teens[] = { "ten", "eleven", /* etc... */ "eighteen", "nineteen" } ;
static const char* const tens[] = { "ten", "twenty", /* etc... */ "eighty", "ninety" } ;


And then:
1
2
3
4
5
void get_digit_text( int digit, char text[] )
{
    if( ( digit >= 0 ) && ( digit <= 9 ) ) strcpy( text, digits[digit] ) ;
    else text[0] = 0 ;
}

and so forth.
Thanks, I has no idea how to declare arrays of cstrings. That shortened my code a lot:

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
#include <cstdio>
#include <cstdlib>
#include <cstring>

void GetNumText(float num, char text[])
{
    static const char* const digits[] = { "", "ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE" } ;
    static const char* const teens[] = { "TEN", "ELEVEN", "TWELVE", "THIRTEEN", "FOURTEEN", "FIFTEEN", "SIXTEEN", "SEVENTEEN", "EIGHTEEN", "NINETEEN" } ;
    static const char* const tens[] = { "", "", "TWENTY", "THIRTY", "FORTY", "FIFTY", "SIXTY", "SEVENTY", "EIGHTY", "NINETY" } ;
    
    int dollars, cents, i;
    char s[10];

    dollars = (int)num;
    cents = int(num * 100) % 100;

    strcpy(text, digits[dollars / 100]);
    
    if (strlen(text))
    {
        strcat(text, " HUNDRED");
        if (dollars % 100)
            strcat(text, " AND ");
    }

    i = dollars % 100;
    if (i >= 20)
    {
        strcat(text, tens[i / 10]);
        if (dollars % 10)
        {
            strcat(text, "-");
            strcat(text, digits[dollars % 10]);
        }
    }
    else if (i >= 10)
    {
        strcat(text, teens[i - 10]);
    }
    else
    {
        strcat(text, digits[i]);
    }
    
    strcat(text, " ");
    itoa(cents, s, 10);
    strcat(text, s);
    strcat(text, "/100");
}

int main()
{
    float num;
    char text[100];

    printf("Enter a number: ");
    scanf("%f", &num);

    while(num > 0)
    {
        GetNumText(num, text);
        printf("%s\nEnter a number: ", text);
        scanf("%f", &num);
    }

    return 0;
}


I have a different problem now. When I try the example I gave in my first post, 123.45 actually gives me "ONE HUNDRED AND TWENTY-THREE 44/100". I think this probably happened with my original code too, but I didn't notice it.

Is there any way to make it more accurate when trying to convert the first two digits after the decimal into an integer?
Might not be the best way, but try this in main -> GetNumText(num + 0.005f, text);
Last edited on
> 123.45 actually gives me "ONE HUNDRED AND TWENTY-THREE 44/100"

Floating point is an inexact representation of a real number.
http://docs.python.org/2/tutorial/floatingpoint.html

Perhaps you could read the amount as two integers - one representing the dollar part and the other representing the cents part. (int has an exact representation).

1
2
3
4
int dollars, cents ;
char decimal_point ;
std::cin >> dollars >>  decimal_point  >> cents ;
// validate dollars in [0,999], decimal_point is '.' and cents in [0,99] 
Thanks. I was hoping that there was a way, but I guess there's nothing to be done.
Replace this cents = int(num * 100) % 100;
     with this cents = int(num * 100 + 0.5) % 100;
That worked perfectly, thank you!
Topic archived. No new replies allowed.