我正在使用+,-,*,/和^运算符编写用于后缀表达式评估的代码。它应该从命令行将输入作为字符串,该字符串是表达式的后记符号(空格用作定界符)。该程序应在控制台上打印表达式的结果。
我编写的代码适用于所有带有整数值的测试用例。例如。它适用于输入:2 2 2 * + 我试图将堆栈输入值更改为float而不是int,但仍然无法使用。
using namespace std;
struct node
{
float data ;
node *next ;
};
class stack
{
private :
node *head;
public :
stack()
{
head = NULL;
}
void push(float a)
{
node * temp = new node();
temp ->data = a ;
temp -> next = head ;
head = temp ;
}
int pop()
{
node *temp = head ;
head = temp->next ;
int a = temp->data ;
delete temp;
return a;
}
int see_top()
{
if(is_empty())
return 0 ;
node * temp = head ;
return (temp->data);
}
int is_empty()
{
if(head == NULL)
return 1;
else
return 0 ;
}
};
int is_digit(char a)
{
if(a >= '0' && a<= '9')
return 1;
else
return 0;
}
int is_operand(char a)
{
switch(a)
{
case '+' :
case '-' :
case '*' :
case '/' :
case '^' : return 1;
default : return 0;
}
}
float operation(float a , float b , char sym)
{
float ans ;
switch(sym)
{
case '+' : ans = a + b ;
break;
case '-' : ans = a - b ;
break ;
case '*' : ans = a*b ;
break ;
case '/' : ans = a/b ;
break ;
case '^' : ans = pow(a,b) ;
break ;
default : break ;
}
return ans ;
}
int main()
{
char exp[100];
stack s ;
float num=0 , num1=0 , num2=0 ;
int l , i ;
cout << "Enter the posfix expression : ";
cin.getline(exp,100);
l=strlen(exp);
for(i=0;i<l;i++)
{
if(is_digit(exp[i]))
{
num = 0;
while(exp[i]!=' ')
{
int a = exp[i++]- '0';
num = 10*num + a ;
}
s.push(num);
}
else if(is_operand(exp[i]))
{
num2 = s.see_top();
s.pop();
num1 = s.see_top();
s.pop();
num = operation(num1 , num2 , exp[i]);
s.push(num);
}
else
continue;
}
num = s.see_top();
s.pop();
cout << "Answer : " << num ;
return 0 ;
}
当我尝试输入带有一些浮点值的表达式时,它没有返回正确的值。例如。理想情况下,对于表达式0.5 0.5 *,应返回0.25,但应返回225。对于表达式0.1 0.1 +,则应返回-36。
答案 0 :(得分:0)
代码看起来非常好!。
您快到了。代码中存在三个问题:
pop()
将所有内容强制转换为int see_top()
将所有内容强制转换为int 这是更新后的pop()
和see_top()
。 注意,他们现在返回浮点数。
float pop()
{
node *temp = head;
head = temp->next;
float a = temp->data;
delete temp;
return a;
}
float see_top()
{
if (is_empty())
return 0;
node *temp = head;
return (temp->data);
}
解析小数点最好通过添加switch语句来解决。
看到小数点后,您实际上就进入了新状态。请参见下面的代码。我还添加了代码来处理“-”字符。我使用pow()
数学函数添加数字的小数部分。我会将数字解析移到一个函数中,但不想完全更改您的代码。这是完整的解决方案:
#include <cmath>
#include <iostream>
using namespace std;
struct node {
float data;
node *next;
};
class stack {
private :
node *head;
public :
stack()
{
head = NULL;
}
void push(float a)
{
node *temp = new node();
temp->data = a;
temp->next = head;
head = temp;
}
float pop()
{
node *temp = head;
head = temp->next;
float a = temp->data;
delete temp;
return a;
}
float see_top()
{
if (is_empty())
return 0;
node *temp = head;
return (temp->data);
}
int is_empty()
{
if (head == NULL)
return 1;
else
return 0;
}
};
bool is_digit(char a)
{
return (a >= '0' && a <= '9') || a == '.' || a == '-';
}
bool is_operand(char a)
{
switch (a) {
case '+' :
case '-' :
case '*' :
case '/' :
case '^' : return true;
default : return false;
}
}
float operation(float a, float b, char sym)
{
float ans;
switch (sym) {
case '+' : ans = a + b;
break;
case '-' : ans = a - b;
break;
case '*' : ans = a * b;
break;
case '/' : ans = a / b;
break;
case '^' : ans = pow(a, b);
break;
default : break;
}
return ans;
}
int main()
{
char exp[100];
stack s;
float num = 0, num1 = 0, num2 = 0;
int l, i;
cout << "Enter the posfix expression : ";
cin.getline(exp, 100);
l = strlen(exp);
for (i = 0; i < l; i++) {
int exponent = 0;
int sign = 1;
if (is_digit(exp[i])) {
num = 0;
while (exp[i] != ' ') {
switch (exp[i]) {
case '.':exponent = -1;
break;
case '-':
sign = -1; // handle the negative sign
break;
default:int a = exp[i] - '0';
if(exponent >= 0) {
num = pow(10, exponent) * num + a;
++exponent;
} else {
num = pow(10, exponent) * a + num;
--exponent;
}
}
++i;
}
num *= sign; // If there was a '-', multiply by -1
s.push(num);
} else if (is_operand(exp[i])) {
num2 = s.see_top();
s.pop();
num1 = s.see_top();
s.pop();
num = operation(num1, num2, exp[i]);
s.push(num);
} else
continue;
}
num = s.see_top();
s.pop();
cout << "Answer : " << num;
return 0;
}
使用std :: istringstream的替代解决方案
为了获得一些额外的乐趣,我重写了一些输入处理以使用std :: istringstream。 stringstream非常强大,在解析时应始终考虑在内。我发现将字符串加倍转换为c ++的函数令人困惑并且容易出错。因此,如果允许您使用stringstream,这可能会有所帮助。由于stringstream将为您完成转换,因此无需搜索小数点。它将处理所有边缘情况。这是stringstream解决方案:
#include <iostream>
#include <cmath>
#include <sstream>
using namespace std;
struct node {
float data;
node *next;
};
class stack {
private :
node *head;
public :
stack()
{
head = NULL;
}
void push(float a)
{
node *temp = new node();
temp->data = a;
temp->next = head;
head = temp;
}
float pop()
{
node *temp = head;
head = temp->next;
float a = temp->data;
delete temp;
return a;
}
float see_top()
{
if (is_empty())
return 0;
node *temp = head;
return (temp->data);
}
bool is_empty()
{
if (head == NULL)
return true;
else
return false;
}
};
int is_digit(char a)
{
if (a >= '0' && a <= '9')
return 1;
else
return 0;
}
int is_operand(char a)
{
switch (a) {
case '+' :
case '-' :
case '*' :
case '/' :
case '^' : return 1;
default : return 0;
}
}
float operation(float a, float b, char sym)
{
float ans;
switch (sym) {
case '+' : ans = a + b;
break;
case '-' : ans = a - b;
break;
case '*' : ans = a * b;
break;
case '/' : ans = a / b;
break;
case '^' : ans = pow(a, b);
break;
default : break;
}
return ans;
}
int main()
{
// char exp[100];
stack s;
float num = 0, num1 = 0, num2 = 0;
cout << "Enter the posfix expression : ";
std::string input_line;
std::getline(cin, input_line);
std::istringstream token_stream(input_line); // Parse words from input_line
std::string token;
while (token_stream >> token) {
// Check the first character of the token. It is n operand, then use it
// You could move the size() check to the is_operand() function
if (token.size() == 1 && is_operand(token[0])) {
char operand = token[0];
num2 = s.see_top();
s.pop();
num1 = s.see_top();
s.pop();
num = operation(num1, num2, operand);
s.push(num);
} else {
std::istringstream number_stream(token); // convert number tokens to floats
if(number_stream >> num) {
s.push(num);
}
}
}
num = s.see_top();
s.pop();
cout << "Answer : " << num;
return 0;
}