C++ RPN计算器/后修复计算器
所以,我必须做一个后缀计算器或RPN计算器,问题是这样的 任务是编写一个只对整数有效的简化计算器。代码必须提供一个名为evaluate的函数,该函数接受一个参数:std::string并返回一个整数。计算器必须按以下方式工作:C++ RPN计算器/后修复计算器,c++,types,stack,C++,Types,Stack,所以,我必须做一个后缀计算器或RPN计算器,问题是这样的 任务是编写一个只对整数有效的简化计算器。代码必须提供一个名为evaluate的函数,该函数接受一个参数:std::string并返回一个整数。计算器必须按以下方式工作: 它逐字符读取字符串 如果它读取一个数字,它会把它放在自己的内部堆栈上 如果它读取一个空格,它必须忽略它 如果它读取字符+、-、*或/它对堆栈的两个最上面的元素执行操作,删除它们并将结果放入堆栈 当它到达std::string参数的末尾时,它返回堆栈的顶部 代码: usin
using namespace std;
int evaluate(string);
bool isdigit(char c);
bool isOp(char c);
bool isdigit(char c)
{
if (c >= '0' && c <= '9')
{
return true;
}
return false;
}
int main()
{
string str;
cout << "\n Enter the input : ";
cin >> str;
evaluate(str);
}
int evaluate(string str)
{
stack<int> mystack;
stack<int> vals;
for (int i = 0; i < str.size(); i++)
{
char c = str[i];
if (isdigit(c))
{
vals.push(c);
}
else if (c == ' ')
{
c = ' ';
cout << str;
}
else
{
int value1, value2, result;
value2 = vals.top();
vals.pop();
value1 = vals.top();
vals.pop();
switch (str[i])
{
case '+':
result = value1 + value2;
mystack.push(result);
break;
case '-':
result = value1 - value2;
mystack.push(result);
break;
case '*':
result = value1 * value2;
mystack.push(result);
break;
case '/':
result = value1 / value2;
mystack.push(result);
break;
}
cout << "result is " << mystack.top();
}
}
}
使用名称空间std;
整数(字符串);
bool-isdigit(字符c);
bool-isOp(char-c);
布尔数字(字符c)
{
如果(c>='0'&&c str;
评价(str);
}
int求值(字符串str)
{
堆叠mystack;
堆栈VAL;
对于(int i=0;i 请注意,提供的算法只有在得到后缀表达式时才有效,而不是中缀表达式
第一个问题:
现在,请看下面一行:
vals.push(c);
<代码> C <代码>是字符,<>代码> Value/COD>是整数<代码>堆栈。当C在代码中呈现1,C++编译器实际上看到<代码> '0' + 1 < /C> >。例如:
23+5*
对于输入23+
,您将得到结果:101。为什么?
'2'!=2
和'3'!=3
。实际计算是:
'0'+2+'0'+3
,这意味着48+2+48+3
,因为在ascii码中'0'==48
要解决这个小问题,只需将插入到vals
堆栈中的值减少“0”:
vals.push(c - '0');
现在输入23+
的结果是:5
第二个问题:
您使用的是两个堆栈,而不是实际需要的一个堆栈。当您将结果值推入第二个堆栈(mystack
)时,您实际上无法访问它(或者更确切地说,使其值的使用更加复杂),只要您获得表达式的另一部分,例如:
23+5*
您可以调试这种情况(使用您正在使用的IDE的监视表/调试代码功能),并看到您正在尝试访问第一个结果的第5个堆栈,但在第一个堆栈中什么也没有,因为结果存储在第二个堆栈中。解决方案:使用单堆栈
case '+':
result = value1 + value2;
//mystack.push(result);
vals.push(result);
break;
总体改进
功能:isdigit
我建议您做的第一件事是删除if
语句-您不需要它。下面的代码将完成此操作:
bool isdigit(char c) {
return c >= '0' && c <= '9';
}
并删除此函数的实现。已存在同名的相同函数:
重要!
给出这个答案是因为我生活中有额外的时间和我所处的一个无聊的环境,但更重要的是,我认为这有助于理解如何调试代码和解决未来(以及更复杂的问题)案例。这类问题是调试问题类型。实际上,您不必在此处查找答案,只需调试代码并查看错误。请明智地使用此处提供的工具,祝您好运
编辑:
对于更多的C++风格解决方案,在更高的难度级别,你可以看到下面的解决方案(考虑它就像C++中的欢迎语):
int求值(字符串str){
//[]()->{}=>了解:Lambda表达式
堆栈VAL;
/*
*流行音乐
* ---
*返回堆栈的顶部值,并将其从堆栈中弹出。
*/
自动弹出=[](堆栈和s)->int{
int res=s.top();
s、 pop();
返回res;
};
/*
*op
* --
*返回对两个整数参数执行所选运算符的函数。
*/
自动运算=[](字符运算)->std::函数{
开关(op){
格“+”:
默认值:return[](inta,intb)->int{returna+b;};
大小写'-':return[](inta,intb)->int{returna-b;};
大小写'*':return[](inta,intb)->int{returna*b;};
大小写“/”:return[](inta,intb)->int{returna/b;};
}
};
/*
* FuxEngin是C++中的循环实现,作为标准库(STD)的一部分。
*它将获得第一个迭代器位置(str.begin())、结束迭代器位置(str.end())和要执行的函数
*集合中的每个值(在开始迭代器和结束迭代器之间)。
*/
std::for_each(str.begin()、str.end()、[&vals、pop、op](字符c){
if(isdigit(c))值推送(c-'0');
否则,如果(c!='')VAL.push(op(c)(pop(VAL),pop(VAL));
//op(c)->根据运算符返回函数
//op(c)(n1,n2)->在n1和n2上使用返回的运算符
//pop(VAL)->函数,该函数返回堆栈的顶部值,然后将其从堆栈中弹出。
//op(c)(pop(VAL),pop(VAL))->对堆栈中的前两个值应用选定的op
});
当你使用调试器执行你的程序时,一次一行,你观察到了什么?这是一个相当简单的逻辑错误,你应该能够在调试器的帮助下在几秒钟内找出它,比在stackoverflow.com上键入问题、发布问题和等待几个小时,也许还要快知道如何有效地使用调试器是每个C++开发人员所需要的技能。没有例外。我的编译器(G++8.2,带有<代码> -Poognic -Walth-WoTea/Cuth>作为额外的警告选项):警告:函数中没有返回语句,响应于<代码> int(字符串STR)返回非空格。
int evaluate(string str) {
// [] () -> {} ====> READ ABOUT: Lambda expressions
stack<int> vals;
/*
* pop
* ---
* Returns the top value of a stack, and the pop it from the stack.
*/
auto pop = [] (stack<int> &s) -> int {
int res = s.top();
s.pop();
return res;
};
/*
* op
* --
* Returns a function that execute the selected operator on two integers params.
*/
auto op = [] (char op) -> std::function<int(int, int)> {
switch (op) {
case '+':
default : return [] (int a, int b) -> int { return a + b; };
case '-': return [] (int a, int b) -> int { return a - b; };
case '*': return [] (int a, int b) -> int { return a * b; };
case '/': return [] (int a, int b) -> int { return a / b; };
}
};
/*
* for_each is a loop implementation in c++ as part of the standard library (std).
* It's get the first iterator place (str.begin()), end iterator place (str.end()), and function to execute on
* each value in the collection (between start and end iterators).
*/
std::for_each(str.begin(), str.end(), [&vals, pop, op] (char c) {
if (isdigit(c)) vals.push(c - '0');
else if (c != ' ') vals.push(op(c)(pop(vals), pop(vals)));
// op(c) -> returns a function according to the operator
// op(c)(n1, n2) -> use the returned operator on n1 and n2
// pop(vals) -> function that returns the top value of the stack, and then pop it from the stack.
// op(c)(pop(vals), pop(vals)) -> apply the selected op on the first two values in the stack
});
cout << "The result is: " << vals.top() << endl;
}