C++實(shí)現(xiàn)四則運(yùn)算器(無(wú)括號(hào))
本文實(shí)例為大家分享了C++實(shí)現(xiàn)無(wú)括號(hào)的四則運(yùn)算器的具體代碼,供大家參考,具體內(nèi)容如下
完成度更高的帶括號(hào)版本可以看C++實(shí)現(xiàn)四則運(yùn)算器(帶括號(hào))
對(duì)于無(wú)括號(hào)的計(jì)算器,實(shí)現(xiàn)起來(lái)比較容易,下面讓我們一步步實(shí)現(xiàn)。
舉例
首先明確需要實(shí)現(xiàn)怎樣的程序,對(duì)于無(wú)括號(hào)的計(jì)算器,大概做成這樣就可以了:
52+34*3-4/2=
分析
對(duì)于例子中的表達(dá)式,由于乘除運(yùn)算的優(yōu)先級(jí)高于加減運(yùn)算,我們不能直接從左到右進(jìn)行。但四則運(yùn)算的規(guī)則是從左到右,先乘除后加減,對(duì)于優(yōu)先級(jí)相同的運(yùn)算符還是可以從左到右運(yùn)算的。
因此我們可以每讀到一個(gè)運(yùn)算符時(shí),檢查前一個(gè)運(yùn)算符的優(yōu)先級(jí),如果前一個(gè)運(yùn)算符的優(yōu)先級(jí)與當(dāng)前運(yùn)算符相等或更高,那么我們便可以完成前一個(gè)運(yùn)算符的計(jì)算;反之,則不進(jìn)行運(yùn)算。這樣一來(lái)就需要將之前的運(yùn)算符以及運(yùn)算符左右的數(shù)保存起來(lái),由于我們每次都是取前一個(gè)運(yùn)算符,符合后進(jìn)先出的條件,故可以選擇棧來(lái)存儲(chǔ)數(shù)據(jù)和符號(hào)。最好將數(shù)據(jù)和符號(hào)分開(kāi)存儲(chǔ),這里為了簡(jiǎn)便(整數(shù)棧即可存儲(chǔ)數(shù)字也可存儲(chǔ)字符),只實(shí)現(xiàn)整數(shù)的四則運(yùn)算,若需要浮點(diǎn)數(shù)的運(yùn)算,稍加修改即可。
首先,實(shí)現(xiàn)一個(gè)棧的類,或者直接使用STL
//Stack.h #ifndef STACK_H #define STACK_H #include<iostream> class stack_int { private: int* bottom; //棧底 int* top; //棧頂 unsigned int capacity;//棧容量 unsigned int size; //棧大小 public: stack_int() :bottom(new int[11]), top(bottom), capacity(10), size(0) {}; stack_int(unsigned int capacity) :bottom(new int[capacity+1]),top(bottom), capacity(capacity),size(0){}; int operator[](unsigned int i) const { return *(bottom + i); } bool isEmpty()const { return bottom == top; } bool isFull()const { return size == capacity-1; } unsigned int getsize()const { return size; } unsigned int getcapacity()const { return capacity; } int gettop()const { if (!isEmpty()) return *(top - 1); else return -1; } void settop(int i) { if (!isEmpty()) { *(top - 1) = i; } } void push(int i) { if ((top - bottom)<capacity) { *top = i; top++; size++; } else { std::cout << "stack full!" << std::endl; stack_expansion(); push(i); } } int pop(int &val) {//返回值為1則棧未空,返回值為0則棧已空無(wú)法出棧 if (top > bottom) { top--; size--; val = *top; return 1; } else { std::cout << "stack empty!" << std::endl; return NULL; } } private: void stack_expansion() {//棧擴(kuò)容 std::cout << "正在擴(kuò)容中..." << std::endl; int newcapacity = 2 * capacity + 1; int* newbottom = new int[newcapacity + 1]; int* newtop = newbottom; for (int i = 0; i < size; ++i) { *newtop = *bottom; newtop++; bottom++; } bottom = newbottom; top = newtop; capacity = newcapacity; } }; #endif
然后在我們的主程序中利用棧來(lái)分析四則運(yùn)算的規(guī)律(源代碼如下)
//Main.cpp #include"stack.h" #include<iostream> using namespace std; bool is_digit(char i) {//是數(shù)字 if (i == '1' || i == '2' || i == '3' || i == '4' || i == '5' || i == '6' || i == '7' || i == '8' || i == '9' || i == '0') return true; else return false; } bool is_operator(char i) {//是運(yùn)算符 if (i == '+' || i == '-' || i == '*' || i == '/' ||i=='=') return true; else return false; } bool get_priority(char pre,char cur) {//獲取兩個(gè)符號(hào)間的優(yōu)先級(jí),pre為靠前的字符,cur為靠后的字符 if ((pre == '+' || pre == '-') && (cur == '*' || cur == '/')) return false; else return true; } int do_operation(int lnum, char ope, int rnum) { if (ope == '+') return lnum + rnum; if (ope == '-') return lnum - rnum; if (ope == '*') return lnum * rnum; if (ope == '/') return lnum / rnum; } /* 1+2*3= 1+5*4-345+36/6*4+145*4*5-52= */ int main() { stack_int s; stack_int num_stack;//數(shù)據(jù)棧 stack_int ope_stack;//符號(hào)棧 char current_char; current_char = getchar(); bool overflag = false; while (overflag!=true) {//未遇到=號(hào)時(shí)不斷進(jìn)行四則運(yùn)算 if (is_digit(current_char)) {//遇到數(shù)字符號(hào)則將完整的數(shù)解析出來(lái)并保存于棧中 int num = 0; num = current_char - '0';//符號(hào)轉(zhuǎn)數(shù)字 current_char = getchar();//獲取下一個(gè)字符 while (is_digit(current_char)) { num = num * 10+(current_char-'0'); current_char = getchar(); } num_stack.push(num); //cout <<"the number is " <<num << endl; } if (current_char == ' ') {//空格則繼續(xù) current_char = getchar(); continue; } if (is_operator(current_char)) {//遇到運(yùn)算符則將運(yùn)算符保存于運(yùn)算符棧中 int ope = '?'; //如果當(dāng)前符號(hào)棧非空,則不斷根據(jù)優(yōu)先級(jí)決定是否進(jìn)行一次運(yùn)算 while((!ope_stack.isEmpty())&&(get_priority((char)ope_stack.gettop(),current_char))) {//如果前一個(gè)運(yùn)算符優(yōu)先級(jí)更高 ope_stack.pop(ope); //cout << "找到了前一個(gè)運(yùn)算符為: " << (char)ope << endl; int lnum, rnum; //符號(hào)棧非空時(shí),數(shù)據(jù)棧應(yīng)該至少有兩個(gè)數(shù),否則出錯(cuò) if (num_stack.isEmpty()) { cout << "數(shù)據(jù)棧缺失兩個(gè)元素,解析失?。? << endl; overflag = true; break; } num_stack.pop(rnum); if (num_stack.isEmpty()) { cout << "數(shù)據(jù)棧缺失一個(gè)元素,解析失敗!" << endl; overflag = true; break; } num_stack.pop(lnum); lnum = do_operation(lnum, (char)ope, rnum);//進(jìn)行運(yùn)算 num_stack.push(lnum); } if (current_char == '=') {//如果解析到=號(hào)了,解析完成 overflag = true; break; } ope_stack.push(current_char); current_char = getchar(); } } for (int i = 0; i < num_stack.getsize(); ++i) cout << num_stack[i] << "\t"; cout << endl; for (int i = 0; i < ope_stack.getsize(); ++i) cout << (char)ope_stack[i] << "\t"; return 0; }
這里需要注意一些問(wèn)題,首先,由于整數(shù)可能是多位數(shù),因此在遇到一個(gè)數(shù)字符號(hào)時(shí),我們可以通過(guò)循環(huán)將后面幾位全部找出,并將符號(hào)轉(zhuǎn)化為真正的數(shù)值。
第二個(gè)問(wèn)題就是有時(shí)候會(huì)出現(xiàn)表達(dá)式解析到等號(hào)了,卻有很多數(shù)沒(méi)進(jìn)行運(yùn)算,解決這個(gè)問(wèn)題的方法就是在
if (is_operator(current_char))
中使用while循環(huán),并將循環(huán)條件設(shè)置為棧非空且棧頂運(yùn)算符優(yōu)先級(jí)高于當(dāng)前讀入的運(yùn)算符(前提是=的優(yōu)先級(jí)小于任何運(yùn)算符)
while((!ope_stack.isEmpty())&&(get_priority((char)ope_stack.gettop(),current_char)))
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
c++連續(xù)輸入未知個(gè)數(shù)的數(shù)字操作
這篇文章主要介紹了c++連續(xù)輸入未知個(gè)數(shù)的數(shù)字操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-12-12C++ Boost Container庫(kù)示例詳細(xì)講解
Boost是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱。Boost庫(kù)是一個(gè)可移植、提供源代碼的C++庫(kù),作為標(biāo)準(zhǔn)庫(kù)的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開(kāi)發(fā)引擎之一,是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱2022-11-11基于QT5實(shí)現(xiàn)一個(gè)時(shí)鐘桌面
這篇文章主要介紹了利用QT5實(shí)現(xiàn)的一個(gè)時(shí)鐘桌面,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定的幫助,感興趣的小伙伴可以了解一下2022-01-01C++?基本數(shù)據(jù)類型中int、long等整數(shù)類型取值范圍及原理分析
這篇文章主要介紹了C++?基本數(shù)據(jù)類型中int、long等整數(shù)類型取值范圍及原理分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11java實(shí)現(xiàn)任意四則運(yùn)算表達(dá)式求值算法
這篇文章主要介紹了java實(shí)現(xiàn)任意四則運(yùn)算表達(dá)式求值算法,實(shí)例分析了基于java實(shí)現(xiàn)表達(dá)式四則運(yùn)算求值的原理與技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-04-04C語(yǔ)言多功能動(dòng)態(tài)通訊錄實(shí)現(xiàn)示例
這篇文章主要為大家介紹了C語(yǔ)言多功能動(dòng)態(tài)通訊錄實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01詳解C++設(shè)計(jì)模式編程中責(zé)任鏈模式的應(yīng)用
這篇文章主要介紹了C++設(shè)計(jì)模式編程中責(zé)任鏈模式的應(yīng)用,責(zé)任鏈模式使多個(gè)對(duì)象都有機(jī)會(huì)處理請(qǐng)求,從而避免請(qǐng)求的發(fā)送者和接收者之間的耦合關(guān)系,需要的朋友可以參考下2016-03-03