将阿拉伯数字转化为中文大写是很简单很实用的功能,但由于0这个特殊数字的存在使得实现起来并非那么容易,实现这一功能的关键就是对0的正确处理。该程序是我几个月之前写成的,当时没有加注释,现在程序的实现细节基本忘光了,难以写出注释。只能凭自己模糊的印象大致部分地介绍一下思路和方法,当初思路中的细节已经无法回忆了,没有注释的代码大家只能将就看一下,能看懂最好看不懂也没办法
我当初的想法是现将输入的阿拉伯数字的每一位单独分离出来,按从低位到高位的顺序存放在线性链表里,然后从低位到高位扫描链表。将数字从低位至高位每四位分为一组,最左边的组可以不足位。用Re代表每组中某数字相对于该组最低位的偏移量,di代表每组中最低起始位从数字最低位数起的的位数,从低位至高位从1起以4为间隔依次增大。用mark表示前一位是否为0,用sign表示某数右边低位部分是否全为0,flag表示每组中某数右边在该组中的低位部分是否全为0。程序中用字符型二维数组存放中文大写数字单位,并用三个函数分别完成单位阿拉伯数字到中文大写数字,每组内的数字单位到中文大写,以及每组的最低起始位的数字单位到中文大写的转化
程序的主体部分就是用循环结构从左到右扫描存放数字各位的线性表,扫描过程中把转化出的中文大写数字按由高位至低位的顺序插入另一个链表,扫描完毕后新链表中存放的就是转换结果,可以直接输出。
至于中文大写形式向阿拉伯数字的转换,暂且一起贴上代码,有空补上注释
代码如下:
copy.h文件内容为
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <algorithm>
using namespace std;
void Num(list<string>& p1, const vector<string>& N, const size_t& wei) //将wei表示的阿拉伯数字转化为中文大写
{
p1.push_back(N[wei]);
}
void Re(list<string>& p1, const vector<string>& R, const size_t& re) //将re表示的组内数字单位转换为中文大写
{
p1.push_back(R[re - 1]);
}
void Di(list<string>& p1, const vector<string>& D, const size_t& di, const size_t& div) //将di表示的每组的最低起始位的数字单位转换为中文大写
{
if (di != 3)
p1.push_back(D[di - 1]);
for (size_t i = 1; i <= div; ++i)
p1.push_back(D[2]);
}
void addNum(list<list<string>>& output, const vector<string>& N, const size_t& wei)
{
list<string> temp;
Num(temp, N, wei);
output.insert(output.begin(), temp);
}
void addRe(list<list<string>>& output, const vector<string>& R, const size_t& re)
{
list<string> temp;
Re(temp, R, re);
output.insert(output.begin(), temp);
}
void addDi(list<list<string>>& output, const vector<string>& D, const size_t& di, const size_t& div)
{
list<string> temp;
Di(temp, D, di, div);
output.insert(output.begin(), temp);
}
unsigned long long computeZeroNum(map<string, size_t>& map_to_bit_number, const string& pre_group_order, const string& pre_num_order, const string& cur_num_order, const string& group_order
, const unsigned long long& pre_zhao_num, const unsigned long long& zhao_numn)
{
unsigned long long t = map_to_bit_number[group_order];
t += zhao_numn * map_to_bit_number["兆"];
t += map_to_bit_number[cur_num_order];
t -= map_to_bit_number[pre_group_order];
t -= pre_zhao_num * map_to_bit_number["兆"];
if (pre_num_order != "$")
t -= map_to_bit_number[pre_num_order] + 1;
return t;
}
const string& getNext(list<list<string>>::const_reverse_iterator& out, list<string>::const_reverse_iterator& in, const list<list<string>>& output, const list<string>& run)
{
const string& next = *in;
++in;
if (in == run.crend())
{
++out;
if (out != output.crend())
in = out->crbegin();
}
return next;
}
int main()
{
string t = "1000567008986000";
bool sign, flag, mark;
size_t re, di, div;
vector<string> N = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; //用字符串数组存放中文大写数字和单位
vector<string> R = { "拾", "佰", "仟" };
vector<string> D = { "万", "亿", "兆" };
//cout << "please input the number which you want to convert" <<endl;
//cin >> t; //输入要转换的阿拉伯数字
vector<int> number(t.size());
list<list<string>> output;
for (size_t i = t.size(), j = 0; i > 0;)
number[j++] = static_cast<int>(t[--i] - 48); //将输入的阿拉伯数字的各位分离,按从低位至高位的顺序从左至右存放在vector中
sign = false;
flag = false;
bool first_is_zero;
re = 0;
di = 0;
div = 0;
for (size_t wei = 0; wei < number.size(); ++wei) //从左到右扫描链表,进行到中文大写的转化,转换结果存放在ouput类型的链表中
{
if (number[wei] == 0)
{
if (re == 3)
{
first_is_zero = true;
}
mark = false;
}
else
{
if (sign == false)
{
if (di != 0)
addDi(output, D, di, div);
}
else
{
if (flag)
{
if (mark == false)
addNum(output, N, 0);
if (re == 0)
addDi(output, D, di, div);
}
else
{
if (first_is_zero)
addNum(output, N, 0);
addDi(output, D, di, div);
}
}
if (re != 0)
{
addRe(output, R, re);
if (re == 3)
{
first_is_zero = false;
}
}
addNum(output, N, number[wei]);
flag = true;
sign = true;
mark = true;
}
if (re == 0)
++re;
else
{
re = (re + 1) % 4;
if (re == 0)
{
flag = false;
++di;
if (di == 4)
di = 1;
else if (di == 3)
++div;
}
}
}
cout << t << "对应的中文大写形式为:";
for (const auto& run : output)
{
for (const auto& go : run)
cout << go;
}
cout << endl;
map<string, size_t> map_to_bit_number;
map_to_bit_number.insert(make_pair("", 0));
map_to_bit_number.insert(make_pair("拾", 1));
map_to_bit_number.insert(make_pair("佰", 2));
map_to_bit_number.insert(make_pair("仟", 3));
map_to_bit_number.insert(make_pair("万", 4));
map_to_bit_number.insert(make_pair("亿", 8));
map_to_bit_number.insert(make_pair("兆", 12));
map<string, char> num_to_char;
num_to_char.insert(make_pair("零", '0'));
num_to_char.insert(make_pair("壹", '1'));
num_to_char.insert(make_pair("贰", '2'));
num_to_char.insert(make_pair("叁", '3'));
num_to_char.insert(make_pair("肆", '4'));
num_to_char.insert(make_pair("伍", '5'));
num_to_char.insert(make_pair("陆", '6'));
num_to_char.insert(make_pair("柒", '7'));
num_to_char.insert(make_pair("捌", '8'));
num_to_char.insert(make_pair("玖", '9'));
string pre_num_order;
string cur_num_order;
string group_order;
unsigned long long pre_zhao_num = 0;
unsigned long long zhao_numn = 0;
string pre_group_order;
string result;
bool pre_is_zero = false;
list<list<string>>::const_reverse_iterator out = output.crbegin();
list<string>::const_reverse_iterator in = out->crbegin();
if (output.size() == 1 && out->size() == 1)
{
result.append(1, num_to_char[*in]);
}
else
{
if (*in == "壹" || *in == "贰" || *in == "叁" || *in == "肆" || *in == "伍"
|| *in == "陆" || *in == "柒" || *in == "捌" || *in == "玖")
{
result.append(1, num_to_char[*in]);
}
else
{
if (*in == "万" || *in == "亿" || *in == "兆")
{
pre_num_order = cur_num_order = "$";
if (*in == "兆")
{
++zhao_numn;
}
else
{
group_order = *in;
}
}
else
{
pre_num_order = "$";
cur_num_order = *in;
}
}
while (true)
{
const string& cur = getNext(out, in, output, *out);
if (out == output.crend())
break;
if (*in == "零")
{
pre_zhao_num = zhao_numn;
pre_group_order = group_order;
pre_is_zero = true;
}
else
{
if (*in == "拾" || *in == "佰" || *in == "仟")
{
pre_num_order = cur_num_order;
cur_num_order = *in;
}
else if (*in == "万" || *in == "亿" || *in == "兆")
{
if (cur != "万" && cur != "亿" && cur != "兆")
{
pre_zhao_num = zhao_numn;
pre_group_order = group_order;
zhao_numn = 0;
}
if (*in == "兆")
{
group_order = "";
++zhao_numn;
}
else
group_order = *in;
}
else
{
if (cur == "万" || cur == "亿" || cur == "兆")
{
pre_num_order = cur_num_order;
cur_num_order = "";
}
if (pre_is_zero || pre_num_order == "$")
{
if (pre_is_zero)
{
if (pre_zhao_num == zhao_numn && pre_group_order == group_order)
{
result.append(map_to_bit_number[cur_num_order] - map_to_bit_number[pre_num_order] - 1, '0');
result.append(1, num_to_char[*in]);
pre_is_zero = false;
continue;
}
}
result.append(computeZeroNum(map_to_bit_number, pre_group_order, pre_num_order, cur_num_order, group_order, pre_zhao_num, zhao_numn), '0');
if (pre_is_zero == false)
{
pre_num_order = cur_num_order;
}
}
else
{
if (pre_num_order == "仟")
result.append(map_to_bit_number[cur_num_order], '0');
}
result.append(1, num_to_char[*in]);
pre_is_zero = false;
}
}
}
}
reverse(result.begin(), result.end());
cout << "中文大写";
for (const auto& run : output)
{
for (const auto& go : run)
cout << go;
}
cout << "对应的阿拉伯数字为:" << endl;
cout << result << endl;
if (result == t)
{
cout << "转换所得阿拉伯数字和原始数字相同" << endl;
}
else
{
cout << "错误:转换所得数字和原始数字不同" << endl;
}
return 0;
}
cpp主程序文件内容为
#define TEST_ALL
#ifndef TEST_ALL
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <list>
#include <algorithm>
using namespace std;
void Num(list<string>& p1, const vector<string>& N, const size_t &wei) //将wei表示的阿拉伯数字转化为中文大写
{
p1.push_back(N[wei]);
}
void Re(list<string>& p1, const vector<string>& R, const size_t &re) //将re表示的组内数字单位转换为中文大写
{
p1.push_back(R[re - 1]);
}
void Di(list<string>& p1, const vector<string>& D, const size_t &di, const size_t &div) //将di表示的每组的最低起始位的数字单位转换为中文大写
{
if (di != 3)
p1.push_back(D[di - 1]);
for (size_t i = 1; i <= div; ++i)
p1.push_back(D[2]);
}
void addNum(list<list<string>> &output, const vector<string>& N, const size_t &wei)
{
list<string> temp;
Num(temp, N, wei);
output.insert(output.begin(), temp);
}
void addRe(list<list<string>>& output, const vector<string>& R, const size_t& re)
{
list<string> temp;
Re(temp, R, re);
output.insert(output.begin(), temp);
}
void addDi(list<list<string>>& output, const vector<string>& D, const size_t& di, const size_t& div)
{
list<string> temp;
Di(temp, D, di, div);
output.insert(output.begin(), temp);
}
unsigned long long computeZeroNum(map<string, size_t>& map_to_bit_number, const string& pre_group_order, const string& pre_num_order, const string& cur_num_order, const string& group_order
, const unsigned long long& pre_zhao_num, const unsigned long long& zhao_numn)
{
unsigned long long t = map_to_bit_number[group_order];
t += zhao_numn * map_to_bit_number["兆"];
t += map_to_bit_number[cur_num_order];
t -= map_to_bit_number[pre_group_order];
t -= pre_zhao_num * map_to_bit_number["兆"];
if (pre_num_order != "$")
t -= map_to_bit_number[pre_num_order] + 1;
return t;
}
const string& getNext(list<list<string>>::const_reverse_iterator& out, list<string>::const_reverse_iterator &in, const list<list<string>>& output, const list<string>& run)
{
const string& next = *in;
++in;
if (in == run.crend())
{
++out;
if (out != output.crend())
in = out->crbegin();
}
return next;
}
void ArabicToCap(const vector<int> &number, list<list<string>> &output)
{
if (number.size() == 1 && number[0] == 0)
{
output.push_back(list<string>(1, "零"));
}
bool sign, flag, mark;
size_t re, di, div;
vector<string> N = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; //用字符串数组存放中文大写数字和单位
vector<string> R = { "拾", "佰", "仟" };
vector<string> D = { "万", "亿", "兆" };
sign = false;
flag = false;
bool first_is_zero;
re = 0;
di = 0;
div = 0;
for (size_t wei = 0; wei < number.size(); ++wei) //从左到右扫描链表,进行到中文大写的转化,转换结果存放在ouput类型的链表中
{
if (number[wei] == 0)
{
if (re == 3)
{
first_is_zero = true;
}
mark = false;
}
else
{
if (sign == false)
{
if (di != 0)
addDi(output, D, di, div);
}
else
{
if (flag)
{
if (mark == false)
addNum(output, N, 0);
if (re == 0)
addDi(output, D, di, div);
}
else
{
if (first_is_zero)
addNum(output, N, 0);
addDi(output, D, di, div);
}
}
if (re != 0)
{
addRe(output, R, re);
if (re == 3)
{
first_is_zero = false;
}
}
addNum(output, N, number[wei]);
flag = true;
sign = true;
mark = true;
}
if (re == 0)
++re;
else
{
re = (re + 1) % 4;
if (re == 0)
{
flag = false;
++di;
if (di == 4)
di = 1;
else if (di == 3)
++div;
}
}
}
}
void CapToArabic(string &result, list<list<string>>& output)
{
map<string, size_t> map_to_bit_number;
map_to_bit_number.insert(make_pair("", 0));
map_to_bit_number.insert(make_pair("拾", 1));
map_to_bit_number.insert(make_pair("佰", 2));
map_to_bit_number.insert(make_pair("仟", 3));
map_to_bit_number.insert(make_pair("万", 4));
map_to_bit_number.insert(make_pair("亿", 8));
map_to_bit_number.insert(make_pair("兆", 12));
map<string, char> num_to_char;
num_to_char.insert(make_pair("零", '0'));
num_to_char.insert(make_pair("壹", '1'));
num_to_char.insert(make_pair("贰", '2'));
num_to_char.insert(make_pair("叁", '3'));
num_to_char.insert(make_pair("肆", '4'));
num_to_char.insert(make_pair("伍", '5'));
num_to_char.insert(make_pair("陆", '6'));
num_to_char.insert(make_pair("柒", '7'));
num_to_char.insert(make_pair("捌", '8'));
num_to_char.insert(make_pair("玖", '9'));
string pre_num_order;
string cur_num_order;
string group_order;
unsigned long long pre_zhao_num = 0;
unsigned long long zhao_numn = 0;
string pre_group_order;
bool pre_is_zero = false;
list<list<string>>::const_reverse_iterator out = output.crbegin();
list<string>::const_reverse_iterator in = out->crbegin();
if (output.size() == 1 && out->size() == 1)
{
result.append(1, num_to_char[*in]);
}
else
{
if (*in == "壹" || *in == "贰" || *in == "叁" || *in == "肆" || *in == "伍"
|| *in == "陆" || *in == "柒" || *in == "捌" || *in == "玖")
{
result.append(1, num_to_char[*in]);
}
else
{
if (*in == "万" || *in == "亿" || *in == "兆")
{
pre_num_order = cur_num_order = "$";
if (*in == "兆")
{
++zhao_numn;
}
else
{
group_order = *in;
}
}
else
{
pre_num_order = "$";
cur_num_order = *in;
}
}
while (true)
{
const string& cur = getNext(out, in, output, *out);
if (out == output.crend())
break;
if (*in == "零")
{
pre_zhao_num = zhao_numn;
pre_group_order = group_order;
pre_is_zero = true;
}
else
{
if (*in == "拾" || *in == "佰" || *in == "仟")
{
pre_num_order = cur_num_order;
cur_num_order = *in;
}
else if (*in == "万" || *in == "亿" || *in == "兆")
{
if (cur != "万" && cur != "亿" && cur != "兆")
{
pre_zhao_num = zhao_numn;
pre_group_order = group_order;
zhao_numn = 0;
}
if (*in == "兆")
{
group_order = "";
++zhao_numn;
}
else
group_order = *in;
}
else
{
if (cur == "万" || cur == "亿" || cur == "兆")
{
pre_num_order = cur_num_order;
cur_num_order = "";
}
if (pre_is_zero || pre_num_order == "$")
{
if (pre_is_zero)
{
if (pre_zhao_num == zhao_numn && pre_group_order == group_order)
{
result.append(map_to_bit_number[cur_num_order] - map_to_bit_number[pre_num_order] - 1, '0');
result.append(1, num_to_char[*in]);
pre_is_zero = false;
continue;
}
}
result.append(computeZeroNum(map_to_bit_number, pre_group_order, pre_num_order, cur_num_order, group_order, pre_zhao_num, zhao_numn), '0');
if (pre_is_zero == false)
{
pre_num_order = cur_num_order;
}
}
else
{
if (pre_num_order == "仟")
result.append(map_to_bit_number[cur_num_order], '0');
}
result.append(1, num_to_char[*in]);
pre_is_zero = false;
}
}
}
}
}
void string_to_int_separate(vector<int> &number, const string &t)
{
for (size_t i = t.size(), j = 0; i > 0;)
number[j++] = static_cast<int>(t[--i] - 48); //将输入的阿拉伯数字的各位分离,按从低位至高位的顺序从左至右存放在vector中
}
void next_number(vector<int> &number)
{
vector<int>::iterator it_run = number.begin();
for ( ; it_run != number.end(); ++it_run)
{
if (0 <= *it_run && *it_run < 9)
{
++* it_run;
break;
}
else
*it_run = 0;
}
if (it_run == number.end())
number.push_back(1);
}
bool lessequal(const vector<int>& left, const vector<int>& right)
{
if (left.size() < right.size())
return true;
if (left.size() > right.size())
return false;
for (vector<int>::const_reverse_iterator p_left = left.crbegin(), p_right = right.crbegin(); p_left != left.crend(); ++p_left, ++p_right)
{
if (*p_left < *p_right)
return true;
if (*p_left > *p_right)
return false;
}
return true;
}
int main()
{
string end = "1000000";
string start = "100001";
//cout << "please input the number which you want to convert" <<endl;
//cin >> t; //输入要转换的阿拉伯数字
vector<int> number_end(end.size());
vector<int> number_start(start.size());
string_to_int_separate(number_end ,end);
string_to_int_separate(number_start, start);
for (; lessequal(number_start, number_end) == true; next_number(number_start))
{
list<list<string>> output;
ArabicToCap(number_start, output);
for (vector<int>::const_reverse_iterator run = number_start.crbegin(); run != number_start.crend(); ++run)
{
cout << *run;
}
cout << "对应的中文大写形式为:" << endl;
for (const auto& run : output)
{
for (const auto& go : run)
cout << go;
}
cout << endl;
string result;
CapToArabic(result, output);
if (result.size() != number_start.size())
{
cout << "error:该中文大写形式转换而得的阿拉伯数字和原数字不同!" << endl;
exit(-1);
}
for (size_t com = 0; com < result.size(); ++com)
{
if (result[com] - 48 != number_start[com])
{
cout << "error:该中文大写形式转换而得的阿拉伯数字和原数字不同!" << endl;
exit(-1);
}
}
cout << "中文大写";
for (const auto& run : output)
{
for (const auto& go : run)
cout << go;
}
cout << "对应的阿拉伯数字为:" << endl;
for (string::const_reverse_iterator run = result.crbegin(); run != result.crend(); ++run)
cout << *run;
cout << endl;
}
return 0;
}
#else
#include "copy.h"
#endif
在cpp文件中定义宏TEST_ALL,则编译copy.h文件,运行的是没有循环测试的版本,若不定义宏则运行的是循环测试版本