背景:在一些比较秘密的场景中,为了传输一些重要的数值串(例如美国新冠病毒实际死亡人数),相关人员往往将这些数据保存为字符串、数值以及各种符号混用的形式。在实际需要这些数据时,就通过提前定义好的方法将它们翻译回来。
相应的子程序:
[1] 计算n!
[2] 求最小公倍数和最大公约数
[3] 输入某雇员每周工作时间(以小时计)和每小时工资数,计算并输出其工资。(如果时间小于0或大于一周的总时间直接输出0)。若雇员每周工作小时超过60小时,则超过60小时的部分按原工资3倍的加班工资来计算,雇员每周工作小时超过40小时而不超过60小时的工资按原工资1.5倍的加班工资计算。
[4] 求组合数
[5] 已知公元1年1月1日是星期一,计算给定的日期是星期几
[6] 四则运算
明确需要覆盖的点:
[1] 使用子程序
[2] 面向对象编程
[3] 考虑异常
[4] 程序中全部输出都采用格式化输出
用C++或Python实现以下内容:
(1)从特定文本文件中读取一个特定格式字典(训练输入、循环、文件操作),包括①从数字到数值的对应,②从字母到数值的对应,③括号和计算符号不作转换(训练泛型)。
(2)再从一个文本文件中读取原始符号串,并实现将原始符号串根据字典进行必要的转换。注意,转换后的符号串需要用链表存储。(训练循环、指针、链表操作)
(3)针对转换后的符号串,按下列要求完成相应的计算,并用两侧各附有一个空格的计算结果替换原来的符号串。(训练参数子程序调用)
①对(a)形式,要求计算阶乘,并替换(计算阶乘,训练迭代和递归)
②对[a, b]形式的要替换为a和b的最小公倍数,对{a, b}形式的要替换为a和b的最大公约数(计算最小公倍数和最大公约数,训练变量交换)
③对<a, b>形式,要求计算员工周工资,其中a是工作小时数,b是每小时工资数,并替换(计算员工周工资,训练分支)
④对(a, b)形式,要求解从a个中挑选b个的组合数,并替换(计算组合数,训练迭代和递归)
⑤对(a,b,c)形式的要求解a年b月c日是周几,并用这个数值替换(计算星期数,训练分支、逻辑运算)
⑥四则运算,例如将读入的符号串(1+3+5)替换为9,注意可能出现嵌套的括号,例如(3/(1 +2))(训练删除链表以及简单的指针操作、递归、形参调用)
(4)再针对处理后的、由空格分隔的数据进行排序(训练排序处理)
(5)最后将排好序的数据,以格式化的形式存入文件。(训练循环、文件操作,格式化输出)
其中字典如下:
1 2
a 3
b 5
4 8
c 9
原始输入文本文件内容:
3 (5,b) a (4+6/(a+3)+1) 11 {44,16} 19 (10) <b, 100> 99 (c,a,2) 100 1000 [b,10]
替换后的内容:
3 (5,5) 3 (8+6/(3+3)+2) 11 {44,16} 19 (10) <5, 100> 99 (9,3,2) 100 1000 [5,10]
#include <iostream>
#include<fstream>
#include<string>
#include<list>
using namespace std;
int Cmultiple(int n1, int n2) //最小公倍数
{
int max = 0;
if (n1 != 0 && n2 != 0)
{
max = (n1 > n2) ? n1 : n2;
do
{
if (max % n1 == 0 && max % n2 == 0)
{
break;
}
else
max++;
} while (1);
}
return max;
}
int Cdivisor(int n1, int n2) //最大公约数
{
int min = 0;
if (n1 != 0 && n2 != 0)
{
min = (n1 < n2) ? n1 : n2;
do
{
if (n1 % min == 0 && n2 % min == 0)
{
break;
}
else
min--;
} while (1);
}
return min;
}
int Date(int year, int month, int day)
{
int week;
long totalday;
int monthday[12] = { 0,31,59,90,120,151,181,212,243,273,304,334 };
int monthdayLeap[12] = { 0,31,60,91,121,152,182,213,244,274,305,335 };
int weekname[7] = { 1,2,3,4,5,6,7 }; //星期几
totalday = (year - 1) * 365 + (year - 1) / 4 - (year - 1) / 100 + (year - 1) / 400;
if ((year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0))
{
totalday += monthdayLeap[month - 1];
}
else
{
totalday += monthday[month - 1];
}
totalday += day;
week = (totalday - 1) % 7;
return weekname[week];
}
int Combination(int n, int m)//组合数
{
long sum = 1;
for (int i = m + 1; i <= n; i++) sum *= i;
for (int i = 1; i <= n - m; i++) sum /= i;
return sum;
}
int Salary(int hour, double hoursalary)
{
double salary = 0;
if (hour < 0 || hour>168)
{
cout << "0" << endl;
}
else if (hour > 40 && hour < 60)
{
salary = 40 * hoursalary + (hour - 40) * hoursalary * 1.5;
}
else if (hour > 60)
{
salary = 40 * hoursalary + (hour - 40) * hoursalary * 3;
}
else
{
salary = hour * hoursalary;
}
return salary;
}
long Factorial(int a)
{
long sum = 1;
for (int i = 1;i < a + 1;i++)
{
sum *= i;
}
return sum;
}
char Dic(char& c)//转换
{
switch (c)
{
case '1':c = '2';break;
case 'a':c = '3';break;
case 'b':c = '5';break;
case '4':c = '8';break;
case 'c':c = '9';break;
default:break;
}
return c;
}
void Read()
{
ifstream ifs;
char ch;
int size = 0;
string str;
list<int>L;
int i = 0;
ifs.open("input.txt", ios::in);
while (ifs.get(ch))
{
if (ch == '<')
{
str += ch;
while (ch != '>')
{
ifs.get(ch);
if (ch == ' ') continue;
str += ch;
}
}
else
str += ch;
i++;
}
ifs.close();
int len = str.length();
string newstr;
for (int i = 0;i < len;i++)
{
if ('9' >= str[i] && str[i] >= '0')
{
while ('9' >= str[i] && str[i] >= '0')
{
newstr += str[i];
i++;
}
newstr += str[i];
}
else
{
newstr += Dic(str[i]);
}
}
ofstream ofs;//写入新文件
ofs.open("temp.txt", ios::out);
ofs << newstr << endl;
ofs.close();
ifstream ifs1;//读新文件
ifs1.open("temp.txt", ios::in);
char ch1;
while (ifs1.get(ch1))
{
if ('9' >= ch1 && ch1 >= '0')
{
int a = 0, b = 0, c = 0;
while (ch1 != ' ')
{
if ('9' >= ch1 && ch1 >= '0')
{
a = ch1 - '0';
b *= 10;
b += a;
}
else
{
ifs1.get(ch1);continue;
}
ifs1.get(ch1);
}
L.push_back(b);
}
else if (ch1 == '{')
{
int a = 0, b = 0, c = 0;
while (ch1 != '}')
{
if ('9' >= ch1 && ch1 >= '0')
{
a = ch1 - '0';
b *= 10;
b += a;
}
else
{
c = b; b = 0; ifs1.get(ch1);continue; //c是第一个数据
}
ifs1.get(ch1);
}
L.push_back(Cdivisor(c, b));
}
else if (ch1 == '<')
{
int a = 0, b = 0, c = 0;
while (ch1 != '>')
{
if ('9' >= ch1 && ch1 >= '0')
{
a = ch1 - '0';
b *= 10;
b += a;
}
else
{
c = b; b = 0;ifs1.get(ch1);continue; //c是第一个数据
}
ifs1.get(ch1);
}
L.push_back(Salary(c, b));
}
else if (ch1 == '[')
{
int a = 0, b = 0, c = 0;
while (ch1 != ']')
{
if ('9' >= ch1 && ch1 >= '0')
{
a = ch1 - '0';
b *= 10;
b += a;
}
else
{
c = b; b = 0;ifs1.get(ch1);continue; //c是第一个数据
}
ifs1.get(ch1);
}
L.push_back(Cmultiple(c, b));
}
else if (ch1 == '(')
{
int n = 0, m = 0, times = 0;
int a = 0, b = 0, c = 0, d = 0, f = 0;
while (ch1 != ' ')
{
times++; //记录读了多少次——读了多少字节
ifs1.get(ch1);
if (ch1 == ',') n++;
else if (ch1 == '(') m++;
}
ifs1.seekg(-times, ios::cur); //移动文件读指针回原先位置'('。
ifs1.get(ch1); //读取e为值
if (m != 0)
{
while (ch1 != ' ')
{
ifs1.get(ch1);
continue;
}
}
else if (n == 0 && m == 0)
{
while (ch1 != ')')
{
if ('9' >= ch1 && ch1 >= '0')
{
a = ch1 - '0';
b *= 10;
b += a;
}
else
{
c = b;b = 0;ifs1.get(ch1);continue;
}
ifs1.get(ch1);
}
L.push_back(Factorial(b));
}
else if (n == 1 && m == 0)
{
while (ch1 != ')')
{
if ('9' >= ch1 && ch1 >= '0')
{
a = ch1 - '0';
b *= 10;
b += a;
}
else
{
c = b;b = 0;ifs1.get(ch1);continue;
}
ifs1.get(ch1);
}
L.push_back(Combination(c, b));
}
else if (n == 2 && m == 0)
{
int num = 0;
while (ch1 != ')')
{
if ('9' >= ch1 && ch1 >= '0')
{
a = ch1 - '0';
b *= 10;
b += a;
}
else
{
num++;
if (num == 1)
{
c = b;b = 0; ifs1.get(ch1); continue; //第一个数
}
else
{
d = b;b = 0; ifs1.get(ch1); continue; //第二个数,b是第三个
}
}
ifs1.get(ch1);
}
L.push_back(Date(c, d, b));
}
}
}
ifs1.close();
L.sort();
ofstream ofs1;
ofs1.open("Converted_data.txt", ios::out);
list<int>::iterator p;
p = L.begin();
while (p != L.end())
{
ofs1 << *p << " ";
p++;
}
ofs1.close();
}
int main()
{
Read();
return 0;
}
因为水平不够,忽略掉了四则运算等。算是勉强实现。。。