吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 3515|回复: 8
收起左侧

[其他转载] 桌面计算器,递归下降分析,Qt框架。代码。

[复制链接]
SstudentT 发表于 2015-6-8 14:02
本帖最后由 SstudentT 于 2015-6-9 12:47 编辑

大概思路:
首先,用Qt框架写个界面。实现能够对鼠标点击输入以及键盘输入,用到Qt有的信号和槽,还有通用的事件处理。
其次,用递归下降思路写个计算表达式的类,
1.parse_expression  
2.parse_term  
3.parse_primary_expression
第一个解决 + -操作!
第二个解决 * /操作!
第三个解决数的读取!

递归下降体现在:
第三个数的读取,如果碰到的是括号。就把括号里面的当初一个expression,调用第一个parse_expression来计算!

异常处理就是parse_expression主要代码放在 try{ }里面,下面各级发生词法错误或者语法错误就throw。然后在tyr{ }的后面catch{ }部分处理!
catch处理的时候判断这个是第几层parse_expression,如果是最外层parse_expression,处理了就结束了。如果不是最外层,就接着throw。

最后,把Qt写的界面和计算表达式的类结合一下。把行编辑器里面的内容最为计算类的计算对象。把对象的计算结果设置成行编辑器内容!

附上源码以及exe程序。链接:http://pan.baidu.com/s/1mgkTMxq
密码:efyz
忘记加了一句,大神请无视我!

头文件compute.h

[C++] 纯文本查看 复制代码
#ifndef COMPUTE_H
#define COMPUTE_H

#include<QString>
#include<QChar>
#include<QDebug>
#include<stdexcept>
#include<iostream>
typedef enum{
    BADTOKEN,
    ENDOFLINE,
    NUMBER,
    ADDOP,
    SUBOP,
    MULOP,
    DIVOP,
    LEFTPAREN,
    RIGHTPAREN
}TOKENKIND;

typedef struct Token{
 TOKENKIND kind;
 double value;
 QString str;
}Token;

typedef enum{
    INITIAL,
    INT_PART,
    FRAC_PART,
    DOT
}Status;

using std::runtime_error;

class Compute
{
public:
    Compute(QString expression,Token*Fuck,int initialize=0)
        :Lexpression(expression),
         ahead_token(Fuck),
         ErrorStatu(initialize),
         Look_ahead_exist(initialize),
         curpos(initialize),
         Parse_expression_level(initialize){}
    QString Printf();
    ~Compute(){}
private:
    QString Lexpression;
    QString ErrorMessage;
    Token *ahead_token;
    int ErrorStatu;
    int Look_ahead_exist;
    int curpos;
    int Parse_expression_level;
    void get_token(Token*token);
    void un_get_token(Token*token);
    void my_get_token(Token*token);
    double parse_primary_expression();
    double parse_term();
    double parse_expression();
};

#endif // COMPUTE_H


头文件mylineedit.h
[C++] 纯文本查看 复制代码
#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H

#include <QLineEdit>
#include<QMouseEvent>
#include<QString>
class MyLineEdit : public QLineEdit
{
    Q_OBJECT
public:
    explicit MyLineEdit(QWidget *parent = 0);
    MyLineEdit(QString text,QWidget*parent=0);
    void textUpdata(QString addText);
    void textRemove();
    void CurInit();
private:
    long CurPos;
protected:
    void mousePressEvent(QMouseEvent *event);
    void keyPressEvent(QKeyEvent *event);
};

#endif // MYLINEEDIT_H


头文件widget.h

[C++] 纯文本查看 复制代码
#ifndef WIDGET_H
#define WIDGET_H

#include<QWidget>
#include<QPushButton>
#include<QGridLayout>
#include<QLineEdit>
#include<QDebug>
#include"compute.h"
#include"mylineedit.h"
namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
    
private:
    Ui::Widget*ui;
    QPushButton*button[20];
    QGridLayout*mainlayout;
    MyLineEdit*lineEdit;
private slots:
    void DigitClicked();
    void BackSpaceClicked();
    void EqualClicked();
    void LeftParenClicked();
    void RightParenClicked();
    void AddClicked();
    void SubClicked();
    void PowClicked();
    void MulClicked();
    void ClearAllClicked();
    void PointClicked();         

};
#endif // WIDGET_H




compute.cpp文件
[C++] 纯文本查看 复制代码
#include "compute.h"


QString Compute::Printf()
{
    double v;
    v=parse_expression();
    if(ErrorStatu==0)
        return QString::number(v);
    else
        return ErrorMessage;
}
void Compute::get_token(Token* token)
{
    Status statu=INITIAL;
    QString temp;
    while (curpos<Lexpression.size()) {
        if(Lexpression[curpos].isDigit())
        {
            if(statu==INITIAL)
            {
                statu=INT_PART;
                temp.append(Lexpression[curpos]);
                curpos++;
                continue;
            }else if(statu==INT_PART){
                temp.append(Lexpression[curpos]);
                curpos++;
                continue;
            }else if(statu==DOT) {
                statu=FRAC_PART;
                temp.append(Lexpression[curpos]);
                curpos++;
                continue;
            }else if(statu==FRAC_PART){
                temp.append(Lexpression[curpos]);
                curpos++;
                continue;
            }
        }else if (Lexpression[curpos]=='+') {
            if(statu==INT_PART||statu==FRAC_PART)
            {
                token->kind=NUMBER;
                token->value=temp.toDouble();
                token->str=temp;
                return;
            }else if (statu==INITIAL) {
                token->kind=ADDOP;
                token->value=0;
                token->str="+";
                curpos++;
                return;
            }else{
                token->kind=BADTOKEN;
                token->value=0;
                token->str="BADTOKEN";
                curpos++;
                return;
            }
        }else if (Lexpression[curpos]=='-') {
            if(statu==INT_PART||statu==FRAC_PART)
            {
                token->kind=NUMBER;
                token->value=temp.toDouble();
                token->str=temp;
                return;
            }else if (statu==INITIAL) {
                token->kind=SUBOP;
                token->value=0;
                curpos++;
                token->str="-";
                return;
            }else{
                token->kind=BADTOKEN;
                token->value=0;
                token->str="BADTOKEN";
                curpos++;
                return;
            }
        }else if (Lexpression[curpos]=='*') {
            if(statu==INT_PART||statu==FRAC_PART)
            {
                token->kind=NUMBER;
                token->value=temp.toDouble();
                token->str=temp;
                return;
            }else if (statu==INITIAL) {
                token->kind=MULOP;
                token->value=0;
                curpos++;
                token->str="*";
                return;
            }else{
                token->kind=BADTOKEN;
                token->str="BADTOKEN";
                token->value=0;
                curpos++;
                return;
            }
        }else if (Lexpression[curpos]=='/') {
            if(statu==INT_PART||statu==FRAC_PART)
            {
                token->kind=NUMBER;
                token->value=temp.toDouble();
                token->str=temp;
                return;
            }else if (statu==INITIAL) {
                token->kind=DIVOP;
                token->value=0;
                curpos++;
                token->str="/";
                return;
            }else{
                token->kind=BADTOKEN;
                token->str="BADTOKEN";
                token->value=0;
                curpos++;
                return;
            }
        }else if (Lexpression[curpos]=='(') {
            if(statu==INT_PART||statu==FRAC_PART)
            {
                token->kind=NUMBER;
                token->value=temp.toDouble();
                token->str=temp;
                return;
            }else if (statu==INITIAL) {
                token->kind=LEFTPAREN;
                token->value=0;
                curpos++;
                token->str="(";
                return;
            }else{
                token->kind=BADTOKEN;
                token->str="BADTOKEN";
                token->value=0;
                curpos++;
                return;
            }
        }else if (Lexpression[curpos]==')') {
            if(statu==INT_PART||statu==FRAC_PART)
            {
                token->kind=NUMBER;
                token->value=temp.toDouble();
                token->str=temp;
                return;
            }else if (statu==INITIAL) {
                token->kind=RIGHTPAREN;
                token->value=0;
                curpos++;
                token->str=")";
                return;
            }else{
                token->kind=BADTOKEN;
                token->str="BADTOKEN";
                token->value=0;
                curpos++;
                return;
            }
        }else if (Lexpression[curpos]=='.') {
            if(statu==INT_PART)
            {
                statu=DOT;
                temp.append(Lexpression[curpos]);
                curpos++;
              continue;
            }else{
                token->kind=BADTOKEN;
                token->str="BADTOKEN";
                token->value=0;
                curpos++;
                return;
            }
        }else if(Lexpression[curpos]==' '){
                curpos++;
                continue;
        }
        else {
           token->kind=BADTOKEN;
           token->str="BADTOKEN";
           token->value=0;
           curpos++;
           return;
        }
    }
    if(statu==INITIAL)
    {
        token->kind=ENDOFLINE;
        token->str="ENDOFLINE";
        token->value=0;
        return;
    }else if(statu==INT_PART||statu==FRAC_PART){
        token->kind=NUMBER;
        token->value=temp.toDouble();
        token->str=temp;
        return;
    }
    return;
}

void Compute::un_get_token(Token*token)
{
    QString str=token->str;
    Look_ahead_exist=1;
    ahead_token->kind=token->kind;
    ahead_token->value=token->value;
    ahead_token->str=str;
}

void Compute::my_get_token(Token *token)
{
    if(Look_ahead_exist==1){
        token->kind=ahead_token->kind;
        token->value=ahead_token->value;
        token->str=ahead_token->str;
        Look_ahead_exist=0;
    }else
        get_token(token);
}

double Compute::parse_primary_expression()
{
    Token token;
    double v;
    int negative=0;

    while (1) {
        my_get_token(&token);
        if(token.kind==NUMBER){
            v=token.value;
            if(negative==0)
            return v;
            else
            return -v;
        }else if(token.kind==SUBOP){
            if(negative==1)
                throw runtime_error("BAD INPUT IN LEXICAL!");
            else{
                negative=1;
                continue;
            }
        }else if (token.kind==LEFTPAREN) {
            Parse_expression_level++;
            v=parse_expression();
            Parse_expression_level--;
            my_get_token(&token);
            if(token.kind!=RIGHTPAREN)
                throw runtime_error("MISSING RIGHTPAREN!");
            else{
                if(negative==1)
                    return -v;
                else
                   return v;
            }
        }else if(token.kind==ENDOFLINE){
            throw runtime_error("ENDOFLINE!");
        }else
            throw runtime_error("BAD INPUT IN LEXICAL!");
}
}

double Compute::parse_term()
{
    Token  token;
    double v1,v2;
    v1=parse_primary_expression();
    while (1) {
        my_get_token(&token);
        if(token.kind==ENDOFLINE){
            un_get_token(&token);
            return v1;
        }else if(token.kind==MULOP){
            v2=parse_primary_expression();
            v1*=v2;
        }else if(token.kind==DIVOP){
            v2=parse_primary_expression();
            if(v2==0.0){
                throw runtime_error("DIVISOR CAN'T BE ZERO!");
            }else{
                v1/=v2;
            }
        }else if(token.kind==ADDOP||token.kind==SUBOP||token.kind==RIGHTPAREN){
            un_get_token(&token);
            return v1;
        }else if(token.kind==BADTOKEN){
            throw runtime_error("BAD INPUT IN LEXICAL!");
        }else{
            throw runtime_error("BAD INPUT IN SYNTAX!");
        }
    }
}

double Compute::parse_expression()
{
    Token token;
    double v1,v2;
    try{
        v1=parse_term();
        while (1) {
            my_get_token(&token);
            if(token.kind==ADDOP){
                v2=parse_term();
                v1+=v2;
            }else if (token.kind==SUBOP) {
                v2=parse_term();
                v1-=v2;
            }else if(token.kind==RIGHTPAREN){
             un_get_token(&token);
             return v1;
            }else if(token.kind==ENDOFLINE){
                un_get_token(&token);
                return v1;
            }else{
                throw runtime_error("BAD INPUT!");
            }
        }
    }catch (runtime_error err){
        ErrorStatu=1;
        ErrorMessage=err.what();
       if(Parse_expression_level)
       {
           Parse_expression_level--;

           throw runtime_error(err.what());
       }

    }
    return 32767.0;
}



mylineedit.cpp文件
[C++] 纯文本查看 复制代码
#include "mylineedit.h"
#include"compute.h"
MyLineEdit::MyLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
}
MyLineEdit::MyLineEdit(QString text,QWidget *parent):QLineEdit(parent)
{
  setText(text);
}

void MyLineEdit::mousePressEvent(QMouseEvent *event)
{
   QLineEdit::mousePressEvent(event);
   CurPos=cursorPosition();
}

void MyLineEdit::keyPressEvent(QKeyEvent *event)
{
    if(event->key()==16777220)
    {
        QString content;
        int initialize=0;
        Token *Fuck=new Token;
        content=text();
        Compute expression(content,Fuck,initialize);
        setText(expression.Printf());
        delete Fuck;
    }
    else
        QLineEdit::keyPressEvent(event);
}

void MyLineEdit::textUpdata(QString addText)
{
    QString text=this->text();
    text.insert(CurPos,addText);
    setText(text);
    CurPos++;
}

void MyLineEdit::textRemove()
{
    if (CurPos==0)
        return;
    QString text=this->text();
    text.remove(CurPos-1,1);
    setText(text);
    CurPos--;
}

void MyLineEdit::CurInit()
{
    CurPos=0;
}




widget.cpp文件
[C++] 纯文本查看 复制代码
#include "widget.h"
#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    mainlayout=new QGridLayout;

    lineEdit=new MyLineEdit("",this);
    mainlayout->addWidget(lineEdit,0,0,2,4);

    for(int bNum=0;bNum<10;bNum++)
    {
        button[bNum]=new QPushButton(QString::number(bNum),this);
        connect(button[bNum],SIGNAL(clicked()),this,SLOT(DigitClicked()));
        mainlayout->addWidget(button[bNum],4+bNum/4,bNum%4,1,1);
    }

    button[10]=new QPushButton("BackSpace",this);
    connect(button[10],SIGNAL(clicked()),this,SLOT(BackSpaceClicked()));
    mainlayout->addWidget(button[10],2,0,2,1);

    button[11]=new QPushButton("=",this);
    connect(button[11],SIGNAL(clicked()),this,SLOT(EqualClicked()));
    mainlayout->addWidget(button[11],2,3,2,1);

    button[12]=new QPushButton("(",this);
    connect(button[12],SIGNAL(clicked()),this,SLOT(LeftParenClicked()));
    mainlayout->addWidget(button[12],6,2,1,1);

    button[13]=new QPushButton(")",this);
    connect(button[13],SIGNAL(clicked()),this,SLOT(RightParenClicked()));
    mainlayout->addWidget(button[13],6,3,1,1);

    button[14]=new QPushButton("+",this);
    connect(button[14],SIGNAL(clicked()),this,SLOT(AddClicked()));
    mainlayout->addWidget(button[14],7,0,1,1);

    button[15]=new QPushButton("-",this);
    connect(button[15],SIGNAL(clicked()),this,SLOT(SubClicked()));
    mainlayout->addWidget(button[15],7,1,1,1);

    button[16]=new QPushButton("*",this);
    connect(button[16],SIGNAL(clicked()),this,SLOT(PowClicked()));
    mainlayout->addWidget(button[16],7,2,1,1);

    button[17]=new QPushButton("/",this);
    connect(button[17],SIGNAL(clicked()),this,SLOT(MulClicked()));
    mainlayout->addWidget(button[17],7,3,1,1);

    button[18]=new QPushButton("ClearAll",this);
    connect(button[18],SIGNAL(clicked()),this,SLOT(ClearAllClicked()));
    mainlayout->addWidget(button[18],2,1,2,1);

    button[19]=new QPushButton("Point",this);
    connect(button[19],SIGNAL(clicked()),this,SLOT(PointClicked()));
    mainlayout->addWidget(button[19],2,2,2,1);

    mainlayout->setSizeConstraint(QLayout::SetFixedSize);
    setLayout(mainlayout);
}

Widget::~Widget()
{
    delete ui;
}

void Widget::DigitClicked()
{
    QPushButton*clickedButton=qobject_cast<QPushButton*>(sender());
    int digitValue=clickedButton->text().toInt();
    if(lineEdit->text()=="0"&&digitValue==0.0)
        return;
    else{
        lineEdit->textUpdata(clickedButton->text());
    }
}

void  Widget::BackSpaceClicked()
{
    lineEdit->textRemove();
}

void Widget::LeftParenClicked()
{
    lineEdit->textUpdata("(");
}

void Widget::RightParenClicked()
{
    lineEdit->textUpdata(")");
}

void Widget::AddClicked()
{
   lineEdit->textUpdata("+");
}

void Widget::SubClicked()
{
   lineEdit->textUpdata("-");
}

void Widget::PowClicked()
{
   lineEdit->textUpdata("*");
}

void Widget::MulClicked()
{
    lineEdit->textUpdata("/");
}

void Widget::PointClicked()
{
    lineEdit->textUpdata(".");
}

void Widget::ClearAllClicked()
{
    lineEdit->setText("");
    lineEdit->CurInit();
}

void Widget::EqualClicked()
{
    QString content;
    int initialize=0;
    Token *Fuck=new Token;
    content=lineEdit->text();
    Compute expression(content,Fuck,initialize);
    lineEdit->setText(expression.Printf());
    delete Fuck;
}



main.cpp文件
[C++] 纯文本查看 复制代码
#include "widget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();
    
    return a.exec();
}


发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

1032621483 发表于 2015-6-8 14:10
好像很厉害的样子
头像被屏蔽
我来看看来哦 发表于 2015-6-8 14:10
 楼主| SstudentT 发表于 2015-6-8 18:50
 楼主| SstudentT 发表于 2015-6-8 18:51
1032621483 发表于 2015-6-8 14:10
好像很厉害的样子

大神请无视我。
manbajie 发表于 2015-6-9 12:11
好东西   流弊啊
袭影于夜 发表于 2015-6-10 08:36
你是华软的?
 楼主| SstudentT 发表于 2015-6-10 20:25

额。。。不是。
眼里有星河 发表于 2015-6-14 20:12
虽然没看懂。不过支持下
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-14 19:01

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表