栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++ 简易翻译器

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++ 简易翻译器

题目概述:

1.给定字典dict.txt,第一行为提示有多少行,其余第一列为需要被替换的字符,第二列为需要替换     上的字符;

2.给定一个输入文件input.txt,其中包含多种运算:[m,n]求m,n的最小公倍数Lcm,{m,n}求m,n的最大公约数Gcd。

 对()内有三种形式:(y/m/d)求y年m月d日为星期几,(m,n)求组合数Cm n,(a)求a的阶乘。

求工资数,其中a为工作小时,b为每小时工资((如果时间小于0或大于一周的总时间直接输出0)。若每周工作小时超过60小时,则超过60小时的部分按原工资3倍的加班工资来计算,每周工作小时超过40小时而不超过60小时的工资按原工资的1.5倍的加班工资来计算。)

单独一个数字则不做任何计算。

3.具体步骤:

(1)从特定文本文件中读取一个特定格式字典,包括①从数字到数值的对应,②从字母到数值的对应,③括号和计算符号不作转换;

(2)再从一个文本文件中读取原始符号串,并实现将原始符号串根据字典进行必要的转换。注意,转换后的符号串需要用链表存储;

(3)针对转换后的符号串,按下列要求完成相应的计算,并用两侧各附有一个空格的计算结果替换原来的符号串;

(4)若是数字转换,3换55需要换,但33不是3,不能替换成5555;无需重复替换如3换5,5换7;

(5)再针对处理后的、由空格分隔的数据进行排序;

(6)最后将排好序的数据,以格式化的形式存入文件;

当时觉得挺折磨的,文件读取与输出,链表操作都是小白,得使劲瞪眼bing,google...一开始字典是一一对应的,我便想存进同一个数组中,偶数(0开始)为第一列被替换字符,奇数为替换上去地的字符。后面需要一对多,也就是3可能换成55,g可能换成777等等。工资数那里由于我是一个一个读取字符来判断符号、计算符号数字的,于是出现了小数计算与多个小数点判断的问题,但所幸原理与算多位数相同。尽管仍有一些不足,但起码现在能看...

完整代码:

#include
#include
#include
#include
#include
using namespace std;
//全局变量
string dicbook[99]{}; //总字典 // 将第一列与第二列合并而成的长字符串数组
string dicbook1[99]{}; //字典第一列即要被转换的字符
string dicbook2[99]{}; //字典第二列即被转换成的字符
char c; //ReadDic字符串中间变量
int row = 0; //行数
string needchange[99]{}; //转换成需要修改的字符串数组
int dicbooklenth = 0, dicbook1lenth = 0, dicbook2lenth = 0, needchangelenth = 0; //各字符串数组长度存储

string dicttxt, inputtxt; //字典,输入
string temptxt, answerdata; //临时,答案

//事先声明的函数
void ReadDic();
void Getinput();

//数学
int Gcd(int m, int n) //求m,n的最大公约数
{
	if (n == 0)
	{
		return m;
	}
	return Gcd(n, m % n);
}
int Lcm(int m, int n) //求m,n最小公倍数
{
	return m * n / Gcd(m, n);
}


int Fac(int n) //求n的阶乘
{
	for (int i = n - 1; i >= 1; i--)
	{
		n *= i;
	}
	return n;
}

int CombinatorialNumber(int n, int m) //求m,n的组合数,无论m和n谁大谁小
{
	int sum = 1;
	int tem = 1;
	if (m > n)
	{
		tem = n;
		n = m;
		m = tem;
	}
	for (int i = 1; i <= m; i++)
	{
		sum = sum * (n - m + i) / i;
	}
	return sum;
}

//工资
double Salary(double time, double per) //求工资
{
	double total = 0;
	if (time <= 0 || time >= 168) total = 0;
	else if (time > 0 && time <= 40) total = time * per;
	else if (time > 40 && time <= 60) total = 1.5 * (time - 40) * per + 40 * per;
	else if (time > 60 && time < 168) total = 3 * (time - 60) * per + 1.5 * 20 * per + 40 * per;
	return total;
}

//年份
int LeapYear(int year) //判断闰年
{
	if (year % 400 == 0 || year % 100 != 0 && year % 4 == 0) return 1;
	else return 0;
}
int WhatDay(int year, int month, int day) // 判断某年月日是星期几
{
	int i = 0, result = 0;
	if (year > 0 && month <= 12 && month > 0 && day <= 31 && day > 0)
	{
		if (LeapYear(year) && month == 2 && day > 29)
		{
			return result;
		}
		else if (LeapYear(year) == 0 && month == 2 && day > 28)
		{
			return result;
		}
		else if (month == 4 || month == 6 || month == 9 || month == 11)
		{
			if (day > 30) return result;
		}
		for (i = 1; i < year; i++)
		{
			result += (LeapYear(i) + 365) % 7;
		}
		for (i = 1; i < month; i++)
		{
			if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12)
			{
				result += 31 % 7;
				result %= 7;
			}
			else if (i == 4 || i == 6 || i == 9 || i == 11)
			{
				result += 30 % 7;
				result %= 7;
			}
			else if (i == 2)
			{
				result += (28 + LeapYear(year)) % 7;
				result % 7;
			}
		}
		result += day % 7;
		result %= 7;
		if (result == 0)
			result = 7;
		return result;
	}
	else return result;
}
//字典转换
string Change(string str) //对字典给定的特定字符进行转换
{
	int j = 1, n = 1, count = 0;
	for (int i = 0; i < dicbooklenth; i += 2)
	{
		n = dicbook[j].length();
		j += 2;
		count++;
		if (0 < n && n < 2)
		{
			replace(str.begin(), str.end(), dicbook[i][0], dicbook[i + 1][0]);
		}
		else if (n >= 2)
		{
			if (str == dicbook[i]) str = dicbook[i + 1];
			else continue;
		}
	}
	return str;
}


//文件操作
void ReadDic() //读取字典并把字典内容存到全局字符数组dicbook
{
	int count = 0; //判断为第一列还是第二列
	int pd = 0; //控制判断是否为多位数
	int mulnumpolen = 0;
	ifstream dic(dicttxt);
	while (!dic.eof())
	{
		c = dic.get();
		if (c == '#')
		{
			c = dic.get();
			c = dic.get();
			row = c - '0';
			c = dic.get();
			c = dic.get();
		}
		if (c == ' ')
		{
			cout << "空格";
			count++;
			pd = 0;
			continue;
		}
		else if (c == 'n')
		{
			cout << "换行" << endl;
			count--;
			pd = 0;
			continue;
		}
		else if (c == EOF)
		{
			cout << "换行" << endl;
			count--;
			pd = 0;
			continue;
		}
		if (count == 0)
		{
			dicbook1[dicbook1lenth] = c;
			dicbook1lenth++;
		}
		else if (count == 1)
		{
			pd++;
			if (pd < 2)
			{
				dicbook2[dicbook2lenth] = c;
				++dicbook2lenth;
			}
			else if (pd >= 2)
			{
				dicbook2[dicbook2lenth - 1] += c;
			}
		}
		cout << c;
	}
	cout << "行数:" << row;
	cout << endl;
	cout << "第一列的元素:";
	for (int i = 0; i < dicbook1lenth; i++)
	{
		
		cout << dicbook1[i] << " ";
	}
	cout << endl;
	int mpl = 0;
	cout << "第二列的元素:";
	for (int i = 0; i < dicbook2lenth; i++)
	{
		
		cout << dicbook2[i] << " ";
	}
	cout << endl;

	int countb1 = 0, countb2 = 0;
	dicbooklenth = dicbook1lenth + dicbook2lenth;
	for (int i = 0; i < dicbooklenth; i++)
	{
		if (i % 2 == 0)
		{
			dicbook[i] = dicbook1[countb1];
			countb1++;
		}
		else
		{
			dicbook[i] = dicbook2[countb2];
			countb2++;
		}
	}
	cout << endl;
	cout << "总字典:";
	for (int i = 0; i < dicbooklenth; i++)
	{
		
		cout << dicbook[i] << " ";
	}
	dic.close(); //关闭文件
}

void Getinput() //得到输入的文件将其转换为字符串形式
{
	ifstream inpu(inputtxt);
	while (!inpu.eof())
	{
		inpu >> needchange[needchangelenth++]; //逐个放入needchange 字符串里
	}
	inpu.close(); //关闭文件
}

void FuncRealize() //字典转换与输入的具体实现
{
	ifstream ifs;
	char ch = 0;
	string str;
	listList1;

	int i = 0;
	ifs.open(inputtxt, ios::in);//读取文件
	while (ifs.get(ch)) //得到一个string类型的input作为转换的另一个str
	{
		if (ch == '<')
		{
			str += ch;
			while (ch != '>')
			{
				ifs.get(ch);
				if (ch == ' ') continue;
				str += ch;
			}
		}
		else
			str += ch;
		i++;
	}
	ifs.close();
	cout << "转换前的字符串:" << endl;
	cout << str << endl;

	int len = str.length();
	string newstr;                   //获得新的string(删除了<>里的空格)
	ReadDic(); //读字典
	Getinput(); //得到输入
	for (int i = 0; i < len; i++)  //逐个替换字符
	{
		if ('9' >= str[i] && str[i] >= '0') //如果读到了数字
		{
			if (i == 0 && (str[i + 1] > '9' || str[i + 1] < '0')) //如果数字在第一位且下一位是符号,转换
			{
				string temstr;
				temstr = str[i];
				newstr += Change(temstr);
			}
			//小数考虑
			if ( (i > 0 && i < len - 1 && str[i + 1] > '9') &&  (str[i + 1] < '0' && str[i - 1] == '.') )  //如果数字不在第一位且不在最后一位,且后一位为符号前一位为小数点,不改
			{
				newstr += str[i];
			}
			else if ((i > 0 && i < len - 1 && str[i + 1] > '9') && (str[i - 1] < '0' && str[i + 1] == '.') )  //如果数字不在第一位且不在最后一位,且前一位为符号后一位为小数点,也不改
			{
				newstr += str[i];
			}
			else if ( (i > 0 && i < len - 1) && (str[i + 1] > '9' || str[i + 1] < '0') && (str[i - 1] > '9' || str[i - 1] < '0') ) //如果数字不在第一位且不在最后一位,前后都是符号
			{
				if ( (str[i + 1] < '0' && str[i - 1] == '.') || (str[i - 1] < '0' && str[i + 1] == '.') )  //前后若有小数点,不改
				{
					newstr += str[i];
				}
				else //其他的,对照字典修改
				{
					string temstr;
					temstr = str[i];
					newstr += Change(temstr);
				}
			}
			else if (i == len - 1 && (str[i - 1] > '9' || str[i - 1] < '0')) 如果数字在最后一位,且前一位是符号,按照字典修改
			{
				string temstr;
				temstr = str[i];
				newstr += Change(temstr);
			}
			else newstr += str[i]; //其他不改
		}
		else //读到符号,改
		{
			string temstr;
			temstr = str[i];
			newstr += Change(temstr);
		}
	}
	cout << endl;
	cout << endl << "转换后的字符串:" << endl;
	cout << newstr;

	ofstream newinpu;//写入新文件
	newinpu.open(temptxt, ios::out);
	newinpu << newstr << endl;
	newinpu.close();

	ifstream newread;//读新文件
	newread.open(temptxt, ios::in);

	char temch; //临时字符,一个个取新文件里的字符串的内容
	while (newread.get(temch)) //当没有读到EOF时
	{
		if ('9' >= temch && temch >= '0') //如果读到数字,下有同理
		{
			int a = 0, b = 0, c = 0; //三个中间变量,将读到的数字转化为int型带入函数计算
			while (temch != ' ') //读取数字
			{
				if ('9' >= temch && temch >= '0') //读了几位就要得到几位
				{
					a = temch - '0'; //假设有字符串‘24’,先读2,得到int型2,b*10 = 0,b+=a = 2,判断还为数字,再读进4,得到int型a = 4,此时b*=10 = 20, b+=a = 24
					b *= 10;
					b += a;
				}
				else
				{
					newread.get(temch); continue; //读到符号,保存,接着读
				}
				newread.get(temch);// 接着读
			}
			List1.push_back(b); //放进List1链表里
		}
		else if (temch == '{')//当读到“{”,求最大公约数
		{
			int a = 0, b = 0, c = 0;
			while (temch != '}')
			{

				if ('9' >= temch && temch >= '0')
				{
					a = temch - '0';
					b *= 10;
					b += a;
				}
				else
				{
					c = b; b = 0;	newread.get(temch); continue;   //c是第一个数据
				}
				newread.get(temch);
			}
			List1.push_back(Gcd(c, b));
		}
		else if (temch == '<')//当读到“<”,求工资
		{
			double a = 0, b = 0, c = 0, point = 0, tempoint = 0;
			while (temch != '>')
			{
				if ('9' >= temch && temch >= '0')
				{
					a = temch - '0';
					b *= 10;
					b += a;
					newread.get(temch);
					if (temch == '.') //如果为小数
					{
						double plus = 0.1;
						newread.get(temch);
						while ('0' <= temch && temch <= '9') //当读的都是数字时,算小数部分为多少,方法与*=10得多位数类似
						{
							tempoint = temch - '0';
							tempoint = tempoint * plus;
							point += tempoint;
							plus *= 0.1; //每多一位往后退一位
							newread.get(temch);
							// cout << "point" << point; 测试point对不对
						}
						b = b + point;
					}
				}
				else
				{
					c = b; b = 0; point = 0; //读到符号时初始化b与小数部分,这样就可以得到两个小数放进Salary中的效果
					newread.get(temch); continue;   //c是第一个数据
				}
			}
			// cout << "cb" << c << " " << b; //检查cb是否有输入,输入是否正确
			List1.push_back(Salary(c, b));
		}
		else if (temch == '[') //当读到“[”,求最小公倍数
		{
			int a = 0, b = 0, c = 0;
			while (temch != ']')
			{
				if ('9' >= temch && temch >= '0')
				{
					a = temch - '0';
					b *= 10;
					b += a;
				}
				else
				{
					c = b; b = 0; newread.get(temch); continue;   //c是第一个数据
				}
				newread.get(temch);
			}
			List1.push_back(Lcm(c, b));
		}
		else if (temch == '(') //当读到“(”,进行下一步判断
		{
			int n = 0, m = 0, s = 0, times = 0; //n,m,s是判断括号里有什么,程序该进哪个循环的重要判据
			int a = 0, b = 0, c = 0, d = 0, f = 0; //中间变量
			while (temch != ' ')
			{
				times++;                   //记录读了多少次——读了多少字节
				newread.get(temch);
				if (temch == ',') n++; 
				else if (temch == '(') m++;
				else if (temch == '/') s++;
			}
			// cout << "nms" << n << m << s; 检查,查看()里的是什么符号的判据是否成功
			newread.seekg(-times, ios::cur);   //移动文件读指针回原先位置'('
			newread.get(temch);                      //读取e为值
			if (m != 0)
			{
				while (temch != ' ')
				{
					newread.get(temch);
					continue;
				}
			}
			else if (n == 0 && m == 0 && s == 0)//求阶乘
			{
				while (temch != ')')
				{
					if ('9' >= temch && temch >= '0')
					{
						a = temch - '0';
						b *= 10;
						b += a;
					}
					else
					{
						c = b; b = 0; newread.get(temch); continue;
					}
					newread.get(temch);
				}
				List1.push_back(Fac(b));
			}
			else if (n == 1 && m == 0 && s == 0)//求组合数
			{
				while (temch != ')')
				{
					if ('9' >= temch && temch >= '0')
					{
						a = temch - '0';
						b *= 10;
						b += a;
					}
					else
					{
						c = b; b = 0; newread.get(temch); continue;
					}
					newread.get(temch);
				}
				List1.push_back(CombinatorialNumber(c, b));
			}
			else if (n == 0 && m == 0 && s == 2)//求星期几
			{
				int num = 0;
				while (temch != ')')
				{
					if ('9' >= temch && temch >= '0')
					{
						a = temch - '0';
						b *= 10;
						b += a;
					}
					else
					{
						num++;
						if (num == 1)
						{
							c = b; b = 0; newread.get(temch); continue;  //第一个数
						}
						else
						{
							d = b; b = 0; newread.get(temch);  continue;  //第二个数,b是第三个
						}
					}
					newread.get(temch);
				}
				List1.push_back(WhatDay(c, d, b));
			}
		}
	}
	newread.close();
	

	ofstream ouput; //放入文件中
	ouput.open(answerdata, ios::out);
	list::iterator List2;
	List2 = List1.begin();
	if (ouput)
	{
		while (List2 != List1.end())
		{
			ouput << *List2 << " ";//写入文件
			List2++;
		}
		if (List2 == List1.end())
		{
			ouput << endl;
		}
	}
	else
	{
		cout << "No file found" << endl;
	}
	ouput.close(); //由于下面又输入了一遍排序后的,这里的输入文件只是临时的,文件中并没有,这里仅为了answer能够输出未排序的回显
	

	ifstream answer(answerdata); //读文件,输出回显
	string line;
	int count = 0;
	if (answer) // 有该文件
	{
		cout << endl << endl << "Result(排序前):" << endl;
		while (getline(answer, line)) // line中不包括每行的换行符
		{
			cout << line << endl;
		}
	}
	else // 没有该文件
	{
		cout << "No file found" << endl;
	}
	cout << endl;
	answer.close();

	List1.sort();
	cout << "排序后:" << endl;
	list::iterator List3;
	List3 = List1.begin();
	while (List3 != List1.end())
	{
		cout << *List3 << " "; // 输出回显
		List3++;
	}

	ouput.open(answerdata, ios::out);
	List3 = List1.begin();
	if (ouput)
	{
		while (List3 != List1.end())
		{
			ouput << *List3 << " ";//写入文件
			List3++;
		}
	}
	else // 没有该文件
	{
		cout << "No file found" << endl;
	}
	ouput.close();
}


int main()
{
	cout << "请输入 字典 的完整地址:";
	cin >> dicttxt;
	cout << "请输入 输入 的完整地址:";
	cin >> inputtxt;
	cout << "请输入 临时存储 的完整地址:";
	cin >> temptxt;
	cout << "请输入 存放排序后的字符串 的完整地址:";
	cin >> answerdata;
	FuncRealize();
	system("pause");
}

文本准备:

dict.txt:

# 7(其实这个可有可无)
1 2
a 19
b 10
4 8
c 9
k 20
6 5

input.txt: 3 (5,b) a 11 {44,11} 19 (6) <9.5,12.45> 99 (k/2/23) 77 1000 [b,1]

temp.txt与answerdata.txt均为空。

输出示例:

 (完整地址可以直接把txt拖进,之前还真不知道...(汗))

具体某些问题注释也写了一些理解,具体操作仔细读读还是能够明白文件txt的读取输出也其实挺好懂的,其使输入与输出更加灵活。但是链表这个东西确实不错!值得深入学习与探究,与数组有类似,但功能上感觉更加强大...当然,关系网也更加复杂了。链表详细很多大佬写的那是又细又好,想参悟链表,咱还得继续学,先继续参考大佬的吧!

参考链表知识链接:【C++】链表及基本操作_撸代码的Ellie的博客-CSDN博客_c++链表

                                  c++链表 - 知乎

 初学,粗浅理解,欢迎指正!一起努力!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1001098.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号