桌面计算器,递归下降分析,Qt框架。代码。
本帖最后由 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
#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
#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
#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;
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文件
#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.isDigit())
{
if(statu==INITIAL)
{
statu=INT_PART;
temp.append(Lexpression);
curpos++;
continue;
}else if(statu==INT_PART){
temp.append(Lexpression);
curpos++;
continue;
}else if(statu==DOT) {
statu=FRAC_PART;
temp.append(Lexpression);
curpos++;
continue;
}else if(statu==FRAC_PART){
temp.append(Lexpression);
curpos++;
continue;
}
}else if (Lexpression=='+') {
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=='-') {
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=='*') {
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=='/') {
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=='(') {
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==')') {
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=='.') {
if(statu==INT_PART)
{
statu=DOT;
temp.append(Lexpression);
curpos++;
continue;
}else{
token->kind=BADTOKEN;
token->str="BADTOKEN";
token->value=0;
curpos++;
return;
}
}else if(Lexpression==' '){
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()
{
Tokentoken;
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文件
#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文件
#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=new QPushButton(QString::number(bNum),this);
connect(button,SIGNAL(clicked()),this,SLOT(DigitClicked()));
mainlayout->addWidget(button,4+bNum/4,bNum%4,1,1);
}
button=new QPushButton("BackSpace",this);
connect(button,SIGNAL(clicked()),this,SLOT(BackSpaceClicked()));
mainlayout->addWidget(button,2,0,2,1);
button=new QPushButton("=",this);
connect(button,SIGNAL(clicked()),this,SLOT(EqualClicked()));
mainlayout->addWidget(button,2,3,2,1);
button=new QPushButton("(",this);
connect(button,SIGNAL(clicked()),this,SLOT(LeftParenClicked()));
mainlayout->addWidget(button,6,2,1,1);
button=new QPushButton(")",this);
connect(button,SIGNAL(clicked()),this,SLOT(RightParenClicked()));
mainlayout->addWidget(button,6,3,1,1);
button=new QPushButton("+",this);
connect(button,SIGNAL(clicked()),this,SLOT(AddClicked()));
mainlayout->addWidget(button,7,0,1,1);
button=new QPushButton("-",this);
connect(button,SIGNAL(clicked()),this,SLOT(SubClicked()));
mainlayout->addWidget(button,7,1,1,1);
button=new QPushButton("*",this);
connect(button,SIGNAL(clicked()),this,SLOT(PowClicked()));
mainlayout->addWidget(button,7,2,1,1);
button=new QPushButton("/",this);
connect(button,SIGNAL(clicked()),this,SLOT(MulClicked()));
mainlayout->addWidget(button,7,3,1,1);
button=new QPushButton("ClearAll",this);
connect(button,SIGNAL(clicked()),this,SLOT(ClearAllClicked()));
mainlayout->addWidget(button,2,1,2,1);
button=new QPushButton("Point",this);
connect(button,SIGNAL(clicked()),this,SLOT(PointClicked()));
mainlayout->addWidget(button,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());
}
}
voidWidget::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文件
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
好像很厉害的样子 我来看看来哦 发表于 2015-6-8 14:10
然而并没有什么用
大神请无视我。。。 1032621483 发表于 2015-6-8 14:10
好像很厉害的样子
大神请无视我。 好东西 流弊啊 你是华软的? 袭影于夜 发表于 2015-6-10 08:36
你是华软的?
额。。。不是。 虽然没看懂。不过支持下
页:
[1]