小寫金額轉換為大寫金額(C實現)

發表于:2007-05-25來源:作者:點擊數: 標簽:小寫金額大寫宋體實現
MI LY: 宋體; mso-font-kerning: 1.0pt; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR

MILY: 宋體; mso-font-kerning: 1.0pt; mso-hansi-font-family: 'Times New Roman'; mso-bidi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">一個C實現的小寫金額轉換大寫金額的方法。網上C實現的轉換很少,其它的實現也很少有做到分析源字符串格式的功能。另附《clearcase/" target="_blank" >cc0000; FONT-FAMILY: 宋體; mso-font-kerning: 1.0pt; mso-hansi-font-family: 'Times New Roman'; mso-ascii-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ZH-CN; mso-bidi-language: AR-SA">正確填寫票據和結算憑證的基本規定

作者:張經緯 2005-08-02

前言

  銀行、單位和個人填寫的各種票據和結算憑證是辦理支付結算和現金收付的重要依據,直接關系到支付結算的準確、及時和安全。票據和結算憑證是銀行、單位和個人憑以記載帳務的會計憑證,是記載經濟業務和明確經濟責任的一種書面證明。因此,填寫票據和結算憑證,必須做到標準化、規范化,要要素齊全、數字正確、字跡清晰、不錯漏、不潦草,防止涂改。

  我的服務需要一個金額轉換過程,本來想在網上找,但都是C++、JavaScript、DelphiDemo,還沒有C的。索性自己寫一個。參考了其它的轉換算法,對我有些啟發。

  大多的算法都是直接分析字符串生成大寫金額,即存在一個假設:源字符串的格式是正確的。在我的過程中,用狀態機的方法分析源字符串,錯誤時,返回空指針(我可不敢保證傳給我的過程的都是##.##)?!》治龀鲈醋址姓麛挡坑卸嗌賯€數字,是否有小數,統計結果放在一個結構體中,整數和小數部分的數字分別放在兩個整形數組里。

  有了統計數據就可以生成大寫金額了。轉換過程有個難點:要區分萬、億等,特別是個位這個,這個概念是在《小寫轉大寫金額在C++中的實現》文章中提到的。在下面的程序中用j= ( size - i - 1 ) & 0x3,實際上是j = ( size - i - 1 ) % 4取模,j==0時為段尾,需要特殊處理。所有的處理都是圍繞0來進行的,也就是說,0才是難點。

  特殊位置的0,按段分,段中第一個非0數字前的0,可能有多個;段中兩個非0數字間的0;段尾的0;個位的0;十分位,角位置的0。

  另外,轉換的一個重點是大寫金額的寫法,好像大多的算法都注重轉換過程而對這個問題沒有深究。我在文章后面附上轉換規則。

下面是代碼

/**
 * @brief
將源字符串中的小寫金額轉換為大寫格式
 *
 * @param dest
目的字符串
 * @param src 
小寫金額字符串
 * @return
 * - NULL
源字符串的格式錯誤,返回NULL
 * -
NULL 目的字符串的首地址
 * @note
轉換根據:中國人民銀行會計司編寫的最新《企業、銀行正確辦理支付結算
 *      
指南》的第114-115
 */
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 '' :
                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;

}

  代碼中有些地方沒有注釋清楚,要是有不明白的可以E-Mailz_jingwei@163.com。

參考: 小寫轉大寫金額在C++中的實現

附:

正確填寫票據和結算憑證的基本規定

銀行、單位和個人填寫的各種票據和結算憑證是辦理支付結算和現金收付的重要依據,直接關系到支付結算的準確、及時和安全。票據和結算憑證是銀行、單位和個人憑以記載帳務的會計憑證,是記載經濟業務和明確經濟責任的一種書面證明。因此,填寫票據和結算憑證,必須做到標準化、規范化,要要素齊全、數字正確、字跡清晰、不錯漏、不潦草,防止涂改。

一、 中文大寫金額數字應用正楷或行書填寫,如壹()、貳()、叁、肆()、伍()、陸()、柒、捌、玖、拾、伯、仟、萬()、億、元、角、分、零、整()等字樣。不得用一、二()、三、四、五、六、七、八、九、十、念、毛、另(0)填寫,不得自造簡化字。如果金額數字書寫中使用繁體字,也應受理。

二、 中文大寫金額數字到""為止的,在""之后,應寫""("")字,在""之后可以不寫""("")字。數字有""的,""后面不寫""("")字。

三、 中文大寫金額數字前應標明"人民幣"字樣,大寫金額數字應緊接"人民幣"字樣填寫,不得留有空白。大寫金額數字前未印"人民幣"字樣的,應加填"人民幣"三字。在票據和結算憑證大寫金額欄內不得預印固定的"仟、佰、拾、萬、仟、佰、拾、元、角、分字樣。

四、阿拉伯小寫金額數字中有"0"時,中文大寫應按照漢語語言規律、金額數字構成和防止涂改的要求進行書寫。舉例如下:

()阿拉伯數字中間有"0"時,中文大寫金額要寫""字。如¥1,40950,應寫成人民幣壹仟肆佰零玖元伍角。
(
)阿拉伯數字中間連續有幾個"0"時,中文大寫金額中間可以只寫一個""字。如¥6,00714,應寫成人民幣陸仟零柒元壹角肆分。
(
)阿拉伯金額數字萬位或元位是"0",或者數字中間連續有幾個"0",萬位、元位也是"0",但千位、角位不是"0"時,中文大寫金額中可以只寫一個零字,也可以不寫""字。如¥1,68032,應寫成人民幣壹仟陸佰捌拾元零叁角貳分,或者寫成人民幣壹仟陸佰捌拾元叁角貳分;又如¥107,00053,應寫成人民幣壹拾萬柒仟元零伍角叁分,或者寫成人民幣壹拾萬零柒仟元伍角叁分。
(
)阿拉伯金額數字角位是"0",而分位不是"0"時,中文大寫金額""后面應寫""字。如¥16,40902,應寫成人民幣壹萬陸仟肆佰零玖元零貳分;又如¥32504,應寫成人民幣叁佰貳拾伍元零肆分。

五、阿拉伯小寫金額數字前面,均應填寫人民幣符號""(或草寫)。阿拉伯小寫金額數字要認真填寫,不得連寫分辨不清。

六、票據的出票日期必須使用中文大寫。為防止變造票據的出票日期,在填寫月、日時,月為壹、貳和壹拾的,日為壹至玖和壹拾、貳拾和叁拾的,應在其前加""; 日為拾壹至拾玖的,應在其前加""。如115,應寫成零壹月壹拾伍日。再如1020,應寫成零壹拾月零貳拾日。

七、票據出票日期使用小寫填寫的,銀行不予受理。大寫日期未按要求規范填寫的,銀行可予受理,但由此造成損失的,由出票人自行承擔。

引自中國人民銀行會計司編寫的最新《企業、銀行正確辦理支付結算指南》的第114-115

原文轉自:http://www.anti-gravitydesign.com

評論列表(網友評論僅供網友表達個人看法,并不表明本站同意其觀點或證實其描述)
国产97人人超碰caoprom_尤物国产在线一区手机播放_精品国产一区二区三_色天使久久综合给合久久97