1、简介
计算器是我们生活中很常见的东西,它可以由多种语言多种方式来实现,今天我想讲的是基于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<setText(input); } int Change(const char *S,char OPS[],int &len) { QStackOPE; 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 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 #includeusing 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#include 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< = 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() { }
到此这篇关于Qt实现可以计算大数的简单计算器的文章就介绍到这了,更多相关Qt计算器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!