1. 程式人生 > >程式碼練習——數字轉中文

程式碼練習——數字轉中文

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

char* pcFig[20] = {"零","一","二","三","四","五","六","七","八","九","十","百","千","萬","億"};
int one = 1;
char tens[50];
char hundreds[50];
char thousands[50];
char wan[50];
char yi[50];

char * OneToStr(int input)
{
	if((input > 0) && (input <10))
	{
		return pcFig[input];
	}
	
    return "";
}

char * TensToStr(int input, int zero)
{
    tens[0]='\0';
    int num = input / 10;
    int left = input % 10;


    if( num == 0 )
    {
        if(zero)
        {
            strcat(tens, "零");
        }
        strcat(tens, OneToStr(left));

    }
    else
    {
        if(num == 1)
        {
            if(one)
            {
                strcat(tens, "一");
                strcat(tens, "十");
            }
            else
            {
                strcat(tens, "十");
                one = 1;
            }
        }
        else
        {
            strcat(tens, OneToStr(num));
            strcat(tens, "十");
        }
        strcat(tens, OneToStr(left));
    }

    return tens;

}

char * HundredsToStr(int input, int zero)
{
    hundreds[0]='\0';
    int num = input / 100;
    int left = input % 100;

    if(num==0)
    {
        if(zero)
        {
            strcat(hundreds, "零");
        }
        strcat(hundreds, TensToStr(left, 0));
    }
    else
    {
        strcat(hundreds, OneToStr(num));
        strcat(hundreds, "百");
        if(left == 0)
        {
            return hundreds;
        }
        strcat(hundreds, TensToStr(left, 1));
    }
    
    return hundreds;
}

char * ThousandsToStr(int input, int zero)
{
    thousands[0]='\0';
    int num = input / 1000;
    int left = input % 1000;

    if(input>19)
    {
        one = 1;
    }

    if(num==0)
    {
        if(zero)
        {
            strcat(thousands, "零");
        }
        strcat(thousands, HundredsToStr(left, 0));
    }
    else
    {
        strcat(thousands, OneToStr(num));
        strcat(thousands, "千");
        if(left == 0)
        {
            return thousands;
        }
        strcat(thousands, HundredsToStr(left, 1));
    }

    return thousands;
}

char * WanToStr(unsigned long input, int zero)
{
    wan[0] = '\0';
    int num = input / 10000;
    int left = input % 10000;

    if(num==0)
    {
        if(zero)
        {
            strcat(wan, "零");
        }
        strcat(wan, ThousandsToStr(left, 0));
    }
    else
    {
        strcat(wan, ThousandsToStr(num, 0));
        strcat(wan, "萬");
        one = 1;
        if(left == 0)
        {
            return wan;
        }
        strcat(wan, ThousandsToStr(left, 1));
    }

    return wan;
}

char * YiToStr(unsigned long input, int zero)
{
    yi[0] = '\0';
    unsigned long num = input / 100000000;
    unsigned long left = input % 100000000;

    if(num==0)
    {
        if(zero)
        {
            strcat(yi, "零");
        }
        strcat(yi, WanToStr(left, 0));
    }
    else
    {
        strcat(yi, ThousandsToStr(num, 0));
        strcat(yi, "億");
        one = 1;
        if(left == 0)
        {
            return yi;
        }
        if(left < 10000000 && left > 9999)
        {
            strcat(yi, "零");
        }
        strcat(yi, WanToStr(left, 1));
    }

    return yi;
}
char * ConvertToChinese(unsigned long input)
{
    one = 0;
    if(input == 0)
    {
        return (char*)"零";
    }
    return YiToStr(input, 0);
}

#define TEST(IN, EXP) \
{ \
    printf("%s\n",ConvertToChinese(IN));\
    assert(strcmp(ConvertToChinese(IN), EXP) == 0);\
};
int main()
{
    TEST(0, "零");
    TEST(1, "一");
    TEST(2, "二");
    TEST(3, "三");
    TEST(4, "四");
    TEST(5, "五");
    TEST(6, "六");
    TEST(7, "七");
    TEST(8, "八");
    TEST(9, "九");
    TEST(10, "十");
    TEST(11, "十一");
    TEST(20, "二十");
    TEST(99, "九十九");
    TEST(100, "一百");
    TEST(101, "一百零一");
    TEST(110, "一百一十");
    TEST(111, "一百一十一");
    TEST(1000, "一千");
    TEST(1001, "一千零一");
    TEST(1010, "一千零一十");
    TEST(1011, "一千零一十一");
    TEST(1100, "一千一百");
    TEST(1101, "一千一百零一");
    TEST(1110, "一千一百一十");
    TEST(1111, "一千一百一十一");
    TEST(10000, "一萬");
    TEST(10001, "一萬零一");
    TEST(10010, "一萬零一十");
    TEST(10011, "一萬零一十一");
    TEST(10100, "一萬零一百");
    TEST(10101, "一萬零一百零一");
    TEST(10110, "一萬零一百一十");
    TEST(10111, "一萬零一百一十一");
    TEST(11000, "一萬一千");
    TEST(11001, "一萬一千零一");
    TEST(11010, "一萬一千零一十");
    TEST(11011, "一萬一千零一十一");
    TEST(11100, "一萬一千一百");
    TEST(11101, "一萬一千一百零一");
    TEST(11110, "一萬一千一百一十");
    TEST(11111, "一萬一千一百一十一");
    TEST(100000, "十萬");
    TEST(100001, "十萬零一");
    TEST(110000, "十一萬");
    TEST(1000000, "一百萬");
    TEST(1010000, "一百零一萬");
    TEST(10000000, "一千萬");
    TEST(10010000, "一千零一萬");
    TEST(99999999, "九千九百九十九萬九千九百九十九");
    TEST(100000000, "一億");
    TEST(100000001, "一億零一");
    TEST(110000000, "一億一千萬");
    TEST(101000000, "一億零一百萬");
    TEST(110100000, "一億一千零一十萬");
    TEST(110010000, "一億一千零一萬");
    TEST(101010000, "一億零一百零一萬");
    TEST(100010000, "一億零一萬");
    TEST(999999999, "九億九千九百九十九萬九千九百九十九");
    TEST(4294967295, "四十二億九千四百九十六萬七千二百九十五");
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define LST_MAX 127

typedef enum{FALSE = 0, TRUE = 1} BOOL;

typedef struct
{
    int lst[LST_MAX];
    int len;
} RESULT;

typedef struct
{
    unsigned long left;
    int mark;
    BOOL append0;
    unsigned long right;
} ANALYSE_RESULT;

typedef struct
{
   unsigned long rank;
   int mark;
} RANKS;

enum {TEN = 10, HUNDRED = 11, THOUSAND = 12, TEN_THOUSEND = 13, HUNDRED_MILLION = 14};

static char *STR[] = {"零", "一", "二", "三", "四", "五", "六","七", "八", "九", "十", "百", "千", "萬", "億"};

static RANKS s_ranks[] =
{
    {100000000, HUNDRED_MILLION},
    {10000, TEN_THOUSEND},
    {1000, THOUSAND},
    {100, HUNDRED},
    {10, TEN},
};
static int s_ranksLen = sizeof(s_ranks) / sizeof(RANKS);

static BOOL CheckIfAppend0(int remain, int rank)
{
    return (remain > 0 && remain < (rank / 10)) ? TRUE : FALSE;
}

static ANALYSE_RESULT Analyse(unsigned long n)
{
    ANALYSE_RESULT result = {0};
    int i = 0;

    for (i = 0; i < s_ranksLen; i++)
    {
        if (n >= s_ranks[i].rank)
        {
            result.left = n / s_ranks[i].rank;
            result.mark = s_ranks[i].mark;
            result.right = n % s_ranks[i].rank;
            result.append0 = CheckIfAppend0(result.right, s_ranks[i].rank);
            break;
        }
    }
    return result;
}

static RESULT Append(unsigned long n, RESULT result_in)
{
    RESULT result = result_in;

    if (result.len < (sizeof(result.lst) / sizeof(result.lst[0])))
    {
        result.lst[result.len] = n;
        result.len ++;
    }
    else
    {
        assert(0);
    }
    return result;
}

static RESULT TransN(unsigned long n, RESULT result_in)
{
    RESULT result = result_in;

    if (n >= 10)
    {
        ANALYSE_RESULT ret = Analyse(n);
        result = TransN(ret.left, result);
        result = Append(ret.mark, result);
        if (ret.append0) result = Append(0, result);
        result = TransN(ret.right, result);
    }
    else if (n > 0)
    {
        result = Append(n, result);
    }
    return result;
}

static RESULT Trans(unsigned long n)
{
    RESULT result = {{0}};

    if (n == 0)
    {
        result = Append(0, result);
    }
    else
    {
        result = TransN(n, result);
    }
    return result;
}

static BOOL NeedSkip1(RESULT result)
{
    return (result.len >= 2 && result.lst[0] == 1 && result.lst[1] == TEN) ? TRUE : FALSE;
}

static void Output(RESULT result_in, char *out, size_t outMaxSize)
{
    char * p = out;
    int i = 0;

    if (NeedSkip1(result_in)) i++; /*根據用例需求或習慣確定是否要將"一十""一十二"等前面的"一"字去掉*/

    while(i < result_in.len)
    {
        p += snprintf(p, outMaxSize - strlen(out), "%s", STR[result_in.lst[i]]);
        i++;
    }
}

static void ToChinese(unsigned long n, char *out, size_t outMaxSize)
{
    /*靜態函式看作內部函式,不用進行有效性判斷,可以進行有效性測試,如*/
    assert(out != NULL);
    assert(outMaxSize > strlen(STR[0]));
    assert(out[0] == '\0');

    Output(Trans(n), out, outMaxSize);
}

char* ConvertToChinese(unsigned long n)
{
    static char out[128];/*偷懶一下,引入不可重入問題, 可以考慮malloc或增加函式變數引入外部儲存*/

    memset(out, 0, sizeof(out));
    ToChinese(n, out, sizeof(out));

    return out;
}

int main(int argc, char *argv[])
{
    #define TEST(IN, EXP) assert(strcmp(ConvertToChinese(IN), (EXP)) == 0)
    TEST(0, "零");
    TEST(1, "一");
    TEST(2, "二");
    TEST(3, "三");
    TEST(4, "四");
    TEST(5, "五");
    TEST(6, "六");
    TEST(7, "七");
    TEST(8, "八");
    TEST(9, "九");
    TEST(10, "十");
    TEST(11, "十一");
    TEST(20, "二十");
    TEST(99, "九十九");
    TEST(100, "一百");
    TEST(101, "一百零一");
    TEST(110, "一百一十");
    TEST(111, "一百一十一");
    TEST(1000, "一千");
    TEST(1001, "一千零一");
    TEST(1010, "一千零一十");
    TEST(1011, "一千零一十一");
    TEST(1100, "一千一百");
    TEST(1101, "一千一百零一");
    TEST(1110, "一千一百一十");
    TEST(1111, "一千一百一十一");
    TEST(10000, "一萬");
    TEST(10001, "一萬零一");
    TEST(10010, "一萬零一十");
    TEST(10011, "一萬零一十一");
    TEST(10100, "一萬零一百");
    TEST(10101, "一萬零一百零一");
    TEST(10110, "一萬零一百一十");
    TEST(10111, "一萬零一百一十一");
    TEST(11000, "一萬一千");
    TEST(11001, "一萬一千零一");
    TEST(11010, "一萬一千零一十");
    TEST(11011, "一萬一千零一十一");
    TEST(11100, "一萬一千一百");
    TEST(11101, "一萬一千一百零一");
    TEST(11110, "一萬一千一百一十");
    TEST(11111, "一萬一千一百一十一");
    TEST(100000, "十萬");
    TEST(100001, "十萬零一");
    TEST(110000, "十一萬");
    TEST(1000000, "一百萬");
    TEST(1010000, "一百零一萬");
    TEST(10000000, "一千萬");
    TEST(10010000, "一千零一萬");
    TEST(99999999, "九千九百九十九萬九千九百九十九");
    TEST(100000000, "一億");
    TEST(100000001, "一億零一");
    TEST(110000000, "一億一千萬");
    TEST(101000000, "一億零一百萬");
    TEST(110100000, "一億一千零一十萬");
    TEST(110010000, "一億一千零一萬");
    TEST(101010000, "一億零一百零一萬");
    TEST(100010000, "一億零一萬");
	TEST(1000000001, "十億零一");
    TEST(1000000010, "十億零一十");
    TEST(1000000100, "十億零一百");
    TEST(1000001000, "十億零一千");
    TEST(1000010000, "十億零一萬");
    TEST(999999999, "九億九千九百九十九萬九千九百九十九");
    TEST(4294967295, "四十二億九千四百九十六萬七千二百九十五");
    system("PAUSE");
    return 0;
}

 

數字轉中文

char * ConvertToChinese(unsigned long);

 

比如:101輸出一百零一

 

測試用例:

#define TEST(IN, EXP) assert(strcmp(ConvertToChinese(IN), EXP) == 0)

    TEST(0, "零");

    TEST(1, "一");

    TEST(2, "二");

    TEST(3, "三");

    TEST(4, "四");

    TEST(5, "五");

    TEST(6, "六");

    TEST(7, "七");

    TEST(8, "八");

    TEST(9, "九");

    TEST(10, "十");

    TEST(11, "十一");

    TEST(20, "二十");

    TEST(99, "九十九");

   TEST(100, "一百");

   TEST(101, "一百零一");

   TEST(110, "一百一十");

   TEST(111, "一百一十一");

    TEST(1000, "一千");

    TEST(1001, "一千零一");

    TEST(1010, "一千零一十");

    TEST(1011, "一千零一十一");

    TEST(1100, "一千一百");

    TEST(1101, "一千一百零一");

    TEST(1110, "一千一百一十");

    TEST(1111, "一千一百一十一");

    TEST(10000, "一萬");

    TEST(10001, "一萬零一");

    TEST(10010, "一萬零一十");

    TEST(10011, "一萬零一十一");

    TEST(10100, "一萬零一百");

    TEST(10101, "一萬零一百零一");

    TEST(10110, "一萬零一百一十");

    TEST(10111, "一萬零一百一十一");

    TEST(11000, "一萬一千");

    TEST(11001, "一萬一千零一");

    TEST(11010, "一萬一千零一十");

    TEST(11011, "一萬一千零一十一");

    TEST(11100, "一萬一千一百");

    TEST(11101, "一萬一千一百零一");

    TEST(11110, "一萬一千一百一十");

    TEST(11111, "一萬一千一百一十一");

    TEST(100000, "十萬");

    TEST(100001, "十萬零一");

    TEST(110000, "十一萬");

    TEST(1000000, "一百萬");

    TEST(1010000, "一百零一萬");

    TEST(10000000, "一千萬");

    TEST(10010000, "一千零一萬");

    TEST(99999999, "九千九百九十九萬九千九百九十九");

    TEST(100000000, "一億");

    TEST(100000001, "一億零一");

    TEST(110000000, "一億一千萬");

    TEST(101000000, "一億零一百萬");

    TEST(110100000, "一億一千零一十萬");

    TEST(110010000, "一億一千零一萬");

    TEST(101010000, "一億零一百零一萬");

    TEST(100010000, "一億零一萬");

    TEST(999999999, "九億九千九百九十九萬九千九百九十九");

    TEST(4294967295, "四十二億九千四百九十六萬七千二百九十五");