-4
#include<stdio.h>
#include<string.h>

char *int_to_string( int n );

void main()
{
    int n;

    printf("Enter the number : ");
    scanf("%d",&n);

    printf("\n%d in words is : %s.\n",n,int_to_string(n));
}

char *int_to_string( int n)
{
    char str[100]="";

    if(n<10)
    {
          switch(n)
        {
            case 0: return "Zero";
            case 1: return "One";
            case 2: return "Two";
            case 3: return "Three";
            case 4: return "Four";
            case 5: return "Five";
            case 6: return "Six";
            case 7: return "Seven";
            case 8: return "Eight";
            case 9: return "Nine";
        }
    }

    else
    {
        strcat(str,int_to_string(n/10));
        strcat(str," ");

        return strcat(str,int_to_string(n%10));
    }
}

Function int_to_string() should return a string containing equivalent of the number in words that is passed. it works fine for single digit number ( i.e. 0-9 ) but above that it just gives nothing.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Gaurish Gangwar
  • 395
  • 4
  • 14
  • Fyi, your program invokes *undefined behavior*. `str[]` no longer exists once `int_to_string` returns. [Read this. Seriously](http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope/6445794#6445794). – WhozCraig Jun 14 '16 at 16:15
  • or, you know, the base case of the recursion (n < 10) doesn't return anything, so if it ever got to the "bottom" it wouldn't return anything. – Marshall Tigerus Jun 14 '16 at 16:16
  • Possible duplicate of [Capitalize string and return local variable](http://stackoverflow.com/questions/20292800/capitalize-string-and-return-local-variable) – n. m. could be an AI Jun 14 '16 at 16:26
  • Even if fixing the local variable issue, your recursion is logically suspect, and wouldn't work as expected. – user3078414 Jun 14 '16 at 19:57

3 Answers3

3

The function has undefined behaviour.

It returns a pointer to local array str that is in general destroyed after exiting the function.

Take into account that it is better to define the parameter as having type unsigned int. Otherwise the function needs to check whether the number is not negative.

You could make the task easier by means of declaring second parameter that will specify a character zero-terminated array that will store the result string.

Or you have to allocate memory dynamically.

Here are shown these two approaches.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

char * int_to_string( unsigned int n )
{
    if( n < 10 )
    {
        char *p = "";

        switch( n )
        {
        case 0: 
            p = "Zero";
            break;
        case 1: 
            p = "One";
            break;
        case 2: 
            p = "Two";
            break;
        case 3: 
            p = "Three";
            break;
        case 4: 
            p = "Four";
            break;
        case 5: 
            p = "Five";
            break;
        case 6: 
            p = "Six";
            break;
        case 7: 
            p = "Seven";
            break;
        case 8: 
            p = "Eight";
            break;
        case 9: 
            p = "Nine";
            break;
        }
        char *q = malloc( strlen( p ) + 1 );
        strcpy( q, p );
        free( p );
        return q; 
    }
    else
    {
        char *q = int_to_string( n / 10 );
        char *p = int_to_string( n % 10 );

        q = realloc( q, strlen( q ) + strlen( p ) + 2 );
        strcat( q, " " );
        return strcat( q, p );
    }
}

char * int_to_string1( unsigned int n, char *s )
{
    if( n < 10 )
    {
        char *p = "";

        switch( n )
        {
        case 0: 
            p = "Zero";
            break;
        case 1: 
            p = "One";
            break;
        case 2: 
            p = "Two";
            break;
        case 3: 
            p = "Three";
            break;
        case 4: 
            p = "Four";
            break;
        case 5: 
            p = "Five";
            break;
        case 6: 
            p = "Six";
            break;
        case 7: 
            p = "Seven";
            break;
        case 8: 
            p = "Eight";
            break;
        case 9: 
            p = "Nine";
            break;
        }

        return strcat( s, p );
    }
    else
    {
        strcat( int_to_string1( n / 10, s ), " " );

        return int_to_string1( n % 10, s );
    }
}

int main( void )
{
    unsigned int n = 1234567890;
    char *s = int_to_string( n );

    puts( s );

    free( s );

    char s1[100];
    s1[0] = '\0';

    puts( int_to_string1( n, s1 ) );
}

The program output is

One Two Three Four Five Six Seven Eight Nine Zero
One Two Three Four Five Six Seven Eight Nine Zero
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
2

Please use string copy before sending a final string. Add last two line in your code it'll work.

    char *int_to_string( int n)
    {
       char str[100]="";
       char str1[100]="";//
       .
       .
       .
       strcat(str,int_to_string(n/10));
       strcat(str," ");     
       strcat(str,int_to_string(n%10));
       strcpy(str1,str);//create one more str1 array of 100 and copy final data
       return str1;// return str1 array of data
     }
Arvind Yadav
  • 441
  • 2
  • 4
  • 1
    `str1` is still an automatic/local variable which will be popped off the stack when `int_to_string` returns. – yano Jun 14 '16 at 17:59
1

1)

In your function str as an automatic variable on the stack was destroyed after the int_to_string returned. But you need str to be alive for more int_to_string calls! So you have to preserve str between calls.

2)

case 0: return "Zero";
....

The code above will not work properly in recursion calls, the word "Zero" has to be added to str string

     case 0: strcat(str,"Zero"); return str;

But why suffer with recursion calls? Recursion can be replaced with a simple loop. Both solutions are shown.

#include <stdio.h>
#include <stdlib.h> 
#include <ctype.h>
#include <string.h>
#include <math.h>

void print_digit(int digit)
{
    switch(digit)
    {
        case '0': printf("Zero "); break;
        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;
   }
}

char * return_digit_word(int digit)
{
    switch(digit)
    {
        case '0': return("Zero "); break;
        case '1': return("One ");  break;
        case '2': return("Two ");  break;
        case '3': return("Three ");break;
        case '4': return("Four "); break;
        case '5': return("Five "); break;
        case '6': return("Six ");  break;
        case '7': return("Seven ");break;
        case '8': return("Eight ");break;
        case '9': return("Nine "); break;
   }
}

char *int_to_string(int n,char str[],char numStr[]) 
{
     if(n<10)
     {
        switch(n)
        {
            case 0: strcat(str,"Zero");break;
            case 1: strcat(str,"One");break;
            case 2: strcat(str,"Two");break;
            case 3: strcat(str,"Three");break;
            case 4: strcat(str,"Four");break;
            case 5: strcat(str,"Five");break;
            case 6: strcat(str,"Six");break;
            case 7: strcat(str,"Seven");break;
            case 8: strcat(str,"Eight");break;
            case 9: strcat(str,"Nine");break;
        }
        return str;
    }
    else{
        int digit = numStr[0]-'0';
        int newNr =  n - digit*pow(10,strlen(numStr)-1);        

        strcat(str, return_digit_word(numStr[0]));
        sprintf(numStr, "%d", newNr); 

        return int_to_string(newNr,str,numStr);
    }
} 


int main(void) {
    int n,i;
    char str[100]="";
    char numStr[100]="";

    n = 1234567890;

    sprintf(numStr, "%d", n);
    printf("\n%d in words is : %s\n",n, int_to_string(n,str,numStr) );

    printf("\n%d in words is : ",n);
    sprintf(numStr, "%d", n);
    for(i=0;i<strlen(numStr);i++)
    {
       print_digit(numStr[i]);
    }

   return 0;
}

Output for n=1234567890:

1234567890 in words is : One Two Three Four Five Six Seven Eight Nine Zero

1234567890 in words is : One Two Three Four Five Six Seven Eight Nine Zero 
sg7
  • 6,108
  • 2
  • 32
  • 40
  • @user3078414 Thanks! I know it. The point was to preserve `str`. I did not debug the logic of the function. Personally, I would use a simple loop as presented. – sg7 Jun 14 '16 at 18:53
  • I wouldn't use recursion at all, but that's not the point - nobody cares if "you know it", or if original code has to be "debugged for logic". If you can give a simple, clear and universally useful answer retaining as much of original code as meaningful, than do it. Else, think twice before posting answers, IMHO. – user3078414 Jun 14 '16 at 19:01
  • @user3078414 Sorry, I cannot debug the logic of this program. I pointed out the problem with automatic variable. I presented the alternative solution. That is all what I can do ATM. I appreciate your point of view. Thank you for your input. – sg7 Jun 14 '16 at 19:06
  • @user3078414 FYI I have also presented solution with working recursion. – sg7 Jun 15 '16 at 02:33