1. 更新说明

  1. 添加与 “零圆整” 等价的预先判断 (0 / 0. / 0.0 / 0.00 / . / .0 / .00)
  2. 修复了因使用函数 strdup 导致的内存泄漏
  3. 除去输入串多余的空白符(空格 / Tab制表符)

2. 代码如下面所示

//=================================================================
// CPSTR: Copyright (c) 2020 By Abodu, All Rights Reserved.
// FNAME: arabToChinese.c
// AUTHR: abodu,abodu@qq.com
// CREAT: 2020-06-14 14:56:23
// ENCOD: UTF-8 Without BOM
// VERNO: 1.0.3
// LUPTS: 2021-10-21 22:18:50
//=================================================================
#include <stdio.h>
#include <stdlib.h>
#include <string.h>/**
*** 阿拉伯数字表示的金额串转换成中文大写金额
*** 转换成功,则输出转换后的大写金额
*** 转换失败,则返回NULL
**/
char *arabToChinese(const char *aInput);#define JINER_MAX_SIZE 1 << 5
#define CNFEE_MAX_SIZE 1 << 8static char a_src[JINER_MAX_SIZE] = {0};
static char o_chn[CNFEE_MAX_SIZE] = {0};
static char *spo = o_chn;char *CU_INT[] = {"整", "圆",             //"拾", "佰", "仟", "萬", //"拾", "佰", "仟", "億", //"拾", "佰", "仟", "兆", //"拾", "佰", "仟", "京", //"拾", "佰", "仟", "垓"  //
};
char *CU_DEC[] = {"负", "角", "份", "厘", "钱", "毫"};char *CN[] = {"零", "壹", "贰", "叁", "肆", //"伍", "陆", "柒", "捌", "玖"};char *CZ_ERR[] = {"[ERR]格式错误,负号(-)出现在金额串的不正确位置处","[ERR]格式错误,小数点(.)只能出现一次","[ERR]格式错误,除-0.XX和0.XX外,不允许出现前置零(0XXX)","[ERR]格式错误,输入的串内含有不属于十进制金额的其他字符",
};static char *apd1(char *npr) {int t = strlen(o_chn);snprintf(o_chn + t, sizeof(o_chn) - t, "%s", npr);return o_chn;
}static char *apd2(char *N1, char *N2) { return apd1(N1), apd1(N2); }/**
*** 删除字符串中所有的逗号和空格
**/
char *trim_casp_all(char *p) {int i = 0, j = 0;while (p[i]) {if (p[i] != ',' && p[i] != ' ' && p[i] != '\t') {p[j++] = p[i];}i++;}p[j] = '\0';//    printf("%s\n", p);return p;
}int main(int argc, char *argv[]) {int i = 1;char *p = NULL;fprintf(stderr, "-- 阿拉伯数字转化成中文金额字符串(小数部分仅保留到分) --\n");do {memset(a_src, 0, JINER_MAX_SIZE);memset(o_chn, 0, CNFEE_MAX_SIZE);if (argc == 1) {//后面没有参数,需要手动输入一个小写金额printf("请输入(阿拉伯数字表示的)小写金额:>");scanf("%s", a_src);} else {sprintf(a_src, "%s", argv[i++]);}printf("%s --> %s\n", a_src, arabToChinese(trim_casp_all(a_src)));} while (i < argc);return 0;
}char *arabToChinese(const char *aInput) {
#define check_zero_yuan(X)                                                     \!strcmp((X), "0.0") || !strcmp((X), "0.00") || !strcmp((X), "0") ||          \!strcmp((X), ".0") || !strcmp((X), ".00") || !strcmp((X), "0.") ||       \!strcmp((X), ".")if (check_zero_yuan(aInput)) {apd1("零圆整");return o_chn;}// PART0 ==== 准备阶段 ====enum {//定义FSM(有限状态机)的状态BEGIN = 0, //起始位MINUS,     //负号位ZEROPRE,   //前缀零(格式 0.XX 或 -0.XX)INTEGER,   //整数位FST_MAX} state = BEGIN;/*** 下面的变量定义初始化成NULL至关重要* 关系着某些位置是否存在,若是一直是NULL则表示某个位置是不存在的**/typedef char *pos_t;pos_t szInput = strdup(aInput);pos_t pDecBgn = NULL;pos_t pMinus = NULL;/** 将it 与 pIntBgn 同时指向输入的金额串的开头 */pos_t pIntBgn = szInput;pos_t it = szInput; //(it是遍历指针,iterator的缩写)// PART1 ====使用状态机解析金额串,若是有格式错误 则会报错并返回 ====do {int ecode = -1;switch (*it) {case '-': // CLASS0: 当前字符是负号(-)/**负号在最开头才算是合法的*/if (BEGIN == state) {pMinus = it;/**将整数部分的开头后移一位(以保证整数部分只包含数字)*/pIntBgn++;/** 状态更新为 MINUS */state = MINUS;} else {/**说明在非开头位置又遇见了负号,格式错误序号设置成*/ecode = 0;}break;case '.': // CLASS1: 当前字符是小数点if (NULL == pDecBgn) {/**后面的一位就是小数部分的起始位置当前置为 \0 以保证整数部分结束了 */pDecBgn = it + 1, *it = '\0';/**负号位状态(-.XXX) 或 起始位状态(.XXX) 时 优化掉整数转换部分 */if (MINUS == state || BEGIN == state) {pIntBgn = NULL; //更新 pIntBgn 为 NULL}} else {/**已经在小数位状态, 再一次遇见小数点*/ecode = 1;}break;case '0' ... '9': // CLASS2: 当前字符是数字符号if (it[0] == '0') {switch (state) {case ZEROPRE:/** 在处于有前缀0的状态下又碰见一个0字符 */ecode = 2;break;case BEGIN:/** 起始位置状态下 进入 前缀零模式 */state = ZEROPRE;break;default:state = INTEGER;}} else { //其他均转化为 数字符号状态state = INTEGER;}break;default:// CLASS3: 当前字符是除 负号,小数点,数字字符 之外的其他字符ecode = 3;}if (ecode != -1) {free(szInput);return CZ_ERR[ecode];}// it后移一位,为进行下一轮判断做准备it++;} while (*it); // 当it到达szInput的末尾就退出循环// PART2 ==== 进行转换 ====//有负号if (pMinus) {apd1(CU_DEC[0]);}//====转换整数部分 ====if (pIntBgn && pIntBgn[0] != '0') {char *t_ops = o_chn;it = pIntBgn; //将it重置到整数部分的开头
#define chkback1 (it - pIntBgn > 1 && it[-1] == '0')
#define chkback2                                                               \(it - pIntBgn > 2 && (it[-1] == '0' || 0 == strncmp(it - 2, "00", 2)))
#define chkback3                                                               \(it - pIntBgn > 3 && (it[-1] == '0' || 0 == strncmp(it - 2, "00", 2) ||      \0 == strncmp(it - 3, "000", 3)))//有整数部分并且以非零开头才需要进行转换int w = strlen(it);int an = 0, r = 0;pos_t cu = NULL;do {r = w % 4;cu = CU_INT[w];an = it[0] & 0xF; //<==> it[0] - '0', 输入的数字字符转换成对应的数字//根据位数判断if (an) {// value is none-zeroswitch (r) {case 0:if (0 == strncmp(it - 4, "0000", 4)) {apd1(CN[0]);}apd2(CN[an], cu);break;case 3:if (chkback1) {apd1(CN[0]);}apd2(CN[an], cu);break;case 2:if (chkback2) {apd1(CN[0]);}apd2(CN[an], cu);break;case 1:// printf("@@@ AAA @@@\n");if (chkback3) {apd1(CN[0]);}apd2(CN[an], cu);break;}} else {//只判断 r==1 时的场景if (r == 1) {if (w == 1) {apd1(cu);} else {if (strncmp(it - 3, "0000", 4)) {apd1(cu);}}}}// printf("w:%2d, r:%d, i_cur:%s, out:%s,\n", w, r, it, o_chn);// it每向后移一位,权位降一级it++, w--;} while (*it);}//====转换小数部分 ====
#define check_no_dec                                                           \!pDecBgn || *pDecBgn == '\0' ||                                              \(pDecBgn[0] == '0' && (pDecBgn[1] == '0' || pDecBgn[1] == '\0'))if (check_no_dec) {//直接打印"XX圆整"apd1(CU_INT[0]);} else { //至少有一位小数int nJiao = pDecBgn[0] & 0xF;int nFen = -1;if (pDecBgn[1] != '\0') {nFen = pDecBgn[1] & 0xF;}apd1(CN[nJiao]);if (nJiao) {apd1(CU_DEC[1]);}if (nFen >= 1) {apd1(CN[nFen]);apd1(CU_DEC[2]);}}free(szInput);return o_chn;
}

3. 测试结果

截图1:

# ./a2c 1001000088080.01 8049307164110.12 12
---- 阿拉伯数字转化成中文金额字符串(小数部分仅保留到分) ----
1001000088080.01 --> 壹兆零壹拾億零捌萬捌仟零捌拾圆零壹分
8049307164110.12 --> 捌兆零肆佰玖拾叁億零柒佰壹拾陆萬肆仟壹佰壹拾圆壹角贰分
1000000000 --> 壹拾億圆整

截图2

# ./a2c 1,0010,0008,8080.01 80,493,071,641,101.12 12.10 332.00 | awk '{printf("%20s --> %s\n",$1,$3)}'
---- 阿拉伯数字转化成中文金额字符串(小数部分仅保留到分) ----1001000088080.01 --> 壹兆零壹拾億零捌萬捌仟零捌拾圆零壹分80493071641101.12 --> 捌拾兆肆仟玖佰叁拾億柒仟壹佰陆拾肆萬壹仟壹佰零壹圆壹角贰分12.10 --> 壹拾贰圆壹角332.00 --> 叁佰叁拾贰圆整

截图3

# ./a2c -.12 0.0 .00 .0 -0.20 9.0 .19 | awk '{printf("%10s --> %s\n",$1,$3)}'
-- 阿拉伯数字转化成中文金额字符串(小数部分仅保留到分) ---.12 --> 负壹角贰份0.0 --> 零圆整.00 --> 零圆整.0 --> 零圆整-0.20 --> 负贰角9.0 --> 玖圆整.19 --> 壹角玖份

【C语言】小写数字金额转换成中文大写金额相关推荐

  1. 金额转换成中文大写金额

    留个纪念.这个类主要用于将数字金额转换成中文大写金额,提供了三个方法: toDX(double val) toDX(String val) toDX(int val) 使用方法 AmtInWords. ...

  2. 把数字金额转换成中文大写数字

    //把数字金额转换成中文大写数字 function changeNumMoneyToChinese(money) { var cnNums = new Array("零", &qu ...

  3. c#金额转换成中文大写金额

    c#金额转换成中文大写金额 原文:c#金额转换成中文大写金额 2018-08-24 转别人 c#金额转换成中文大写金额 /// <summary>/// 金额转换成中文大写金额/// &l ...

  4. 如何把数字金额转换成中文大写

    问题:要求把万亿级别内的浮点数转换成中文大写,例如把数字1112221000060.254400转换成:壹万壹仟壹佰贰拾贰亿贰仟壹佰万零陆拾元零贰角伍分 分析:关键是先把double类型转换成char ...

  5. .NET把小写数字金额转换成大写人民币金额的两种算法

    第一种方法: 用正则表达式,C#方法如下 usingSystem.Text.RegularExpressions;//首先引入命名空间 private string DaXie ( string  m ...

  6. php数字转换百千万,PHP数字金额转换成中文大写显示

    整个功能其实不难,只是还算挺实用,所以记一下哈,其他编程语言转换一下也是能可以的! 思路:把传过来的金额转换成整数和小数两部分,再对其分别进行转换处理 代码附上: function moneyToSt ...

  7. php显示大写金额,PHP数字金额转换成中文大写显示

    整个功能其实不难,只是还算挺实用,所以记一下哈,其他编程语言转换一下也是能可以的! 思路:把传过来的金额转换成整数和小数两部分,再对其分别进行转换处理 代码附上: function moneyToSt ...

  8. php 把数字变成大写数字,PHP数字金额转换成中文大写显示

    整个功能其实不难,只是还算挺实用,所以记一下哈,其他编程语言转换一下也是能可以的! 思路:把传过来的金额转换成整数和小数两部分,再对其分别进行转换处理 代码附上: function moneyToSt ...

  9. java中数字格式金额转换成中文大写金额工具类

    /*** 金额转换工具类*/ public class MoneyUtils {private static final String UNIT = "万千佰拾亿千佰拾万千佰拾元角分&quo ...

最新文章

  1. AC日记——信息传递 洛谷 P2661 (tarjan求环)
  2. Android源码项目目录结构
  3. 爬虫python下载视频_用python做爬虫下载视频
  4. mysql stack is full_mysql优化之表的优化与列类型选择
  5. html设置顶部对齐,HTML / CSS文本从div顶部对齐
  6. 《塔木德智慧全书》(之四)
  7. 别让for循环毁了你的程序(一)
  8. DetoursHook
  9. 轻松解决U盘拷贝文件时提示文件过大问题
  10. 使用Gradle构建Spring源码
  11. Coded UI 自动化测试初步研究
  12. Matlab加矩形窗程序,基于MATLAB结合矩形窗设计FIR滤波器
  13. 新元宇宙奇科幻小说每周连载《地球人奇游天球记》第十二回金星挖矿
  14. python控制苹果手机触摸屏失灵怎么办_苹果手机触摸屏失灵怎么办
  15. OpenGl学习笔记二:创建自己的着色器
  16. 批量提取CAD中文字
  17. CTFHub笔记之WEB文件上传:无验证、前端验证、文件头检查
  18. MYSQL的地理信息数据库_国家基础地理信息系统数据库
  19. deploy market
  20. 暗黑起源服务器维护,暗黑起源官方网站

热门文章

  1. Bailian3255 十进制到六进制【进制转换】
  2. 编译报错undefined symbol: vtable for
  3. 《学习opencv》第四章1,2题(第二题详解,最切题)
  4. MUSCI算法估计空间方位角
  5. python分析红楼梦中人物形象_红楼梦人物形象分析+赏析_作文
  6. maven打包报错 Failed to execute goal org.apache.maven.plugins:maven-jar-plugin:3.0.2:jar
  7. 计算机视觉——Bag Of features图像检索
  8. 光伏组件高温自燃?台湾一屋顶光伏电站起火
  9. 计算机会计技术特点,会计电算化系统的特点
  10. IcoFX v3.6.0 ICO图标制作工具中文便携版