计算机软件技术实习项目一——简易计算器

此项目用到的主要有中缀表达式转后缀表达式,双栈法实现带括号的四则运算

中缀转后缀表达式:

思路:和中缀表达式的计算类似,只不过不用计算,把表达式输出即可

      1.用字符数组存储整行输入的中缀表达式;

      2.接着从字符数组的0位置开始判断字符,如果是数字,那就要判断后面是否是数字,如果是就不断扫描组成一个整数

        (暂不考虑负数和小数),最终组成一个整数,然后输出这个数(因为不用计算,所以直接输出即可);

      3.如果是左括号,直接进符号栈;

      4.如果是操作运算符,与符号栈的栈顶元素比较优先级:如果高就压入栈;

                低,就取出符号栈顶的元素输出;

                接着,再判断符号栈顶的元素和当前的运算符号继续比较优先级,重复前面步骤,直到栈空或者当前的符号优先级高;

      5.如果是右括号,把符号栈栈顶的元素取出,如果不是左括号,把取出的运算符输出,接着取符号栈栈顶的元素,直到符号栈

         中取出的符号是左括号;

      6.当扫描完字符数组时,判断符号栈是否为空:

                不为空,把符号栈栈顶的元素取出,输出到窗口,直到符号栈为空。

双栈法:

思路:需要两个栈,一个用来存数字,一个用来存符号

定义一个指针index用来遍历表达式

遍历表达式,index指向数字时,将该数字压入数字栈

这里需要注意:指向的数字并非是一位数,可能是多位数

是多位数的情况下,则需要在指向的数字往后看一位,如果是数字,要进行拼接,得到两位数;

还需要再往后看一位,直到后一位是符号为止,才能将最终拼接出来的数压入数字栈

index指向符号时,则需要判断

​ ①如果当前的符号栈为空,则直接压入符号栈

​ ②如果指向的符号优先级大于符号栈顶符号的优先级,则直接压入符号栈

​ ③如果指向的符号优先级小于或等于符号栈顶符号的优先级,则需要从数字栈中取出两个数,并在符号栈中取出一个符号,进行运算,将得到的结果压入数字栈,最后将指向的当前的符号压入符号栈

当表达式遍历结束,顺序从数字栈和符号栈中取出相应的数字和符号,并运算
最后在数字栈中只有一个数字,即表达式的最终结果

UI界面展示:

UI的实现代码:

Widget::Widget(QWidget *parent)
  : QWidget(parent)
  , ui(new Ui::Widget)
{
  ui->setupUi(this);
  this->setWindowTitle("计算器");
 
}

槽函数的实现:

 
void Widget::on_btn_clear_clicked() //清空
{
  ui->le_show->clear();
  infix.clear();
}
void Widget::on_btn_back_clicked() //退格
{
  infix.remove(infix.length()-1,1);
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_1_clicked()
{
  infix += "1";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_0_clicked()
{
  infix += "0";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_point_clicked()
{
    if(infix.lastIndexOf(".")>infix.lastIndexOf("+")||infix.lastIndexOf(".")>infix.lastIndexOf("-")||infix.lastIndexOf(".")>infix.lastIndexOf("*")||infix.lastIndexOf(".")>infix.lastIndexOf("/"))return;
    if(infix.back()==")"||infix.back()=="("||infix.back()=="+"||infix.back()=="-"||infix.back()=="*"||infix.back()=="/"||infix.back()==".")return;
  infix += ".";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_add_clicked()
{
     if(infix.back()=="("||infix.back()=="+"||infix.back()=="-"||infix.back()=="*"||infix.back()=="/"||infix.back()==".")return;
  infix += "+";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_sub_clicked()
{
     if(infix.back()=="("||infix.back()=="+"||infix.back()=="-"||infix.back()=="*"||infix.back()=="/"||infix.back()==".")return;
  infix += "-";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_3_clicked()
{
  infix += "3";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_2_clicked()
{
  infix += "2";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_multiply_clicked()
{
     if(infix.back()=="("||infix.back()=="+"||infix.back()=="-"||infix.back()=="*"||infix.back()=="/"||infix.back()==".")return;
  infix += "*";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_6_clicked()
{
  infix += "6";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_5_clicked()
{
  infix += "5";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_4_clicked()
{
  infix += "4";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_divide_clicked()
{
    if( infix.back()=="("||infix.back()=="+"||infix.back()=="-"||infix.back()=="*"||infix.back()=="/"||infix.back()==".")return;
  infix += "/";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_9_clicked()
{
  infix += "9";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_8_clicked()
{
  infix += "8";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_7_clicked()
{
  infix += "7";
  ui->le_show->setText(infix);
}
 
void Widget::on_btn_right_clicked()
{
    if(infix.back()=="("||infix.back()=="+"||infix.back()=="-"||infix.back()=="*"||infix.back()=="/"||infix.back()==".")return;
    if(count1>count2){
     count2++;
  infix += ")";
  ui->le_show->setText(infix);}
}
 
void Widget::on_btn_left_clicked()
{
  if(infix.back()>="0"&&infix.back()<="9")return;
  if(infix.back()==".")return;
      count1++;
    infix += "(";
  ui->le_show->setText(infix);
}

核心算法的实现:

void Widget::on_btn_equal_clicked()// =
{
    QChar j= infix.right(1).at(0);
        if(count1!=count2||j=="+"||j=="-"||j=="*"||j=="/")
        {
            ui->le_show->setText("表达式错误");
            return;
        }
  ui->text_history->clear();
  optr.clear();
  opnd.clear();
  if(infix[0]=="-")
      infix = "0" + infix;
  if(infix.isEmpty())
      return;
  optr.push('='); //=置于栈底,级别最低
  int i = 0;
  double num,a,b;
  char item,ch;
  while(!optr.empty())
  {
      if(infix[i]=="0"||infix[i]=="1"||infix[i]=="2"||infix[i]=="3"||infix[i]=="4"||infix[i]=="5"||
          infix[i]=="6"||infix[i]=="7"||infix[i]=="8"||infix[i]=="9"||infix[i]==".") //数字字符或者.,则拼接并入栈
      {
          num = jointNum(infix,i);
          opnd.push(num);  //数字入栈
      }
      else //操作符
      {
           item = optr.top();
          switch(compare_priority(in_priority(item),out_priority(infix[i].toLatin1())))//比较运算符优先级,toLatin1:QChar->char
          {
             case -1:
          {
              optr.push(infix[i].toLatin1());//infix[i]优先级高,入栈
                              i++;  //指向下一个字符
          }
              break;
             case 0:
          {
              item = optr.pop(); //删除括号或者=
              if(item!='=')
                  i++;  //指向下一个字符
          }
              break;
             case 1:
          {
              ch = optr.pop(); //infix[i]级别低,弹出一个运算符并弹出两个操作数进行运算后再压栈
              a = opnd.pop();
              b = opnd.pop();
              opnd.push(calcualate_num(a,b,ch)); //运算后结果入栈
          }
          }
 
      }
  }
  num = opnd.pop();
  if(!opnd.empty())
   qDebug()<<"error";
  QString temp = infix + "="+ QString::number(num);
  history_infix.push_back(temp);
  de_weight(history_infix);
  for(int i = 0;i<history_infix.size();i++)
  {
      ui->text_history->append(history_infix.at(i));
  }
  ui->le_show->setText(QString::number(num));
  infix = QString::number(num);
}

运算符优先级判定及运算符栈和运算数栈的定义:

int Widget::in_priority(char ch)
{
  int in;
  switch(ch)
  {
      case '=':in = 0;break;
      case '+':in = 3;break;
      case '-':in = 3;break;
      case '*':in = 5;break;
      case '/':in = 5;break;
      case '(':in = 1;break;
      case ')':in = 6;break;
  }
  return in;
}
 
int Widget::out_priority(char ch)
{
  int out;
  switch(ch)
  {
      case '=':out = 0;break;
      case '+':out = 2;break;
      case '-':out = 2;break;
      case '*':out = 4;break;
      case '/':out = 4;break;
      case '(':out = 6;break;
      case ')':out = 1;break;
  }
  return out;
}
 
int Widget::compare_priority(int in, int out)
{
  if(in<out)
      return -1;
  else if(in==out)
      return 0;
  else
      return 1;
}
 
int Widget::calcualate_num(double num1, double num2, char oper)
{
  switch(oper)
  {
  case '+':return num2+num1;
  case '-':return num2-num1;
  case '*':return num2*num1;
  case '/':
  {
      if(num1 == 0)
      {
          QMessageBox::warning(this,"错误","除数为0!!!");
          return 0;
      }
 
      return num2/num1;
  }
  }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值