今晚虽然没有自己做笔试,但是看到一些笔试完后讨论的题,自己也尝试写了一下,第二题是实现一个极简解释器。
1.题目
题目是实现一个极简解释器,输入会给出代码的行数和每一行代码,每一行代码只存在变量名,等号,数字,加号,空格,不存在其他的符号,并且变量名之间不能有等号。要求输出最后一行的结果。
示例:
输入:
4
xx = 2
yy = 5
zz = xx
cd = xx + yy + zz
输出:9
2.思路
总体思路是定义一个map,将运算看成入map和查询map的过程。
(1)获得每一行输入,然后将每一行输入到getResult函数中处理。
(2)在getResult函数的输入参数是当前行line,当前行数i,总指令行数n
1)首先要以等号为界将表达式分成左右两部分:left和right(需要处理掉多余的空格)
2)然后需要判断右边是单纯的数字或变量还是变量的求和运算:通过计算右边字符串中'+'号的个数plusNum
如果plusNum等于0,则代表右边是单纯的数字或变量:
->如果右边是单纯的数字[每一位都是数字]:将数字的值压入key值为left的map中
->如果右边是变量,需要检查这个变量是否已存在在map中,若存在,则将对应的value值压入key值为left的map中,若不存在,且已是最后一步操作,则输出“NA”
如果plusNum不等于0,则代表右边是求和运算:
-> 需要先获得每个待求和字串,压入堆栈,再依次判断是变量还是数字,进行加和运算,加和的结果入key值为left的map中
3)最后,如果是最后一个操作,则输出对应的值
3.代码
#include <iostream>
#include <vector>
#include <list>
#include <sstream>
#include <map>
#include <stack>
#include <string>
#include <algorithm>
using namespace std;
map<string, int> calulate;
bool isNumber(string str)//用于判断是不是个数字
{
bool isNum = true;
for (int i = 0; i < str.size(); i++)
{
if (str[i]<'0' || str[i] >'9')
isNum = false;
}
return isNum;
}
void getTheResult(string line, int i, int n)
{
//将输入行以'='分割成左部分和右部分,并去掉多余的空格
istringstream input(line);
string left;
getline(input,left,'=');
left.erase(remove(left.begin(), left.end() ,' ' ), left.end());
string right;
getline(input, right);
right.erase(remove(right.begin(), right.end(), ' '), right.end());
//判断右侧是否有求和运算
int plusNum = 0;
for (int i = 0; i < right.size(); i++)
{
if (right[i] == '+')
plusNum++;
}
//如果右边是单个数字或变量,入map
bool isNum = isNumber(right);
if (plusNum == 0)
{
if (isNum == true)//如果是数字
calulate[left] = stoi(right);
else//如果是变量
{
if ((calulate.find(right) == calulate.end()) && (i == n))
cout << "NA" << endl;
if (calulate.find(right) != calulate.end())
calulate[left] = calulate[right];
}
}
else //如果右边是公式
{
//将待求和部分入栈
istringstream rightTmp(right);
stack <string> num;
int i = plusNum;
string tmp;
while (i--)
{
getline(rightTmp, tmp, '+');
num.push(tmp);
}
getline(rightTmp, tmp);
num.push(tmp);
//根据每部分是数字还是变量求和
i= plusNum+1;
int res = 0;
while (i--)
{
string tmp = num.top();
if (isNumber(tmp))
res += stoi(tmp);
else if(calulate.find(right) == calulate.end())
res += calulate[tmp];
else
{
if(i==n)
cout << "NA" << endl;
}
num.pop();
}
calulate[left] = res;
}
if (i == n)//如果是最后一次操作,输出
{
cout<< calulate[left] <<endl;
}
}
int main()
{
int n;
cin >> n;
string space;
getline(cin,space);
int i = 0;
while (i++<n)
{
string line;
getline(cin,line);
getTheResult(line,i,n);
}
}
4.小结
<1>以=分割出str的左部分和右部分:
isstringstream input(str);
string left;
getline(input,left,'=');//left里是等号左边的内容,input里剩下等号右边的内容
string right;
getline(input,right);
<2>去除string str中空格的现有方法:需要包含头文件algorithm
str.erase(remove(str.begin(),str.end(),' '),str.end());
<3>字符串数字转换
string a = to_string(3.1415);//数字转字符
int a = stoi("123");//字符转数字