Thread: Converting Numbers to Words

  1. #1
    Registered User denizengt's Avatar
    Join Date
    Sep 2003
    Posts
    19

    Question Converting Numbers to Words

    Hello everyone.

    I'm new to programming in general, and I'm wondering if you can help me.

    Does anyone have a solution to a problem where you are given a number, lets say, 1645030, and have to produce the output: one million six hundred forty five thousand thirty?

    I have a partially working solution that works for numbers 1000 and less but it's very clunky and doesn't work when I extend it (massive confusing mass of if's). Does anyone have a neater, working way of doing it? Much appreciated!

    I'm just learning c as a hobby, and this has stopped me in my tracks!
    Last edited by denizengt; 09-02-2003 at 11:54 PM.

  2. #2
    Registered User
    Join Date
    Mar 2003
    Posts
    143
    denizengt,

    I suggest that you post what you have written so far, then we can help you restructure it so that it is (hopefully) less clunky. We will also be able to give you some pointers on extending the structure to cope with larger numbers. This is a much better way for you to learn than just looking at an answer you are given...
    DavT
    -----------------------------------------------

  3. #3
    Registered User denizengt's Avatar
    Join Date
    Sep 2003
    Posts
    19
    Ok DavT, thank you for replying. Apologies to everyone on the size!
    Code:
    #include <stdio.h>
    #include <strings.h>
    
       void hasTrillions(char);
       void hasBillions(char);
       void hasMillions(char);
       void hasThousands(char);
       void hasHundreds(char);  
       void simpleNumber(char);
       void hasTeen(char);
       void hasTens(char); 
    
       main() {
       
       /*Define string, and array of chars..*/
       
          char string[256]; /*max length 255*/
      
          int cPos;
          int iterator;
          
          printf("Enter an integer, and hit enter  :  ");
          gets(string);
          int len = strlen(string);
          cPos = len;
       
          for(iterator = 0; iterator != len; iterator++) {
          
             if (cPos == 1){
    
                    if(string[0] == '0') {
                      printf("zero ");
                      }
    
                    simpleNumber(string[len-1]);
                    cPos=0;
             }
    
    
          
             if(cPos == 2) {
             
                if (string[len-cPos] == '1'){
                   hasTeen(string[len-cPos+1]);
                   cPos=0;
                   break;}
                
                else if(string[len-cPos]!='1'){
                   hasTens(string[len-cPos]);
                   cPos--;
                }
             
             }
    
             if(cPos == 3) {
               hasHundreds(string[len-cPos]);
               cPos--;
    
    
               }
    
             if (cPos == 4) {
               hasThousands(string[len-cPos]);
               cPos--;
               }
    
             if (cPos == 5) {
    
    
                if (string[len-cPos] == '1'){
                   hasTeen(string[len-cPos+1]);
                   cPos = cPos-2;
                   printf("Thousand ");
    
                }
                
                if(string[len-cPos]!='1' ){
                   hasTens(string[len-cPos]);
    
                    if(string[len-cPos] == '0'){
                     printf("Thousand ");
                     }
    
                   cPos--;
    
                }
               }
    
             if (cPos == 6) {
               if(string[len-cPos] != '0'){
                hasHundreds(string[len-cPos]);
                }
    
                cPos--;
    
               }
    
             if (cPos > 6) {
    
               switch(len){
                 case 7: hasMillions(string[0]);cPos--; break;
                 case 8: if(string[0] == '1'){
                         hasTeen(string[1]);
                         printf("Million ");
                         cPos=cPos-2;
                         break;
                         }
    
                         if(string[0] != '1'){
                         hasTens(string[0]);
    
                         cPos--;
                         break;
                         }
    
                         break;
                 case 9:  break;
    
                }
    
              }
    
          }
       
       }
    
    
    
       void hasTens(char x){ 
          switch(x){ 
             case '1':printf("Ten ");
                break; 
             case '2':printf("Twenty ");
                break; 
             case '3':printf("Thirty ");
                break; 
             case '4':printf("Fourty ");
                break; 
             case '5':printf("Fifty ");
                break; 
             case '6':printf("Sixty ");
                break; 
             case '7':printf("Seventy ");
                break; 
             case '8':printf("Eighty ");
                break; 
             case '9':printf("Ninety ");
                break; 
          } 
       } 
    
    
       void hasTeen(char x){ 
          switch(x){
             case '0':printf("Ten");
                break;
             case '1':printf("Eleven ");
                break; 
             case '2':printf("Twelve ");
                break; 
             case '3':printf("Thirteen ");
                break; 
             case '4':printf("Fourteen ");
                break; 
             case '5':printf("Fifteen ");
                break; 
             case '6':printf("Sixteen ");
                break; 
             case '7':printf("Seventeen ");
                break; 
             case '8':printf("Eighteen ");
                break; 
             case '9':printf("Nineteen ");
                break; 
          } 
       } 
    
    
       void simpleNumber(char n){
          switch(n){
            /* case '0':printf("Zero ");*/
    
             case '1':printf("One "); 
                break; 
             case '2':printf("Two "); 
                break; 
             case '3':printf("Three "); 
                break; 
             case '4':printf("Four "); 
                break; 
             case '5':printf("Five "); 
                break; 
             case '6':printf("Six "); 
                break; 
             case '7':printf("Seven "); 
                break; 
             case '8':printf("Eight "); 
                break; 
             case '9':printf("Nine "); 
                break; 
          } 
       } 
    
       void hasHundreds(char x){
          if(x !='0'){
             simpleNumber(x);
             printf("Hundred ");
          }
       }
    
       void hasThousands(char x){
          if(x !='0'){
             simpleNumber(x);
             printf("Thousand ");
          }
       }
    
       void hasMillions(char x){
          if(x !='0'){
             simpleNumber(x);
             printf("Million ");
          }
       }
    
    
       void hasBillions(char x){
          if(x !='0'){
             simpleNumber(x);
             printf("Billion ");
          }
       }
    
       void hasTrillions(char x){
          if(x !='0'){
             simpleNumber(x);
             printf("Trillion ");
          }
       }
    As you can see, it's pretty terrible! Someone said that I might improve it by using pointers. I'm not familiar with pointers (my first language was Java, and I'm not exactly excellent with that). Why should I use pointers? (sorry if this is really obvious to you!)

    If you compile and build it..yeah, extension is a little bit of a problem.

    Any pointers (not c pointers) ?
    Last edited by denizengt; 09-03-2003 at 05:12 AM.

  4. #4
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  5. #5
    Registered User denizengt's Avatar
    Join Date
    Sep 2003
    Posts
    19
    I must admit, I found those two links incredibly confusing.

  6. #6
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I must admit, I found those two links incredibly confusing.
    Any reasonable solution to this problem is likely to be confusing. Especially if you're relatively new to the language. What parts are you having trouble with? Perhaps we can help.
    My best code is written with the delete key.

  7. #7
    Registered User denizengt's Avatar
    Join Date
    Sep 2003
    Posts
    19
    Pointers! I can recognize pointers, but I'm not sure why one would use them over say, using variables for the purpose (especially in the context of arrays).

    What are the benefits of using pointers in my case?

  8. #8
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >What are the benefits of using pointers in my case?
    Pointers simplify string operations. I find it easier to search, move around a string, and make signifigant changes when I'm using a pointer as the iterator. Integer indices just make complicated operations more opaque. Most of the string functions in the standard library also return pointers.
    My best code is written with the delete key.

  9. #9
    Registered User denizengt's Avatar
    Join Date
    Sep 2003
    Posts
    19
    Ok, there's a question I've got to ask.

    I don't think that the way I am trying to do it, ie, with functions, is perhaps the best method to do it. What I want to do, is convert numbers into words, and words into numbers, so it's to be a two way thing.

    I read a little information on the web on "lookup" tables. That is, essentially arrays of strings. An earlier post on this website suggested to use them, however I'm not sure how I could "split" a number, say 76328, then use a lookup table to "tack" on a number descriptor, say "thousand" or "hundred" at the proper interval.

    I apologise if I am not making much sense.

  10. #10
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I'm not sure how I could "split" a number
    It's probably going to be easier to convert the number into a string using sprintf and then walk the string and print out the word value. Let's say you have 76328. You start on the left so that everything prints out nicely. 7 is the ten thousands place, so you print out "seventy" since 7 is equivalent to the tens place. Then you move forward to the thousands place and print "six", then "thousand". Move forward to the hundreds place and print the value of the digit, "three", then the value of the place, "hundred". Move forward to the tens place and print "twenty", then forward again to the ones place and print "eight". The result is "seventy six thousand three hundred twenty eight". Which is preciesly what you want. You'll notice a pattern here, the numbers pair into twos:

    <tens> <ones>

    Then you simply tack on further qualifiers after you handle the base cases: hundred, thousand, million, billion, etc... To convert to a number you perform the same process, this time using strcmp instead of testing a single character. For the actual implementation you could have a couple of tables such as one for the base cases and one for further qualifiers:
    Code:
    struct digit {
      const char *word[9];
      int number[10];
    };
    
    struct digit base[] = {
      /* Ones */
      {
        {"one", "two", "three", ..., "nine"},
        {1,2,3, ... , 9},
      },
      /* Tens */
      {
        {"ten", "twenty", thirty", ...., "ninety"},
        {10, 20, 30, ..., 90},
      },
    };
    Then you only have to handle the special case of the teens and use a counter to find the big stuff. Start at 0, increment to 1 and you're at the hundreds, increment to 2 and you're at the thousands. Lather, rinse, repeat.
    My best code is written with the delete key.

  11. #11
    Registered User zahid's Avatar
    Join Date
    Aug 2001
    Posts
    531
    denizengt,
    I don't know what you are thinking, But I would say the code in your second post is the simplest.
    Which part is giving you the problem?



    Code:
    ........................
    .........................
    
    //Pattern for every 3 digit 
             if (cPos == 4) {
               hasThousands(string[len-cPos]);
               cPos--;
               }
    
             if (cPos == 5) {
    
    
                if (string[len-cPos] == '1'){
                   hasTeen(string[len-cPos+1]);
                   cPos = cPos-2;
                   printf("Thousand ");
    
                }
                
                if(string[len-cPos]!='1' ){
                   hasTens(string[len-cPos]);
    
                    if(string[len-cPos] == '0'){
                     printf("Thousand ");
                     }
    
                   cPos--;
    
                }
               }
    
             if (cPos == 6) {
               if(string[len-cPos] != '0'){
                hasHundreds(string[len-cPos]);
                }
    
                cPos--;
    
               }
    
    ...............................
    .............................
    I guess you can make this code work.
    Last edited by zahid; 09-07-2003 at 07:07 AM.
    [ Never code before desk work ]
    -------------------------------------:-->
    A man who fears Nothing is the man who Loves Nothing
    If you Love Nothing, what joy is there in your life.
    =------------------------------------------------------= - I may be wrong.

  12. #12
    Registered User denizengt's Avatar
    Join Date
    Sep 2003
    Posts
    19
    Code:
    struct digit {
      const char *word[9];
      int number[10];
    };
    
    struct digit base[] = {
      /* Ones */
      {
        {"one", "two", "three", ..., "nine"},
        {1,2,3, ... , 9},
      },
      /* Tens */
      {
        {"ten", "twenty", thirty", ...., "ninety"},
        {10, 20, 30, ..., 90},
      },
    }
    Prelude, could you explain this code to me? This may sound stupid, but why is *word, a pointer?


    Given a string is entered, how can I decide if it is literal, (and hence print out numerical equivalent from the struct), or if it is numerical(and hence print out literal from the struct?)

  13. #13
    End Of Line Hammer's Avatar
    Join Date
    Apr 2002
    Posts
    6,231
    >>could you explain this code to me? This may sound stupid, but why is *word, a pointer?
    word is an array of pointers, here is another example to help explain:
    Code:
    const char *List[] = {"one", "two", "three" }
    The array is 3 elements in length, each element is sizeof(char*) in size. Each element is a pointer, pointing to a string literal, which is stored somewhere else in memory. The other was to code this is:
    Code:
    const char List[][6] = {"one", "two", "three" }
    ... but this way wastes memory, as the array now has 3 lots of 6*sizeof(char) in it. It is also more difficult to manage, because you are having to specify the maximum lenth of ny given element (6 in this case).


    >>Given a string is entered, how can I decide if it is literal, (and hence print out numerical equivalent from the struct), or if it is numerical(and hence print out literal from the struct?) <<
    If you can't convert it from a numeric, you'll have to assume its a literal and keep a tight control on the error checking.
    When all else fails, read the instructions.
    If you're posting code, use code tags: [code] /* insert code here */ [/code]

  14. #14
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >Given a string is entered, how can I decide if it is literal or if it is numerical
    I gave some hackey code for this in another thread. It looked like so:
    Code:
    char *endp;
    int num;
    
    num = (int)strtol(buff, &endp, 0);
    if (buff == endp)
      /* Not a number */
    else
      /* Is a number */
    This chaffes a bit with me because if I have to perform such a test the program definition is grievously broken IMO.
    My best code is written with the delete key.

  15. #15
    Registered User denizengt's Avatar
    Join Date
    Sep 2003
    Posts
    19
    I'm still unsure on how to tackle this problem

    I've defined my struct similar to how Prelude did before.

    Now, let's assume I am in "word to number mode". I get a string using gets(string)

    I start from the left, and iterate through the each element in the string till it's end.

    The parts I am still largely unsure about is writing the number out (after I convert the number contained in the string to the int).

    How DO I determine when to tack on the qualifier? Say I enter 122,555 into the input string. I want this to say "one hundred twenty two thousand five hundred fifty five", I'm not sure how to use that struct object there, and when to tack on the qualifier..

    I also want to reuse the code you see, so when I pass the literal version back, it will produce the numerical equivalent.


    Sorry, I'm just really confused.. I expected this to be simpler..
    Last edited by denizengt; 09-09-2003 at 06:40 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 5
    Last Post: 12-21-2007, 01:38 PM
  2. Converting words into ASCII values
    By manutdfan in forum C Programming
    Replies: 3
    Last Post: 01-22-2007, 12:22 PM
  3. converting numbers into words
    By Kozam in forum C Programming
    Replies: 2
    Last Post: 09-30-2003, 07:49 AM
  4. C++ program help(converting numbers to english words)
    By bama1 in forum C++ Programming
    Replies: 4
    Last Post: 10-08-2002, 01:17 AM
  5. A (complex) question on numbers
    By Unregistered in forum C++ Programming
    Replies: 8
    Last Post: 02-03-2002, 06:38 PM