国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

簡(jiǎn)易計(jì)算器(詳解用棧實(shí)現(xiàn)算術(shù)表達(dá)式求值)

這篇具有很好參考價(jià)值的文章主要介紹了簡(jiǎn)易計(jì)算器(詳解用棧實(shí)現(xiàn)算術(shù)表達(dá)式求值)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

[問題描述]

一個(gè)算術(shù)表達(dá)式是由操作數(shù)(operand)、運(yùn)算符(operator)和界限符(delimiter)組成的。假設(shè)操作數(shù)是正實(shí)數(shù),運(yùn)算符只含加減乘除等四種運(yùn)算符,界限符只含左右括號(hào)如:6+15*(21-8/4)。編程利用“運(yùn)算符優(yōu)先法”求算術(shù)表達(dá)式的值。

[基本要求]

(1)讀入一個(gè)合法的算術(shù)表達(dá)式,輸出正確的結(jié)果。

(2)考慮算法的健壯性,當(dāng)表達(dá)式錯(cuò)誤時(shí),要給出錯(cuò)誤原因的提示。

(4)實(shí)現(xiàn)非整數(shù)的處理。

實(shí)現(xiàn)一個(gè)簡(jiǎn)易計(jì)算器,我們要做的事情主要有兩個(gè)。第一個(gè)是判斷輸入的表達(dá)式是否正確;第二個(gè)是若表達(dá)式正確,則求出運(yùn)算結(jié)果。

1、判斷算術(shù)表達(dá)式是否正確

判斷 算術(shù)表達(dá)式是否正確要充分考慮各種可能的錯(cuò)誤情況,這里 我列舉出了幾種錯(cuò)誤情況:
(1) 括號(hào)不匹配(遺漏了左括號(hào)或右括號(hào));
(2)出現(xiàn)非法字符,如 !/?& 等;
(3)運(yùn)算符重復(fù),例如1+3**2 中乘號(hào)重復(fù);
(4)缺少用于運(yùn)算的數(shù),例如 (/3+2)+1 、*3+4、2+4/?。
除了第一種情況外,其他情況都可以用 if 語(yǔ)句很容易地判斷出來(lái);但要判斷括號(hào)是否匹配 就要運(yùn)用到。這里算法思想是:依次讀取表達(dá)式中的字符,若是非括號(hào)字符,則忽略。若是左括號(hào),則壓棧。若是右括號(hào),則與棧頂元素進(jìn)行匹配,若棧為空,則說(shuō)明右括號(hào)多余(即遺漏了左括號(hào)),報(bào)錯(cuò)返回;若匹配成功,則棧頂元素彈棧(即一個(gè)左括號(hào)和一個(gè)右括號(hào)完成了配對(duì)),繼續(xù)讀取下一個(gè)字符。直到表達(dá)式遍歷完畢,若此時(shí)棧不為空,則說(shuō)明有左括號(hào)還沒有匹配(即遺漏了右括號(hào)),報(bào)錯(cuò)返回;若棧為空,則說(shuō)明括號(hào)全部配對(duì)成功。

2、求出運(yùn)算結(jié)果

我們平常寫出的算式對(duì)于我們來(lái)說(shuō)是比較直觀和容易計(jì)算的,這種形式的表達(dá)式被稱為中綴表達(dá)式,但對(duì)于計(jì)算機(jī)而言,中綴表達(dá)式是無(wú)法直接進(jìn)行計(jì)算的。因?yàn)樵谟?jì)算過(guò)程中,我們不是讀到一個(gè)運(yùn)算符就立即計(jì)算,而是要與后面的運(yùn)算符進(jìn)行優(yōu)先級(jí)比較,以決定先算哪個(gè),而計(jì)算機(jī)卻做不到這點(diǎn),但我們可以棧來(lái)解決這個(gè)問題。具體實(shí)現(xiàn)方法如下:

首先,我們創(chuàng)建兩個(gè)棧 Num 和 Sign ,Num 保存運(yùn)算數(shù),Sign 保存運(yùn)算符號(hào)。然后,我們依次讀取表達(dá)式中的字符,若為運(yùn)算數(shù),則轉(zhuǎn)化為對(duì)應(yīng)數(shù)值壓入?Num棧中;若為運(yùn)算符,則和 Sign棧的棧頂運(yùn)算符進(jìn)行優(yōu)先級(jí)比較:若棧頂運(yùn)算符優(yōu)先級(jí)低于當(dāng)前運(yùn)算符,則將當(dāng)前運(yùn)算符壓入Sign棧中;若棧頂運(yùn)算符優(yōu)先級(jí)高于當(dāng)前運(yùn)算符,則 Sign棧彈出運(yùn)算符、Num棧彈出兩個(gè)運(yùn)算數(shù),進(jìn)行相應(yīng)計(jì)算,并將計(jì)算結(jié)果壓入 Num棧中;但若為 ‘)’ ,則需要將對(duì)應(yīng)左括號(hào)從 Sign棧中彈出,這就需要完成兩個(gè)括號(hào)內(nèi)的所有運(yùn)算,計(jì)算方式同上。直到表達(dá)式遍歷完畢,Num棧的棧頂元素即為最終結(jié)果。

算法思想如此,實(shí)現(xiàn)起來(lái)卻并不簡(jiǎn)單。例如,我們要將運(yùn)算數(shù)轉(zhuǎn)化為對(duì)應(yīng)數(shù)值,由于包括浮點(diǎn)數(shù)的情況,這個(gè)實(shí)現(xiàn)起來(lái)就比較復(fù)雜。以下是我的程序代碼:

# include <iostream>
# include <algorithm>
# include <string>
# include <stack>
using namespace std;
bool CheckOperator(char c);             //判斷是否為運(yùn)算符
bool CheckMatch(string str);            //判斷算式是否正確
int Prior(char c);                      //求符號(hào)的優(yōu)先級(jí)
bool CheckPrior(char c1, char c2);      //通過(guò)優(yōu)先級(jí)判斷是否入棧
float CalNum(float a, float b, char c); //求單項(xiàng)運(yùn)算的結(jié)果
float CalResult(string str);            //計(jì)算最終結(jié)果
int main()
{
	string str;
	cout << "請(qǐng)輸入計(jì)算式:";
	cin >> str;
	str.append("#");           //作為算式的終止符
	bool t = CheckMatch(str);  //判斷算式是否正確
	if (t) {
		float r = CalResult(str);  //計(jì)算最終結(jié)果
		cout << "計(jì)算結(jié)果為:" << r << endl;
	}
	return 0;
}

bool CheckOperator(char c)   //判斷是否為運(yùn)算符
{
	if (c == '+' || c == '-' || c == '*' || c == '/') {
		return true;
	}
	else {
		return false;
	}
}

bool CheckMatch(string str)  //判斷算式是否正確
{
	if (CheckOperator(str[0]) || CheckOperator(str[str.length() - 2])) {
		//算式首尾位置出現(xiàn)運(yùn)算符
		cout << "算術(shù)表達(dá)式錯(cuò)誤!\n" << "原因:缺少用于運(yùn)算的數(shù)" << endl;
		return false;
	}
	//判斷括號(hào)及運(yùn)算符輸入是否正確
	stack<char>S;   //用于存放括號(hào)的棧
	for (int i = 0; i < str.length() - 1; i++) {
		if (!CheckOperator(str[i]) && (str[i] < 48 || str[i]>57) && str[i] != '(' && str[i] != ')' && str[i] != '.') {
			//出現(xiàn)非法字符
			cout << "算術(shù)表達(dá)式錯(cuò)誤!\n" << "原因:出現(xiàn)非法字符" << str[i] << endl;
			return false;
		}
		if (CheckOperator(str[i]) && CheckOperator(str[i + 1])) {
			//運(yùn)算符重復(fù)
			cout << "算術(shù)表達(dá)式錯(cuò)誤!\n" << "原因:運(yùn)算符" << str[i] << "重復(fù)" << endl;
			return false;
		}
		if (str[i] == '(')
		{
			S.push(str[i]);
			if (CheckOperator(str[i + 1])) {
				//'('后缺少用于運(yùn)算的數(shù)
				cout << "算術(shù)表達(dá)式錯(cuò)誤!\n" << "原因:缺少用于運(yùn)算的數(shù)" << endl;
				return false;
			}
		}
		if (str[i] == ')')
		{
			if (S.empty()) {
				//若棧已為空,說(shuō)明遺漏左括號(hào)
				cout << "算術(shù)表達(dá)式錯(cuò)誤!\n" << "原因:遺漏左括號(hào)" << endl;
				return false;
			}
			S.pop();
		}
	}
	if (!S.empty()) {
		//若此時(shí)棧還不為空,說(shuō)明遺漏右括號(hào)
		cout << "算術(shù)表達(dá)式錯(cuò)誤!\n" << "原因:遺漏右括號(hào)" << endl;
		return false;
	}
	return true;
}

int Prior(char c)    //返回符號(hào)的優(yōu)先級(jí)
{
	switch (c)
	{
	case '#': return 0;
	case '+':
	case '-': return 1;
	case '*':
	case '/': return 2;
	case ')': return 3;
	case '(': return 4;
	}
}

bool CheckPrior(char c1, char c2) //通過(guò)優(yōu)先級(jí)判斷是否入棧(c1當(dāng)前,c2棧中)
{
	if (c2 == '(') {
		return true;  //同意進(jìn)棧
	}
	int p1 = Prior(c1);
	int p2 = Prior(c2);
	if (p1 > p2) {   //當(dāng)前運(yùn)算符的優(yōu)先級(jí)較高
		return true; //同意進(jìn)棧
	}
	else {
		return false; //不同意進(jìn)棧
	}
}

float CalNum(float a, float b, char c) //求單項(xiàng)運(yùn)算的結(jié)果
{
	switch (c)
	{
	case '+': return a + b;
	case '-': return a - b;
	case '*': return a * b;
	case '/': return a / b;
	}
}

float CalResult(string str) //計(jì)算最終結(jié)果
{
	stack<float>Num;  //保存運(yùn)算數(shù)的棧
	stack<char>Sign;  //保存運(yùn)算符的棧
	Sign.push('#');
	float a, b;
	for (int i = 0; i < str.length() && !Sign.empty(); i++) {
		if (str[i] >= 48 && str[i] <= 57) {
			//若為數(shù)字
			a = float(str[i]) - 48;           //a保存由字符轉(zhuǎn)化為數(shù)字后的值
			int j;
			//將字符轉(zhuǎn)化為數(shù)字
			for (j = i + 1; (str[j] == '.') || (j < str.length() && str[j] >= 48 && str[j] <= 57); j++) {
				if (str[j] == '.') {
					//若為小數(shù)
					int k, l;
					for (k = j + 1, l = 1; k < str.length() && str[k] >= 48 && str[k] <= 57; k++, l++) {
						b = float(str[k]) - 48;
						a = a + b * pow(10, -l);
					}
					j = k;
					break;
				}
				else {
					b = float(str[j]) - 48;
					a = a * 10 + b;
				}
			}
			i = j - 1;
			Num.push(a);  //運(yùn)算數(shù)進(jìn)棧
		}
		else {
			//若為運(yùn)算符
			char c1 = str[i];  //c1當(dāng)前運(yùn)算符
			while (1) {
				char c2 = Sign.top();             //c2棧頂運(yùn)算符
				if (c2 == '#' && str[i] == '#') { //若遇到起始符,并且str也到達(dá)末尾
					Sign.pop();
					break;
				}
				bool t = CheckPrior(c1, c2);     //通過(guò)優(yōu)先級(jí)判斷是否入棧(c1當(dāng)前,c2棧中)
				if (t) {
					//同意運(yùn)算符進(jìn)棧
					int s = Prior(str[i]);
					if (s == 3) {
						//出現(xiàn)')',優(yōu)先進(jìn)行括號(hào)內(nèi)的運(yùn)算
						while ((c2 = Sign.top()) != '(') {
							a = Num.top();  //取出第一個(gè)數(shù)
							Num.pop();
							b = Num.top();  //取出第二個(gè)數(shù)
							Num.pop();
							float r = CalNum(b, a, c2);  //求單項(xiàng)運(yùn)算的結(jié)果
							Sign.pop();
							Num.push(r);    //運(yùn)算得到的新數(shù)進(jìn)棧
						}
						Sign.pop();
					}
					else {
						Sign.push(c1); //運(yùn)算符進(jìn)棧
					}
					break;
				}
				else {
					//不同意運(yùn)算符進(jìn)棧,執(zhí)行運(yùn)算操作
					a = Num.top();
					Num.pop();
					b = Num.top();
					Num.pop();
					float r = CalNum(b, a, c2); //求單項(xiàng)運(yùn)算的結(jié)果
					Sign.pop();
					Num.push(r);
				}
			}
		}
	}
	return Num.top();
}

?運(yùn)行結(jié)果:

請(qǐng)輸入計(jì)算式:((1+2*3)-1)/2+1.5*3
計(jì)算結(jié)果為:7.5
請(qǐng)輸入計(jì)算式:(1+3)*4)-2
算術(shù)表達(dá)式錯(cuò)誤!
原因:遺漏左括號(hào)

總結(jié):實(shí)現(xiàn)簡(jiǎn)易計(jì)算器主要運(yùn)用了棧的數(shù)據(jù)結(jié)構(gòu)。其中主要的操作是通過(guò)遍歷算數(shù)表達(dá)式實(shí)現(xiàn)的,所以程序總的時(shí)間復(fù)雜度約為O(n),n是指算數(shù)表達(dá)式的長(zhǎng)度。對(duì)于正在練習(xí)棧的小伙伴們來(lái)說(shuō),簡(jiǎn)易計(jì)算器是很不錯(cuò)的練習(xí)項(xiàng)目。

以上是我個(gè)人的學(xué)習(xí)成果,很高興能與大家分享。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-718742.html

到了這里,關(guān)于簡(jiǎn)易計(jì)算器(詳解用棧實(shí)現(xiàn)算術(shù)表達(dá)式求值)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Android開發(fā):kotlin語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易計(jì)算器

    Android開發(fā):kotlin語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易計(jì)算器

    輸入兩個(gè)數(shù)字,可選加減乘除操作符,并計(jì)算顯示對(duì)應(yīng)結(jié)果 隨系統(tǒng)切換語(yǔ)言 可對(duì)結(jié)果進(jìn)行四舍五入操作 界面布局:activity_main.xml文件代碼 字符定義:string.xml文件代碼 邏輯實(shí)現(xiàn):MainActivity.kt 文件代碼 方法一(偷懶): 復(fù)制文件到對(duì)應(yīng)位置 方法二: 1. 繪制界面 2. 編寫邏輯

    2023年04月08日
    瀏覽(28)
  • 【Servlet學(xué)習(xí)三】實(shí)現(xiàn)一個(gè)內(nèi)存版本的簡(jiǎn)易計(jì)算器~

    【Servlet學(xué)習(xí)三】實(shí)現(xiàn)一個(gè)內(nèi)存版本的簡(jiǎn)易計(jì)算器~

    目錄 一、方式1:使用form表單的形式(不推薦) ??1、前端代碼:HTML文件 ??2、后端代碼:Calculator_form.java文件 ??3、最終效果 二、方式2:使用ajax形式(最常用重點(diǎn)?。。。???1、前端代碼:HTML文件 ??2、后端代碼:Calculator_ajax.java文件 ??3、最終效果 ?注意: (1)前端

    2024年02月12日
    瀏覽(21)
  • 單片機(jī)實(shí)現(xiàn)簡(jiǎn)易計(jì)算器功能,附有解析與代碼

    單片機(jī)實(shí)現(xiàn)簡(jiǎn)易計(jì)算器功能,附有解析與代碼

    目錄 首先分為根據(jù)要實(shí)現(xiàn)的功能來(lái)選擇硬件和軟件: 硬件部分 軟件部分 輸入部分: 計(jì)算部分: 連續(xù)計(jì)算: 源代碼示例: 主函數(shù): 鍵盤輸入: LCD1602顯示: 蜂鳴器: 延時(shí)函數(shù): 首先我們要實(shí)現(xiàn)的功能有:多位顯示,小數(shù)計(jì)算,連續(xù)計(jì)算,符號(hào)按錯(cuò)修改,, 用到LCD1602顯示

    2024年02月09日
    瀏覽(21)
  • Java算法題 給一個(gè)字符串表達(dá)式,實(shí)現(xiàn)一個(gè)基本計(jì)算器,返回計(jì)算結(jié)果

    題目: 考點(diǎn):棧 解題思路: 使用 2 個(gè)棧,一個(gè) stack_nums 用來(lái)保存計(jì)算過(guò)程的操作數(shù),一個(gè) stack_symbol 用來(lái)保存運(yùn)算符。 在HashMap中,指定加減優(yōu)先級(jí)為1,乘除優(yōu)先級(jí)為2 循環(huán)遍歷字符串s, 操作符入棧: 若當(dāng)前字符為\\\'+\\\', \\\'-\\\', \\\'*\\\', \\\'/\\\', \\\'(\\\' 時(shí),壓入運(yùn)算符棧 stack_symbol, 操作數(shù)入

    2024年02月07日
    瀏覽(19)
  • 4.2 實(shí)現(xiàn)基于棧的表達(dá)式求值計(jì)算器(難度4/10)

    4.2 實(shí)現(xiàn)基于棧的表達(dá)式求值計(jì)算器(難度4/10)

    本作業(yè)主要考察:解釋器模式的實(shí)現(xiàn)思想/棧結(jié)構(gòu)在表達(dá)式求值方面的絕對(duì)優(yōu)勢(shì) C++數(shù)據(jù)結(jié)構(gòu)與算法夯實(shí)基礎(chǔ)作業(yè)列表 通過(guò)棧的應(yīng)用,理解特定領(lǐng)域設(shè)計(jì)的關(guān)鍵作用,給大家眼前一亮的感覺。深刻理解計(jì)算機(jī)語(yǔ)言和人類語(yǔ)言完美結(jié)合的杰作。是作業(yè)中的上等作品,是數(shù)據(jù)結(jié)構(gòu)與

    2024年02月10日
    瀏覽(23)
  • JAVA制作的簡(jiǎn)易計(jì)算器——傻瓜計(jì)算器

    JAVA制作的簡(jiǎn)易計(jì)算器——傻瓜計(jì)算器

    用JAVA編寫的傻瓜計(jì)算器 作用: 1.可以實(shí)現(xiàn)加法、減法、乘法、除法簡(jiǎn)單運(yùn)算且是單一運(yùn)算,不可混合使用。 2.CE為清除鍵 3.沒有小數(shù)點(diǎn)O(∩_∩)O 思路: 創(chuàng)建JFrame窗口,設(shè)置標(biāo)題,創(chuàng)建JButton,創(chuàng)建文本框JTextField用作顯示。 先定義各種按鈕類型,用作成員。定義窗口方法對(duì)窗口

    2024年02月11日
    瀏覽(18)
  • java 簡(jiǎn)易計(jì)算器

    java 簡(jiǎn)易計(jì)算器

    1.使用Java圖形界面組件設(shè)計(jì)軟件,界面如圖所示。 2.軟件能夠滿足基本的“加、減、乘、除”等運(yùn)算要求。 3.程序代碼清晰,語(yǔ)法規(guī)范,結(jié)構(gòu)合理,邏輯正確。 先分析,計(jì)算器大概是由三個(gè)大部分組成的:菜單欄,顯示框,按鈕。 所以定義一個(gè)類cal繼承JFrame。 我們定義完后

    2024年02月01日
    瀏覽(26)
  • JAVA簡(jiǎn)易計(jì)算器

    JAVA簡(jiǎn)易計(jì)算器

    1.C是清除鍵,功能是將之前所輸入的數(shù)字、計(jì)算結(jié)果等信息全部歸零 2.CE,清除當(dāng)前輸入的數(shù)據(jù)或符號(hào) 3.單擊MS存儲(chǔ)當(dāng)前顯示值,可以理解為放到存儲(chǔ)區(qū) 4.單擊MC清除存儲(chǔ)區(qū)數(shù)值 5.單擊MR將存儲(chǔ)區(qū)數(shù)據(jù)顯示到屏幕上 6.M+:當(dāng)前顯示的數(shù)與存儲(chǔ)區(qū)的數(shù)相加 7.M-:當(dāng)前顯示的數(shù)與存儲(chǔ)

    2024年02月09日
    瀏覽(26)
  • QT 簡(jiǎn)易計(jì)算器

    QT 簡(jiǎn)易計(jì)算器

    2024年02月09日
    瀏覽(25)
  • Android Studio實(shí)現(xiàn)簡(jiǎn)易計(jì)算器(帶橫豎屏,深色淺色模式,更該按鈕顏色,selector,style的使用)

    Android Studio實(shí)現(xiàn)簡(jiǎn)易計(jì)算器(帶橫豎屏,深色淺色模式,更該按鈕顏色,selector,style的使用)

    目錄 前言 運(yùn)行結(jié)果: 運(yùn)行截屏(p50e) ?apk文件 源碼文件 ?項(xiàng)目結(jié)構(gòu) 總覽 MainActivity.java drawable 更改圖標(biāo)的方法: blackbutton.xml bluebuttons.xml greybutton.xml orangebuttons.xml whitebutton.xml layout 布局文件 ?豎屏: 橫屏: values ? ? ? ? colors.xml strings.xml styles 淺色模式 深色模式 themes.xml

    2024年02月06日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包