C语言代码分享:小写金额转换为大写格式

913 阅读4分钟

这是我参与新手入门的第2篇文章


背景

银行、单位和个人填写的各种票据和结算凭证是办理支付结算和现金收付的重要依据,直接关系到支付结算的准确、及时和安全。票据和结算凭证是银行、单位和个人凭以记载帐务的会计凭证,是记载经济业务和明确经济责任的一种书面证明。因此,填写票据和结算凭证,必须做到标准化、规范化,要要素齐全、数字正确、字迹清晰、不错漏、不潦草,防止涂改。

遵循规则

  1. 中文大写金额数字填写,如壹、贰、叁、肆、伍、陆、柒、捌、玖、拾、佰、仟、万、亿、元、角、分、零、整(正)等字样,不得用一、二(两)、三、四、五、六、七、八、九、十、毛、另(或0)填写,不得自造简化字。如果金额数字书写中使用繁体字,也应受理。

  2. “人民币”于数字之间不得留有空位,有固定格式的的重要单证,大写金额栏一般都印有“人民币”字样,大写数字应紧接在“人民币”后面书写,在“人 民币”与数字之间不得留有空位。大写金额栏没有印有“人民币”字样的,应加添“人民币”三字。

  3. 整(正)字的用法,中文大写金额数字到”元“为止的,在”元“之后、应些”整“(或”正“)字;在”角“之后,可以不写”整“(或”正“)字;大写金额 数字有”分“的,”分“后面不写”整“(或”正“)字。

  4. 有关零的写法,阿拉伯数字小写金额数字中有”0“时,中文大写应按照汉语语言规律、金额数字构成和防止涂改的要求进行书写。举例如下:

  • 阿拉伯数字中间有“0”时,中文大写要写”零“字。

  • 阿拉伯数字中间连续有几个“0”时、中文大写金额中间可以只写一个”零“字。

  • 阿拉伯金额数字万位和元位是”0“,或者数字中间连续有几个”0“,万位、元位也是”0“但千位、角位不是”0“时,中文大写金额中可以只写一个零字,也可以不写”零“字。

  • 阿拉伯金额数字角位是”0“而分位不是”0“时,中文大写金额”元“后面应写”零“字。

  1. 壹拾几的“壹”字,在汉字大写中不得遗漏。平时口语习惯说“拾几”“拾几万”但“拾”代表的是数位,不是数字。

示范代码

char* chineseFee( char* dest, char* src )
{
    enum
    {
        START,                 /*开始*/
        MINUS,                 /*负号*/
        ZEROINT,               /*0整数*/
        INTEGER,               /*整数*/
        DECIMAL,               /*小数点*/
        DECIMALfRACTION,       /*小数位*/
        END,                   /*结束*/
        ERROR                  /*错误*/
    } status = START;
    struct
    {
        int minus;             /*0为正,1为负*/
        int sizeInt;
        int sizeDecimal;
        int integer[10];
        int decimal[10];
    } feeInfo;
    char* NumberChar[] = 
        { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" };
    char* UnitChar[] = 
        { "整", "圆", "拾", "佰","仟", "万", "拾", "佰", "仟", "亿", 
          "拾", "佰", "仟", "万亿", "拾", "佰", "仟", "亿亿", 
          "角", "分", "负", "人民币" };
          
    int      i, j,size;             /*循环变量*/
    int      zeroTag        = 0,    /*0标志*/
             decZeroTag     = 0;
      
    char*    pDest          = dest;
    char*    pSrc           = src;
    
    int*     pInt           = feeInfo.integer;
    int*     pDec           = feeInfo.decimal;
    
    /*初始化*/
    feeInfo.sizeInt        = 0;
    feeInfo.sizeDecimal    = 0;
    feeInfo.minus          = 0;
    
    /*分析字符串*/
    while( 1 )
    {
        switch ( *pSrc )
        {
            case '-' :
                status = ( status == START ) ? MINUS : ERROR;
                feeInfo.minus = ( status == MINUS ) ? 1 : 0;
                break;
            case '1' :
            case '2' :
            case '3' :
            case '4' :
            case '5' :
            case '6' :
            case '7' :
            case '8' :
            case '9' :
            case '0' :
                if ( *pSrc == '0' && status == ZEROINT )/*|| status == START ) )*/
                {
                    status = ERROR;
                    break;
                }
                if ( status == MINUS || status == START || status == INTEGER )
                {
                    if ( *pSrc == '0' && ( status == MINUS || status == START ) )
                        status = ZEROINT;
                    else
                        status = INTEGER;
                    *pInt = (*pSrc) - 48;
                    ++pInt;
                    ++feeInfo.sizeInt;
                }
                else if ( status == DECIMAL || status == DECIMALfRACTION )
                {
                    status = DECIMALfRACTION;
                    *pDec = (*pSrc) - 48;
                    ++pDec;
                    ++feeInfo.sizeDecimal;
                }
                else
                {
                    status =ERROR;
                }
                break;
            case '.' :
                status = ( status == INTEGER || status == ZEROINT ) 
                         ? DECIMAL : ERROR;
                break;
            case '\0' :
                status = ( status == INTEGER || status == DECIMALfRACTION 
                           || status == ZEROINT ) ? END : ERROR;
                break;
            default :
                status = ERROR;
        }
        if ( status == END ) 
            break;
        else if ( status == ERROR )
            return NULL;
        
        ++pSrc;
    }
    
    /*只有1位小数时,设置百分位为0,使下面代码不需要区分这两种情况*/
    if ( feeInfo.sizeDecimal == 1 )
    {
        feeInfo.decimal[ 1 ] = 0;
        ++feeInfo.sizeDecimal;
    }
    /*判断是否需要打印小数部分,有小数部且十分位和百分位不都为0*/
    /*需要打印小数部时,zeroTag设为0,否则设为1*/
    if ( feeInfo.sizeDecimal == 0                                 /*没有小数*/
        || ( !feeInfo.decimal[ 0 ] && !feeInfo.decimal[ 1 ] ) )   /*小数部都为0*/
        decZeroTag = 1;
    else
        decZeroTag = 0;
        
    /*printf( "int size: %d    decimal size: %d\n", feeInfo.sizeInt, feeInfo.sizeDecimal );*/
    
    strcpy( pDest, UnitChar[ 21 ] );                  /*初始化目标字符串-人民币*/
    
    if ( feeInfo.minus ) strcat( pDest, UnitChar[ 20 ] );    /*负号*/
        
    /*处理整数部分*/
    size = feeInfo.sizeInt;
    for( i = 0; i < size; ++i )
    {
        j = size - i - 1 & 0x3;                              /*j = 0时为段尾*/
        if ( feeInfo.integer[ i ] == 0 && j )                /*处理非段尾0*/
        {
            zeroTag = 1;
        }
        else if ( feeInfo.integer[ i ] == 0 && !j )          /*处理段尾0*/
        {
            if ( feeInfo.sizeInt == 1 && decZeroTag )        /*特殊处理个位0*/
                strcat( pDest, NumberChar[ feeInfo.integer[ i ] ] );
            if ( feeInfo.sizeInt != 1 || decZeroTag )
                strcat( pDest, UnitChar[ size - i ] );
            zeroTag = 0;
        }
        else                                                 /*处理非0*/
        {
            if ( zeroTag )
            {
                strcat( pDest, NumberChar[ 0 ] );
                zeroTag = 0;
            }
            strcat( pDest, NumberChar[ feeInfo.integer[ i ] ] );
            strcat( pDest, UnitChar[ size - i ] );
            if ( !j ) zeroTag = 0;                      /*如果是段尾,设为非标志*/
        }
    }
    
    if ( decZeroTag )
    {
        strcat( pDest, UnitChar[ 0 ] );/*没有小数部,打印"整"字符*/
    }
    else
    {
        /*十分位*/
        if ( feeInfo.decimal[ 0 ] )
        {
            strcat( pDest, NumberChar[ feeInfo.decimal[ 0 ] ] );
            strcat( pDest, UnitChar[ 18 ] );
        }
        else if ( feeInfo.sizeInt != 1 || feeInfo.integer[ 0 ] )
        {
            strcat( pDest, NumberChar[ feeInfo.decimal[ 0 ] ] );
        }
        
        /*百分位不为0时*/
        if ( feeInfo.decimal[ 1 ] )    
        {
            strcat( pDest, NumberChar[ feeInfo.decimal[ 1 ] ] );
            strcat( pDest, UnitChar[ 19 ] );
        }
    }
    return dest;
}

函数功能

将源字符串中的小写金额转换为大写格式

  • dest 目的字符串
  • src 小写金额字符串
  • return
  1. NULL:源字符串的格式错误,返回NULL
  2. 非NULL:目的字符串的首地址