Qt实现可以计算大数的简单计算器
音视频开发老舅 人气:01、简介
计算器是我们生活中很常见的东西,它可以由多种语言多种方式来实现,今天我想讲的是基于C++语言,由QT实现的可以计算大数的简单计算器。
2、作品演示
(1)简单四则运算
(2)大数运算
3、重点原理讲解
(1)四则运算如何实现 (2)大数的加减乘除
4、代码主体框架
1个主函数; 两个类: 一个calculator类,实现了对界面的布局,其实这个布局很简单,就设置了一些按钮以及一个显示框。
类的声明:
class calculator : public QMainWindow { Q_OBJECT public: calculator(QWidget *parent = 0); ~calculator(); private: QLineEdit *inputLine;//显示框 QString input="0"; //输入框 //0-9按钮 QPushButton *zeroButton; QPushButton *oneButton; QPushButton *twoButton; QPushButton *threeButton; QPushButton *fourButton; QPushButton *fiveButton; QPushButton *sixButton; QPushButton *sevenButton; QPushButton *eightButton; QPushButton *nineButton; QPushButton *addButton; QPushButton *subButton; QPushButton *divButton; QPushButton *mulButton; QPushButton *equButton; QPushButton *timButton; //Time QPushButton *decButton; QPushButton *botButton; QPushButton *CEButton; QPushButton *ACButton; QPushButton *lefButton; QPushButton *rigButton; private slots: void buttonZeroClicked(); void buttonOneClicked(); void buttonTwoClicked(); void buttonThreeClicked(); void buttonFourClicked(); void buttonFiveClicked(); void buttonSixClicked(); void buttonSevenClicked(); void buttonEightClicked(); void buttonNineClicked(); void buttonAddClicked();//+ void buttonSubClicked();//- void buttonMulClicked();//乘 void buttonDivClicked();//除 void buttonTimClicked(); //时间 void buttonDecClicked();//小数点 void buttonBotClicked(); //加减号 void buttonEquClicked();//等于号 void buttonLefClicked();//左括号 void buttonRigClicked();//右括号 void buttonCEClicked();//CE void buttonACClicked();//AC };
界面布局:
calculator::calculator(QWidget *parent) : QMainWindow(parent) { QWidget *widget=new QWidget; //构建一个QWidget布局将设置的布局添加进这个QWidget this->setCentralWidget(widget); inputLine=new QLineEdit; inputLine->setText(input); zeroButton=new QPushButton("0"); oneButton=new QPushButton("1"); twoButton=new QPushButton("2"); threeButton=new QPushButton("3"); fourButton=new QPushButton("4"); fiveButton=new QPushButton("5"); sixButton=new QPushButton("6"); sevenButton=new QPushButton("7"); eightButton=new QPushButton("8"); nineButton=new QPushButton("9"); decButton=new QPushButton("."); botButton=new QPushButton("±"); timButton=new QPushButton("Time"); addButton=new QPushButton("+"); subButton=new QPushButton("-"); mulButton=new QPushButton("*"); divButton=new QPushButton("/"); equButton=new QPushButton("="); lefButton=new QPushButton("("); rigButton=new QPushButton(")"); CEButton=new QPushButton("CE"); ACButton=new QPushButton("AC"); QGridLayout *H=new QGridLayout(this); //声明了一个网格布局 inputLine->setFixedHeight(50); //调整第一行大小 CEButton->setFixedHeight(50); ACButton->setFixedHeight(50); H->addWidget(inputLine,0,0,1,3); H->setRowStretch(0,100); H->addWidget(CEButton,0,3); H->addWidget(ACButton,0,4); H->addWidget(oneButton,1,0); H->addWidget(twoButton,1,1); H->addWidget(threeButton,1,2); H->addWidget(botButton,1,3); H->addWidget(timButton,1,4); H->addWidget(fourButton,2,0); H->addWidget(fiveButton,2,1); H->addWidget(sixButton,2,2); H->addWidget(addButton,2,3); H->addWidget(subButton,2,4); H->addWidget(sevenButton,3,0); H->addWidget(eightButton,3,1); H->addWidget(nineButton,3,2); H->addWidget(mulButton,3,3); H->addWidget(divButton,3,4); H->addWidget(zeroButton,4,0); H->addWidget(decButton,4,1); H->addWidget(lefButton,4,2); H->addWidget(rigButton,4,3); H->addWidget(equButton,4,4); widget->setLayout(H); //将布局显示出来 connect(zeroButton,SIGNAL(clicked()),this,SLOT(buttonZeroClicked()));//信号与槽函数 connect(oneButton,SIGNAL(clicked()),this,SLOT(buttonOneClicked())); connect(twoButton,SIGNAL(clicked()),this,SLOT(buttonTwoClicked())); connect(threeButton,SIGNAL(clicked()),this,SLOT(buttonThreeClicked())); connect(fourButton,SIGNAL(clicked()),this,SLOT(buttonFourClicked())); connect(fiveButton,SIGNAL(clicked()),this,SLOT(buttonFiveClicked())); connect(sixButton,SIGNAL(clicked()),this,SLOT(buttonSixClicked())); connect(sevenButton,SIGNAL(clicked()),this,SLOT(buttonSevenClicked())); connect(eightButton,SIGNAL(clicked()),this,SLOT(buttonEightClicked())); connect(nineButton,SIGNAL(clicked()),this,SLOT(buttonNineClicked())); connect(addButton,SIGNAL(clicked()),this,SLOT(buttonAddClicked())); connect(subButton,SIGNAL(clicked()),this,SLOT(buttonSubClicked())); connect(mulButton,SIGNAL(clicked()),this,SLOT(buttonMulClicked())); connect(divButton,SIGNAL(clicked()),this,SLOT(buttonDivClicked())); connect(botButton,SIGNAL(clicked(bool)),this,SLOT(buttonBotClicked()));//正负号 connect(timButton,SIGNAL(clicked(bool)),this,SLOT(buttonTimClicked()));//时间 connect(decButton,SIGNAL(clicked(bool)),this,SLOT(buttonDecClicked()));//点号 connect(lefButton,SIGNAL(clicked(bool)),this,SLOT(buttonLefClicked()));//左括号 connect(rigButton,SIGNAL(clicked(bool)),this,SLOT(buttonRigClicked()));//右括号 connect(CEButton,SIGNAL(clicked()),this,SLOT(buttonCEClicked())); connect(ACButton,SIGNAL(clicked()),this,SLOT(buttonACClicked())); connect(equButton,SIGNAL(clicked()),this,SLOT(buttonEquClicked())); //等于号*/ }
槽函数实现部分举例说明,其它类似:
void calculator::buttonZeroClicked() //以下是实现相应的槽函数 { if(input=="0") input='0'; else input=input+'0'; inputLine->setText(input); } void calculator::buttonTimClicked() //Time { input=QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss:zzz"); //格式化输出当前时间 inputLine->setText(input); }
点击等于号的时候调用Change函数和Exchange函数,对式子进行运算。
Change 函数,将显示框里面的中缀表达式转化为了后缀表达式,存入OPS字符数组中,数字之间用#分开,保存数组长度,方便后面的运算。
Exchange函数,将后缀表达式进行运算,对每两个数的加法减法乘法或者除法都是采用大数运算,通过CDashu类对 + – * / 的重载,然后在Exchange 函数中建立对象调用,最后将返回值再转化为字符输出到屏幕上。
void calculator::buttonEquClicked()//等于号 { std::string str=input.toStdString(); const char *S=str.c_str(); cout<<S[strlen(S)]; char OPS[max1]; int len; double result; char* change = new char[max1]; bool flag; Change(S,OPS,len); change = EXchange(OPS,len,result,flag); //QString::number(result,10,6); input=input+"="+change; inputLine->setText(input); } int Change(const char *S,char OPS[],int &len) { QStack<char> OPE; int i = 0 ,j = 0; int l = strlen(S); for( i ;i < strlen(S);i++) { switch(S[i]) { case '+': if(OPE.isEmpty()) OPE.push(S[i]); else if(OPE.top() == '*' || OPE.top() == '/' || OPE.top() == '-') { OPS[j++] = OPE.pop(); i--;//多次判断OPE.top()符号的优先级是否高于'+' } else OPE.push(S[i]); break; case '-': //if('('!=S[i-1]&&0!=i) //{ if(OPE.isEmpty()) OPE.push(S[i]); else if(OPE.top() == '*' || OPE.top() == '/' || OPE.top() == '+') { OPS[j++] = OPE.pop(); i--; } else OPE.push(S[i]); break; //} /*else { while ((S[i] >= '0'&&S[i] <= '9' )|| S[i] == '.'||('-'==S[i]&&(S[i-1]<'0'||S[i-1]>'9' || i == 0))) { if(S[i] == '-') OPS[j++]='#'; OPS[j++] = S[i]; i++; } i--; OPS[j++] = '#'; //数字中的间隔符 }*/ case '*': if(OPE.isEmpty()) { OPE.push(S[i]); } else if(OPE.top() == '/') { OPS[j++] = OPE.pop(); i--; } else OPE.push(S[i]); break; case '/': if(OPE.isEmpty()) { OPE.push(S[i]); } else if(OPE.top() == '*') { OPS[j++] = OPE.pop(); i--; } else OPE.push(S[i]); break; case'(': OPE.push(S[i]); break; case')': while (OPE.top() != '(') { OPS[j++] = OPE.pop();//遇到右括号,一直弹出操作符知道遇到左括号 } OPE.pop();//直接不放入数组弹出左括号 break; default: while (S[i] >= '0'&&S[i] <= '9' || S[i] == '.'||('-'==S[i]&&S[i-1]<'0'&&S[i-1]>'9')) { OPS[j++] = S[i]; i++; } i--; OPS[j++] = '#'; //数字中的间隔符 break; }//switch }//for while (!OPE.isEmpty()) { OPS[j++] = OPE.pop(); } len = j; return 0; }//Change char* EXchange(char OPS[], int len, double &result,bool &flag) { int tag = 0,t3; QStack<char*> SZ; char *s = new char[max1]; char *str1 = new char[max1]; char *str2 = new char[max1]; char *str = new char[max1]; char st1[max1][max1]; CDashu x1; CDashu x2; CDashu y; int i,j,t = 0,temp; for(i = 0;i < len;i++) { switch(OPS[i]) { case '+': str1 = SZ.pop(); str2 = SZ.pop(); x1.Change(str1); x2.Change(str2); y = x2 + x1; tag = 0; temp = 0; if(y.a[0]) { s[tag] = y.a[0]+'0'; tag++; } else temp++; for( ;tag <= y.getlength()-temp;tag++) { s[tag] = y.a[tag + temp]+'0'; } s[tag] = '\0'; SZ.push(s); break; case '-': str1 = SZ.pop(); str2 = SZ.pop(); x1.Change(str1); x2.Change(str2); y = x2 - x1; tag = 0; temp = 0; if(y.getflag()) { s[tag] = '-'; tag++; } if(y.a[0]) { s[tag] = y.a[0]+'0'; tag++; } else temp++; if(s[0] == '-') { for( ;tag <= y.getlength();tag++) { s[tag] = y.a[tag]+'0'; } s[tag] = '\0'; } else { for( ;tag <= y.getlength()-temp;tag++) { s[tag] = y.a[tag + temp]+'0'; } s[tag] = '\0'; } SZ.push(s); break; case '*': int max,min,max2; str1 = SZ.pop(); str2 = SZ.pop(); x1.Change(str1); x2.Change(str2); y = x1*x2; y.get(max,max2,min); j = 0; for(t3 = max;t3 >= min;t3--) { s[j++] = y.a[t3]+'0'; } s[j] = '\0'; SZ.push(s); break; case '/': { str1 = SZ.pop(); str2 = SZ.pop(); x1.Change(str1); x2.Change(str2); y = x2 / x1; int x = 0; i = 0; int num[max1]; while(y.yushu[0]) { num[x] = y.yushu[0]%10; y.yushu[0] = y.yushu[0]/10; x++; } x--; while(x > -1) { s[i] = num[x]+'0'; x--; i++; } s[i] = '.'; for(i = i+1,j = 1;j < 50;i++,j++) { s[i] = y.yushu[j]+'0'; } s[i] = '\0'; SZ.push(s); } break; default: j = 0; while (OPS[i] != '#') { st1[t][j] = OPS[i]; j++; i++; } st1[t][j] = '\0'; SZ.push(st1[t]); t++; break; } } return SZ.top(); }
下面重点介绍一下大数类:
类的声明与部分成员函数的实现
#ifndef CDASHU_H #define CDASHU_H #include<cstring> using namespace std; #define max1 500 #define MAXN 9999 class CDashu { public: int a[max1]; int yushu[max1]; CDashu() { length = 1; memset(a, 0, sizeof(a)); } //构造函数 void Change( char *s); //将字符串转换为大数 long getlength() { return length; } int getflag() { return flag; } friend int Compare(CDashu a,CDashu b); void get(int &m,int &m2,int &min) { m = max; m2 = max2; min = this->min; } ~CDashu(); CDashu operator +(CDashu b);//对各类运算的重载 CDashu operator -(CDashu b); CDashu operator *(CDashu b); CDashu operator /(CDashu b); private: long length; int flag; int max,min,max2; }; #endif // CDASHU_H
大数类的实现:
#include "cdashu.h" #include "cdashu.h" #include <iostream> #include <string.h> using namespace std; /* ostream& operator<<(ostream& out, CDashu& b) //重载输出运算符 { int i; out << b.a[b.length - 1]; for (i = b.length - 2; i >= 0; i--) { out.width(4); out.fill('0'); out << b.a[i]; } return out; }*/ void CDashu::Change( char *s) { memset(a, 0, sizeof(a)); long l = strlen(s); length = l; for (int i = 1; i <= l; i++) { a[i] = (int)s[i-1] - '0'; } for (int i = 1; i <= l; i++) { cout << a[i]; } cout << endl; } CDashu CDashu::operator+(CDashu b) { int i = length, j = b.length; if (i >= j) { for (; i > 0 && j > 0; i--, j--) a[i] += b.a[j];//逐个相加 i = length; for (i; i >= 0; i--) { if (a[i] >= 10) //进位运算 { a[i - 1] += a[i] / 10; a[i] %= 10; } } return *this; } else { for (; i >= 0 && j >= 0; i--, j--) b.a[j] += a[i];//逐个相加 i = b.length; for (i; i > 0; i--) { if (b.a[i] >= 10) //进位运算 { b.a[i - 1] += b.a[i] / 10; b.a[i] %= 10; } } return b; } } CDashu CDashu::operator -(CDashu b) { flag = 0; b.flag = 0; int i, j; if (length == b.length) { i = 1;j = 1; while (a[i] == b.a[i]) { i++; } if (a[i] < b.a[i]) b.flag = 1; } i = length; j = b.length; if (i < j || b.flag) { for (i; i > 0 && j > 0; i--, j--) b.a[j] -= a[i];//一一相减 i = b.length; for (i; i > 0; i--) { if (b.a[i] < 0) //补位运算 { b.a[i] += 10; b.a[i - 1] -= 1; } } return b; } else { for (i; i >= 0 && j >= 0; i--, j--) a[i] -= b.a[j];//一一相减 i = length; for (i; i >= 0; i--) { if (a[i] < 0) //补位运算 { a[i] += 10; a[i - 1] -= 1; } } return *this; } cout << endl; } CDashu CDashu::operator *(CDashu b) { CDashu t; int i, j; t.max = t.min = t.max2 = 1; for (i = length; i > 0; i--) { for (j = b.length; j > 0; j--) { t.a[length+b.length+1 -(i + j)] += a[i] * b.a[j];//t.a[]初始化为0 t.min = min<(length+b.length+1 -(i + j))?t.min:(length+b.length+1 -(i + j)); t.max = max>(length+b.length+1 -(i + j))?t.max:(length+b.length+1 -(i + j)); } } for (i = t.min; i <= t.max; i++) { if (t.a[i] >= 10) { t.a[i + 1] += t.a[i] / 10; t.a[i] = t.a[i] % 10; t.max2 = i+1; } } t.max = t.max > t.max2 ? t.max:t.max2; return t; } CDashu CDashu::operator /(CDashu b) { int i,j,flag = 1,count = 0,tag = 0,mm=0; min = 1; flag = Compare(*this,b); max = length; if (length < b.length || flag == 0) count = 0; else { while (flag == 1 || flag == 2) { if(min == length && a[min] == 0) { break; } else { i = length; j = b.length; count++; for ( ; i >= min && j > 0; i--, j--) a[i] -= b.a[j];//一一相减 i = length; for (i; i >= min; i--) { if (a[i] < 0) //补位运算 { a[i] += 10; a[i - 1] -= 1; } } i = min; if (a[i] == 0 && i != length) { while (a[i] == 0) { i++; } min = i; }//如果有减到前面为0,最小下标右移到不为0的位置 flag = Compare(*this,b);//比较两个数的大小 } cout<<count<<endl; }//while }//else cout << count << '.'; yushu[0] = count; tag = 0; for(i = 1;i <= length;i++) { if(a[i] != 0) { tag = 1; break; } } if(!tag) { for(i = 1;i < 50;i++) { yushu[i] = 0; } } else { int jingdu = 1; while(jingdu < 50) { count = 0; /*if(min == length && a[min] == 0) { for( ;jingdu < 30;jingdu++) { yushu[jingdu] = 0; } break; }*/ length++; a[length] = 0; flag = Compare(*this,b);//比较两个数的大小 if(flag == 2) { yushu[jingdu] = 1; jingdu++; for( ; jingdu < 50;jingdu++) { yushu[jingdu] = 0; } } else { if (flag == 0) { yushu[jingdu] = 0; jingdu++; } else { while (flag == 1 || flag==2) { if(min == length && a[min] == 0) { mm = 1; yushu[jingdu] = count; for( jingdu = jingdu+1;jingdu < 50;jingdu++) { yushu[jingdu] = 0; } break; } count++; i = length,j = b.length; for(;i >= min && j > 0;i--,j--) { a[i] -= b.a[j]; } i = length; for (i; i >= min; i--) { if (a[i] < 0) //补位运算 { a[i] += 10; a[i - 1] -= 1; } } i = min; if (a[i] == 0 && i != length) { while(a[i] == 0) { i++; } } min = i;//如果有减到前面为0,最小下标右移到不为0的位置 flag = Compare(*this,b);//比较两个数的大小 } yushu[jingdu] = count; jingdu++; } } if(mm) break; } } return *this; } int Compare(CDashu a,CDashu b) { int i = a.min, j = 1,flag = 1; if(a.length-a.min + 1 < b.length) flag = 0; else if(a.length-a.min+1 > b.length) flag = 1; else { while (a.a[i] == b.a[j] && i <= a.length && j <= b.length) { i++; j++; } if (a.a[i] < b.a[j]) flag = 0; if(a.a[i] == b.a[i]) { flag = 2; } } return flag; } CDashu::~CDashu() { }
加载全部内容