Преобразовать арабское число (long long int) в слова в C - PullRequest
0 голосов
/ 05 июня 2019

Я хотел бы преобразовать число, скажем, 1024 или 2345787654 в английские слова, так что для 1024 должно быть напечатано тысяча двадцать четыре и т. Д.

Однако мой код дает мне ошибку сегментации. Я попытался запустить его с gdb, но он предполагает, что проблема в функции my_strcat. Однако я не вижу никаких проблем с этой функцией. Пожалуйста, помогите.

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

const char *digits[] = { NULL, "one ", "two ", "three ", "four ", "five ", "six ", "seven ", "eight ", "nine " };
const char *tens[] = { NULL, "ten ", "twenty ", "thirty ", "forty ", "fifty ", "sixty ", "seventy ", "eighty ", "ninety " };
const char *teens[] = { "ten ", "eleven ", "twelve ", "thirteen ", "fourteen ", "fifteen ", "sixteen ", "seventeen ", "eighteen ", "nineteen " };
const char *scales[] = { "", "thousand ", "million ", "billion " };

char *my_strcat ( char **dest, const char * src)
{
    char *tab = malloc ( sizeof ( char) * (strlen ( *dest) + strlen ( src) + 1));
    if ( NULL == tab)
        return NULL;
    strcpy ( tab, *dest);
    strcat ( tab, src);
    free ( *dest);
    *dest = malloc ( sizeof ( char) * ( strlen ( tab) + 1));
    strcpy ( *dest, tab);
    return tab;
}

char * LongToEnglish(unsigned long x)
{
    switch(x)
    {
    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";
    case 10:
        return "Ten";
    case 11:
        return "Eleven";
    case 12:
        return "Twelve";
    case 13:
        return "Thirteen";
    case 14:
        return "Fourteen";
    case 15:
        return "Fifteen";
    case 16:
        return "Sixteen";
    case 17:
        return "Seventeen";
    case 18:
        return "Eighteen";
    case 19:
        return "Nineteen";
    case 20:
        return "Twenty";
    case 30:
        return "Thirty";
    case 40:
        return "Forty";
    case 50:
        return "Fifty";
    case 60:
        return "Sixty";
    case 70:
        return "Seventy";
    case 80:
        return "Eighty";
    case 90:
        return "Ninety";
    case 100:
        return "One Hundred";
    case 1000:
        return "One Thousand";
    case 1000000:
        return "One Million";
    case 1000000000:
        return "One Billion";
    }
    // less than 100
    for (long i = 1; i <= 9; i ++)
    {
        long j = i * 10;
        if ((x >= j) && (x < j + 10))
        {
            long r = x - j;

            if(r > 0)
                return my_strcat(my_strcat(*LongToEnglish(j), " "), LongToEnglish(r));
            else
                return my_strcat(*LongToEnglish(j), "");
        }
    }
    // less than 1000
    for (long i = 1; i <= 9; i ++)
    {
        long j = i * 100;
        if ((x >= j) && (x < j + 100))
        {
            long r = x - j;

            if(r > 0)
                return my_strcat(my_strcat(LongToEnglish(i), " Hundred "), LongToEnglish(r));
            else
                return my_strcat(LongToEnglish(i), " Hundred");
        }
    }
    // less than 10000
    for (long i = 1; i <= 9; i ++)
    {
        long j = i * 1000;
        if ((x >= j) && (x < j + 1000))
        {
            long r = x - j;
            if(r > 0)
                return my_strcat(my_strcat(LongToEnglish(i), " Thousand "), LongToEnglish(r));
            else
                return my_strcat(LongToEnglish(i), " Thousand");
        }
    }
    // Million
    for (long i = 1; i <= 9; i ++)
    {
        long j = i * 1000000;
        if ((x >= j) && (x < j + 1000000))
        {
            long r = x - j;
            if(r > 0)
                return my_strcat(my_strcat(LongToEnglish(i), " Million "), LongToEnglish(r));
            else
                return my_strcat(LongToEnglish(i), " Million");
        }
    }
    // Billion
    for (long i = 1; i <= 4; i ++)
    {
        long j = i * 1000000000;
        if ((x >= j) && (x < j + 1000000000))
        {
            long r = x - j;
            if(r > 0)
                return my_strcat(my_strcat(LongToEnglish(i), " Billion "), LongToEnglish(r));
            else
                return my_strcat(LongToEnglish(i), " Billion");
        }
    }
    // Divide the number into 3-digit groups from left to right
    char* output = "";
    long cnt = 0;
    while (x > 0)
    {
        long y = x % 1000;
        x /= 1000;
        if (y > 0)   // skip middle-chunk zero
        {
            char * t = "";
            if (cnt == 1) t = " Thousand ";
            if (cnt == 2) t = " Million ";
            if (cnt == 3) t = " Billion ";
            output = my_strcat(my_strcat(LongToEnglish(y), t), output);
        }
        cnt ++;
    }

    return (output);
}

char* numberToWords(int num)
{
    return LongToEnglish(num);
}

int main(int argc, char **argv)
{
    char *dst = NULL;
    dst = malloc ( sizeof ( char) * 10000000);

    unsigned long long n = 122334;
    dst = numberToWords(n);

    printf("%s", dst);
    free(dst);

    return 0;
}

Ответы [ 2 ]

1 голос
/ 05 июня 2019

В вашем коде есть другие проблемы, я говорю только одну. Когда ввод n=3 в main, numberToWords возвращает "Three", и вы пытаетесь вызвать free("Three") и т. Д.

Иногда вы возвращаете статическую строку и пытаетесь освободить ее для этого конкретного случая.

0 голосов
/ 05 июня 2019

Задача для групп из тысяч человек всегда одинакова.Таким образом, вы можете сделать это гораздо менее сложным.Обработка строк может быть оптимизирована ...

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

const char *digits[] = { NULL, "one ", "two ", "three ", "four ", "five ", "six ", "seven ", "eight ", "nine ", "ten ", "eleven ", "twelve ", "thirteen ", "fourteen ", "fifteen ", "sixteen ", "seventeen ", "eighteen ", "nineteen " };
const char *tens[] = { NULL, "ten ", "twenty ", "thirty ", "forty ", "fifty ", "sixty ", "seventy ", "eighty ", "ninety " };
const char *scales[] = { "", "thousand ", "million ", "billion " };

char *long2words(long x, int grp) {
    char *buf = malloc(4096), *bp;    
    int e,t,h;

    *buf='\0';
    e = x%10;
    t = (x/10)%10;
    h = (x/100)%10;
    x /=1000;
    if(x!=0) {
        strcat(buf, bp=long2words(x,grp+1));
        free(bp);
    }
    if(h!=0) {
        strcat(buf, digits[h]);
        strcat(buf,"hundred ");
    }
    if(t<2) strcat(buf, digits[t*10+e]);
    else {
        strcat(buf, tens[t]);
        strcat(buf, digits[e]);
    }
    strcat(buf, scales[grp]);

    return buf;
}
int main()
{
    printf(long2words(102410241024,0));

    return 0;
}
...