將使用者輸入的小寫貨幣形式轉換為規範的大寫貨幣形式
阿新 • • 發佈:2018-12-30
需求:寫一個程式,實現貨幣的小寫轉換成大寫形式(符合習慣)
例如:輸入123,456,789.02返回相應的大寫 壹億貳仟叄佰肆拾伍萬陸仟柒佰捌拾玖元零貳分;
輸入1000,返回壹仟元整;
#include "stdafx.h" #include "math.h" #include <string> #include <iostream> using namespace std; #define INTEGER_ONLY 1 // 表示整數部分的標誌 #define DECIMAL_ONLY 2 // 表示小數部分的標誌 /* 需求:寫一個程式,實現貨幣的小寫轉換成大寫形式(符合習慣) 例如:輸入123,456,789.02返回相應的大寫 壹億貳仟叄佰肆拾伍萬陸仟柒佰捌拾玖元零貳分; 輸入1000,返回壹仟元整; */ /* string類的成員函式說明: 1) 原型:double atof(const char *nptr); 功 能: 把字串轉換成浮點數 名字來源:ascii to floating point numbers 的縮寫 2) 原型:char *fcvt(double value, int ndigit, int *decpt, int *sign); 功能: 把一個浮點數轉換為字串 引數: value:要轉換的浮點數, 輸入引數 ndigit:小數點後面的位數, 輸入引數 decpt:表示小數點的位置, 輸出引數 sign:表示符號,0為正數,1為負數,輸出引數 3) 原型:string replace(string src, length, replacement); 功能:替換 src 字串中從第一個匹配src的字串索引開始的 length 個字元為 replacement 字串 輸出:替換後的string型別 */ /* ********************************************************************* 功能:獲得使用者輸入的string 輸入:無 輸出:string型別 ********************************************************************* */ string getNum() { string s; cout << "請輸入一個數字(精確到小數點後兩位):"<< endl; cin >> s; return s; } /* ********************************************************************* 功能:將輸入的數字字串轉換為double型別,並檢查輸入的有效性(為正數) 輸入:string型別 輸出:bool型別:true,正數; false,負數 ********************************************************************* */ bool checkNum(string& str) { // 檢查輸入非數字的字元 bool flag = true; double d = atof(str.c_str()); //把字串轉換成浮點數 if(d < 0) flag = false; return flag; } /* ********************************************************************* 功能:將這個數轉換成 double 型別,並對其進行四捨五入操作 輸入:string型別 輸出:string型別 ********************************************************************* */ string roundString(string s) { double d = atof(s.c_str()); /* 轉換成 double 型別 */ int dec, sign; /* fcvt()函式輸出引數 */ s = fcvt(d, 2, &dec, &sign); /* 將這個數進行四捨五入,保留到小數點後兩位; 當這個數轉換成字串以後不會顯示小數點, 並且會以四捨五入的形式只保留小數點後兩位 */ if(s.length() > 15) /* 規定數值的最大長度只能是15位(到萬億位) */ { cout << "提示:輸入資料過大!(整數部分最多13位!)"<< endl; return ""; } return s; } /* ********************************************************************* 功能:將這個數轉換成 double 型別,並對其進行四捨五入操作 輸入:標誌位flag,string型別 輸出:string型別 ********************************************************************* */ string formatChinese(int flag, string s) { int sLength = s.length(); string bigLetter[] = {"零","壹","貳","叄","肆","伍","陸","柒","捌","玖"}; /* 貨幣大寫形式 */ string small[] = {"分", "角"}; /*分位到角位 */ string unit[] = {"元", "拾", "佰", "仟", /*個位到仟位 */ "萬", "拾", "佰", "仟", /*拾萬位到仟萬位 */ "億", "拾", "佰", "仟", "萬"}; /*億位到萬億位 */ string newS = ""; /* 用來存放轉換後的新字串 */ for(int i = 0; i < sLength; i ++) /* 逐位替換為中文大寫形式 */ { if(flag == INTEGER_ONLY) /* 轉換整數部分為中文大寫形式(帶單位) */ { newS = newS + bigLetter[s.at(i) - '0'] + unit[sLength-1 - i]; } else if(flag == DECIMAL_ONLY) /* 轉換小數部分(帶單位) */ { newS = newS + bigLetter[s.at(i) - '0'] + small[sLength-1 - i]; } } return newS; } /* ********************************************************************* 功能:將這個數分割成整數部分和小數部分,轉換成對應的貨幣的中文大寫形式 輸入:string型別 輸出:string型別 ********************************************************************* */ string splitNum(string s) { if("" == s) /* 如果傳入的是空串則繼續返回空串 */ { return ""; } string IntegerOnly = s.substr(0, s.size() - 2); /* 擷取輸入數字的整數部分 */ string IntegerPart = formatChinese(INTEGER_ONLY, IntegerOnly); string DecimalOnly = s.substr(s.size() - 2, s.size()); /* 擷取這個數的小數部分 */ string DecimalPart = formatChinese(DECIMAL_ONLY, DecimalOnly); string newS = IntegerPart + DecimalPart; /* 把轉換好了的整數部分和小數部... ...分重新拼湊一個新的字串 */ return newS; } /* ********************************************************************* 功能:將非規範性貨幣中文大寫表達形式轉換成規範的貨幣中文大寫形式 輸入:string型別(source),string型別(搜尋字串),string型別(替代字串) 輸出:string型別 ********************************************************************* */ string replaceAll(string src, string regex, string replacement) { int length = regex.length(); while(src.find(regex) < src.length()) { src.replace(src.find(regex), length, replacement); } return src; } /* ********************************************************************* 功能:將非規範性貨幣中文大寫表達形式轉換成規範的貨幣中文大寫形式 輸入:string型別 輸出:string型別 ********************************************************************* */ string cleanZero(string s) { if("" == s) /* 如果傳入的是空串則返回空串 */ { return ""; } string regex1[] = {"零仟", "零佰", "零拾"}; string regex2[] = {"零億", "零萬", "零元"}; string regex3[] = {"億", "萬", "元"}; string regex4[] = {"零角", "零分"}; // 字串中存在多個'零'在一起的時候只讀出一個'零',並省略多餘的單位 for(int i = 0; i < 3; i ++){ /* case1: 把 "零仟", 零佰","零拾"... ...等字串替換成一個"零" */ s = replaceAll(s, regex1[i], "零"); } s = replaceAll(s, "零零零", "零"); s = replaceAll(s, "零零", "零"); /* 當第一輪轉換過後有可能有很多個零疊在一起, ...要把很多個重複的零變成一個零 */ for(int i = 0; i < 3; i ++) /* 第二輪轉換考慮 "零億","零萬","零元"等情況 */ { s = replaceAll(s, regex2[i], regex3[i]); /* "億","萬","元"這些單位有些情況是... ...不能省的,需要保留下來 */ } s = replaceAll(s,"零角零分","整"); /* 考慮沒有小數的情況 */ for(int i = 0; i < 2; i ++) { /* 第三輪轉換把"零角","零分"字串省略 */ s = replaceAll(s, regex4[i], ""); } s = replaceAll(s, "億萬", "億"); /* 當"萬"到"億"之間全部是"零"的時候, ...忽略"億萬"單位,只保留一個"億" */ return s; } int _tmain(int argc, _TCHAR* argv[]) { cout << "\n------------將數字轉換成中文金額的大寫形式(C++)------------\n" << endl; for(;;) { string s = getNum(); if(checkNum(s)) /* 檢查使用者輸入是否有效 */ { s = roundString(s); /* 用四捨五入規範浮點數,保留兩位 */ s = splitNum(s); /* 把浮點數分割成小數和整數部分,分別表示為... ...貨幣的大寫形式 */ s = cleanZero(s); /* 把貨幣的大寫形式規範化 */ cout << "轉換成中文後為:" << s << endl; } else { cout << "非法輸入,程式即將退出" << endl; } cout << "\n--------------------------------------------------------------" << endl; } return 0; }
輸出結果: