C++實(shí)現(xiàn)四則運(yùn)算器(無括號(hào))
本文實(shí)例為大家分享了C++實(shí)現(xiàn)無括號(hào)的四則運(yùn)算器的具體代碼,供大家參考,具體內(nèi)容如下
完成度更高的帶括號(hào)版本可以看C++實(shí)現(xiàn)四則運(yùn)算器(帶括號(hào))
對(duì)于無括號(hào)的計(jì)算器,實(shí)現(xiàn)起來比較容易,下面讓我們一步步實(shí)現(xiàn)。
舉例
首先明確需要實(shí)現(xiàn)怎樣的程序,對(duì)于無括號(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)算。這樣一來就需要將之前的運(yùn)算符以及運(yùn)算符左右的數(shù)保存起來,由于我們每次都是取前一個(gè)運(yùn)算符,符合后進(jìn)先出的條件,故可以選擇棧來存儲(chǔ)數(shù)據(jù)和符號(hào)。最好將數(shù)據(jù)和符號(hào)分開存儲(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則棧已空無法出棧
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
然后在我們的主程序中利用棧來分析四則運(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ù)解析出來并保存于棧中
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;
}
這里需要注意一些問題,首先,由于整數(shù)可能是多位數(shù),因此在遇到一個(gè)數(shù)字符號(hào)時(shí),我們可以通過循環(huán)將后面幾位全部找出,并將符號(hào)轉(zhuǎn)化為真正的數(shù)值。
第二個(gè)問題就是有時(shí)候會(huì)出現(xiàn)表達(dá)式解析到等號(hào)了,卻有很多數(shù)沒進(jìn)行運(yùn)算,解決這個(gè)問題的方法就是在
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)文章
Qt編寫自定義控件實(shí)現(xiàn)抽獎(jiǎng)轉(zhuǎn)盤
這篇文章主要為大家詳細(xì)介紹了Qt編寫自定義控件實(shí)現(xiàn)抽獎(jiǎng)轉(zhuǎn)盤,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
VC++文件監(jiān)控之FindFirstChangeNotification
因?yàn)镽eadDirectoryChangesW 上次測(cè)試發(fā)現(xiàn)不能多級(jí)目錄監(jiān)控,所以嘗試用FindFirstChangeNotification來實(shí)施文件監(jiān)控,需要的朋友可以參考下2019-04-04
詳解C++編程中標(biāo)記語句與復(fù)合語句的寫法
這篇文章主要介紹了C++編程中標(biāo)記語句與復(fù)合語句的寫法,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-01-01
C語言實(shí)現(xiàn)“幸運(yùn)數(shù)”的實(shí)例詳解
這篇文章主要介紹了C語言實(shí)現(xiàn)“幸運(yùn)數(shù)”的實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-07-07
Visual Studio C++指針靠前靠后的問題全面解析
這篇文章主要介紹了Visual Studio C++指針靠前靠后的問題全面解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04
C語言 鏈?zhǔn)蕉鏄浣Y(jié)構(gòu)詳解原理
二叉樹的鏈?zhǔn)酱鎯?chǔ)結(jié)構(gòu)是指,用鏈表來表示一棵二叉樹,即用鏈來指示元素的邏輯關(guān)系。通常的方法是鏈表中每個(gè)結(jié)點(diǎn)由三個(gè)域組成,數(shù)據(jù)域和左右指針域,左右指針分別用來給出該結(jié)點(diǎn)左孩子和右孩子所在的鏈結(jié)點(diǎn)的存儲(chǔ)地址2021-11-11

