Не возвращающая строка. Эта программа преобразует цифру вроде 123 в слова типа One Two Three, почему в итоге я ничего не получаю?

#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));
    }
}

Функция int_to_string () должна возвращать строку, содержащую эквивалент переданного числа в словах. он отлично работает для однозначного числа (например, 0-9), но выше он просто ничего не дает.


person Gaurish Gangwar    schedule 14.06.2016    source источник
comment
К вашему сведению, ваша программа вызывает неопределенное поведение. str[] больше не существует после возвращения int_to_string. Прочтите это. Серьезно.   -  person WhozCraig    schedule 14.06.2016
comment
или, как вы знаете, базовый случай рекурсии (n ‹10) ничего не возвращает, поэтому, если он когда-нибудь дойдет до конца, он ничего не вернет.   -  person Marshall Tigerus    schedule 14.06.2016
comment
Возможный дубликат Введите строку с заглавной буквы и верните локальную переменную   -  person n. 1.8e9-where's-my-share m.    schedule 14.06.2016
comment
Даже если исправлена ​​проблема с локальной переменной, ваша рекурсия логически подозрительна и не будет работать должным образом.   -  person user3078414    schedule 14.06.2016


Ответы (3)


Функция имеет неопределенное поведение.

Он возвращает указатель на локальный массив str, который обычно уничтожается после выхода из функции.

Учтите, что лучше определить параметр как имеющий тип unsigned int. В противном случае функции необходимо проверить, не является ли число отрицательным.

Вы можете упростить задачу, объявив второй параметр, который будет указывать символьный массив с завершающим нулем, в котором будет храниться строка результата.

Или вам нужно динамически распределять память.

Здесь показаны эти два подхода.

#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 ) );
}

Вывод программы:

One Two Three Four Five Six Seven Eight Nine Zero
One Two Three Four Five Six Seven Eight Nine Zero
person Vlad from Moscow    schedule 14.06.2016
comment
он возвращает строку, эквивалентную числу для n ‹10. например для int_to_string (5) возвращает Пять @marshall - person Gaurish Gangwar; 14.06.2016
comment
Влад для n < 10, пожалуйста, см. Это - person Weather Vane; 14.06.2016

Пожалуйста, используйте копию строки перед отправкой последней строки. Добавьте последние две строки в свой код, и все будет работать.

    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
     }
person Arvind Yadav    schedule 14.06.2016
comment
str1 по-прежнему является автоматической / локальной переменной, которая будет извлечена из стека при возврате int_to_string. - person yano; 14.06.2016

1)

В вашей функции str как автоматическая переменная в стеке была уничтожена после возврата int_to_string. Но вам нужно str быть живым, чтобы звонить еще int_to_string! Значит, между звонками нужно сохранять str.

2)

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

Приведенный выше код не будет работать должным образом в вызовах рекурсии, слово "Zero" необходимо добавить в строку str.

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

Но зачем мучиться с рекурсивными вызовами? Рекурсию можно заменить простым циклом. Показаны оба решения.

#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;
}

Выход для 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 
person sg7    schedule 14.06.2016
comment
@ user3078414 Спасибо! Я знаю это. Дело было в том, чтобы сохранить str. Логику функции отлаживать не стал. Лично я бы использовал простой цикл, как представлено. - person sg7; 14.06.2016
comment
Я бы вообще не стал использовать рекурсию, но дело не в этом - никого не волнует, знаете ли вы об этом или нужно ли отлаживать исходный код для логики. Если вы можете дать простой, ясный и универсально полезный ответ, сохранив как можно больше смысла от исходного кода, то сделайте это. Иначе подумайте дважды, прежде чем публиковать ответы, ИМХО. - person user3078414; 14.06.2016
comment
@ user3078414 Извините, я не могу отладить логику этой программы. Я указал на проблему с автоматической переменной. Я представил альтернативное решение. Это все, что умею делать банкоматы. Я ценю вашу точку зрения. Спасибо за ваш вклад. - person sg7; 14.06.2016
comment
@ user3078414 FYI Я также представил решение с рабочей рекурсией. - person sg7; 15.06.2016