读书人

关于金额转换有关问题

发布时间: 2012-03-01 10:25:46 作者: rapoo

关于金额转换问题
最近碰到一个问题,不知如何解决。要求打印输出如下: 拾 万 仟 拾 元 分 角。就是将小写金额转为大写后在拆分打到上面的那个格式中。小写金额转大写我会,但是拆分的时候用什么函数好阿。因为打印的时候还要对准格式,把分角元拾仟万这些对应着打上去。哪位能告诉我怎么实现呢,肯定要涉及到些判断的吧。

[解决办法]
/**
* @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 ", 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;
}

读书人网 >C语言

热点推荐