Advertisement
Ebola

C++ Number/Chinese Numerals Conversion

Mar 12th, 2014
2,038
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.60 KB | None | 0 0
  1. // C++98
  2. #include <iostream>
  3. #include <fstream>
  4. using namespace std;
  5.  
  6. /**
  7.  * Files
  8.  */
  9. #define FILE_IN     "num.txt"
  10. #define FILE_OUT    "spell.txt"
  11.  
  12. /**
  13.  * Constants
  14.  */
  15. #define CHAR_ZERO   CHAR_NUM[0]
  16. #define LEN_NUM     10
  17. #define LEN_SI      3
  18. #define LEN_BI      4
  19.  
  20. const int MAX_LEN = 20;
  21. const int INTERVAL = 4;
  22.  
  23. // chinese numerals
  24. const string CHAR_NUM[] = {"零", "ㄧ", "二", "三", "四", "五", "六", "七",
  25. "八", "九"};
  26. // small interval
  27. const string CHAR_SI[] = {"十", "百", "千"};
  28. // big interval
  29. const string CHAR_BI[] = {"萬", "億", "兆", "京"};
  30.  
  31. /**
  32.  * Prototypes
  33.  */
  34. typedef string (*FUNC)(string );
  35.  
  36. string num2spell(string );
  37. string spell2num(string );
  38. bool validate(FUNC , bool verbose = false);
  39.  
  40. int main() {
  41.     // 驗證正確性
  42.     //validate(num2spell, true);
  43.  
  44.     // 數字 -> 中文數字
  45.     while (1) {
  46.         string num;
  47.  
  48.         cout << "輸入整數: ";
  49.         cin >> num;
  50.  
  51.         try {
  52.             cout << num2spell(num) << endl;
  53.         } catch (const string &str) {
  54.             cout << "Error: " << str << endl;
  55.         }
  56.     }
  57.  
  58.     // 中文數字 -> 數字
  59. //    while (1) {
  60. //        string num;
  61. //
  62. //        cout << "輸入中文數字: ";
  63. //        cin >> num;
  64. //
  65. //        cout << spell2num(num) << endl;
  66. //    }
  67.  
  68.     return 0;
  69. }
  70.  
  71. /** \brief Convert a number to Chinsese numerals
  72.  * \param string num    A non-negative integer
  73.  * \return string   Chinese numerals
  74.  */
  75. string num2spell(string num) {
  76.     size_t sz = num.size(), revi, si, bi;
  77.     bool lastZero = false,
  78.         lastNonZero = false;
  79.     int val;
  80.     string ret;
  81.  
  82.     // limit the size
  83.     if (sz > MAX_LEN) {
  84.         throw string("Exceeded max length");
  85.     }
  86.  
  87.     // special numbers
  88.     if ("0" == num) {
  89.         return CHAR_ZERO;
  90.     }
  91.  
  92.     for (size_t i = 0; i != sz; ++i) {
  93.         revi = (sz - 1) - i;
  94.         bi = revi / INTERVAL;
  95.         si = revi % INTERVAL;
  96.  
  97.         val = num[i] - '0';
  98.  
  99.         if (0 != val) {
  100.             if (lastZero) {
  101.                 // append a zero
  102.                 ret += CHAR_ZERO;
  103.             }
  104.  
  105.             // append a numeral
  106.             if (1 == val && 1 == si) {
  107.                 // ten
  108.                 if (0 != i) {
  109.                     ret += CHAR_NUM[1];
  110.                 }
  111.             } else {
  112.                 ret += CHAR_NUM[val];
  113.             }
  114.  
  115.             if (0 != si) {
  116.                 // append a small interval char
  117.                 ret += CHAR_SI[si - 1];
  118.             }
  119.  
  120.             lastNonZero = true;
  121.             lastZero = false;
  122.         } else {
  123.             lastZero = true;
  124.         }
  125.  
  126.         if (0 == si && 0 != bi) {
  127.             if (lastNonZero) {
  128.                 // append a big interval char
  129.                 ret += CHAR_BI[bi - 1];
  130.  
  131.                 // uncomment this to hide zero at rear of the big interval
  132.                 // followed up by another one
  133.                 //lastZero = false;
  134.             }
  135.  
  136.             lastNonZero = false;
  137.         }
  138.     }
  139.  
  140.     return ret;
  141. }
  142.  
  143. /** \brief Convert a Chinese numerals to number
  144.  * \param string spell  A Chinese numerals
  145.  * \return string   Number as string
  146.  */
  147. string spell2num(string spell) {
  148.     int val = -1, siNum[INTERVAL] = {0}, biPower = 0, lastBiPower = 0;
  149.     bool isNum, isSi, isBi, valProc, firstNonZero = false;
  150.     string ch;
  151.     string ret;
  152.  
  153.     if (CHAR_ZERO == spell) {
  154.         return "0";
  155.     }
  156.  
  157.     for (size_t i = 0; i != spell.size(); i += 2) {
  158.         ch = spell.substr(i, 2);
  159.  
  160.         // numeral
  161.         isNum = false;
  162.         for (int j = 0; j != LEN_NUM; ++j) {
  163.             if (ch == CHAR_NUM[j]) {
  164.                 val = j;
  165.  
  166.                 valProc = false;
  167.                 isNum = true;
  168.             }
  169.         }
  170.  
  171.         // small interval
  172.         isSi = false;
  173.         if ( !isNum) {
  174.             for (int si = 0; si != LEN_SI; ++si) {
  175.                 if (ch == CHAR_SI[si]) {
  176.                     // ten
  177.                     if (-1 == val) {
  178.                         val = 1;
  179.                     }
  180.  
  181.                     siNum[si + 1] = val;
  182.                     valProc = true;
  183.  
  184.                     isSi = true;
  185.                 }
  186.             }
  187.         }
  188.  
  189.         // big interval
  190.         isBi = false;
  191.         if ( !isSi) {
  192.             for (int bi = 0; bi != LEN_BI; ++bi) {
  193.                 if (ch == CHAR_BI[bi]) {
  194.                     lastBiPower = biPower;
  195.                     biPower = (bi + 1) * INTERVAL;
  196.  
  197.                     lastBiPower -= INTERVAL + biPower;
  198.  
  199.                     while (lastBiPower > 0) {
  200.                         ret += '0';
  201.                         --lastBiPower;
  202.                     }
  203.  
  204.                     if ( !valProc) {
  205.                         siNum[0] = val;
  206.                     }
  207.  
  208.                     // append small interval digits
  209.                     for (int si = INTERVAL - 1; -1 != si; --si) {
  210.                         if (0 != siNum[si]) {
  211.                             firstNonZero = true;
  212.                         }
  213.  
  214.                         if (firstNonZero) {
  215.                             ret += (siNum[si] + '0');
  216.                         }
  217.  
  218.                         siNum[si] = 0;
  219.                     }
  220.  
  221.                     isBi = true;
  222.                 }
  223.             }
  224.         }
  225.     }
  226.  
  227.     if (isBi) {
  228.         while (0 != biPower) {
  229.             ret += '0';
  230.             --biPower;
  231.         }
  232.     } else {
  233.         lastBiPower = biPower - INTERVAL;
  234.  
  235.         while (lastBiPower > 0) {
  236.             ret += '0';
  237.             --lastBiPower;
  238.         }
  239.  
  240.         if ( !valProc) {
  241.             siNum[0] = val;
  242.         }
  243.  
  244.         for (int si = INTERVAL - 1; -1 != si; --si) {
  245.             if (0 != siNum[si]) {
  246.                 firstNonZero = true;
  247.             }
  248.  
  249.             if (firstNonZero) {
  250.                 ret += (siNum[si] + '0');
  251.             }
  252.         }
  253.     }
  254.  
  255.     return ret;
  256. }
  257.  
  258. bool validate(FUNC func, bool verbose) {
  259.     fstream fsIn(FILE_IN, fstream::in),
  260.             fsOut(FILE_OUT, fstream::in);
  261.     string computed, lineIn, lineOut;
  262.     bool ret = true;
  263.     int lineNum = 1;
  264.  
  265.     while (getline(fsIn, lineIn) &&
  266.            getline(fsOut, lineOut)) {
  267.         computed = func(lineIn);
  268.  
  269.         if (computed != lineOut) {
  270.             if (verbose) {
  271.                 cout << "Conflicting Result at line " << lineNum << endl <<
  272.                     "in      : " << lineIn << endl <<
  273.                     "expected: " << lineOut << endl <<
  274.                     "result  : " << computed << endl;
  275.             }
  276.  
  277.             ret = false;
  278.             break;
  279.         }
  280.  
  281.         ++lineNum;
  282.     }
  283.  
  284.     return ret;
  285. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement