亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? expressionparser.java

?? jdkJDK實例寶典源碼講解了java中各種類的使用和語法規則
?? JAVA
字號:
package book.string;

/**
 * 一個簡單的表達式解析器,這個解析器可以計算由數字、運算符和括號組成的表達式的值,并能處理變量,
 * 為了處理簡單,本解析器只支持一個字母的變量,不區分變量字母的大小寫。因此,最多只能存儲26個變量。
 * 如果用戶的變量名長度大于一個字母,則只取第一個字母當作變量。
 */
public class ExpressionParser {

	// 4種標記類型
	/**	標記為空或者結束符	*/
	public static final int NONE_TOKEN = 0;
	/**	標記為分隔符*/
	public static final int DELIMITER_TOKEN = 1;
	/**	標記為變量*/
	public static final int VARIABLE_TOKEN = 2;
	/**	標記為數字*/
	public static final int NUMBER_TOKEN = 3;

	// 4種錯誤類型
	/**	語法錯誤	*/
	public static final int SYNTAX_ERROR = 0;
	/**	括號沒有結束錯誤	*/
	public static final int UNBALPARENS_ERROR = 1;
	/**	表達式為空錯誤	*/
	public static final int NOEXP_ERROR = 2;
	/**	被0除錯誤	*/
	public static final int DIVBYZERO_ERROR = 3;
	//針對四種錯誤類型,定義的四個錯誤提示
	public static final String[] ERROR_MESSAGES = { "Syntax Error", "Unbalanced Parentheses",
			"No Expression Present", "Division by Zero" };
	/**	表達式的結束標記*/
	public static final String EOE = "\0";
	
	/**	表達式字符串*/
	private String exp;  
	/**	解析器當前指針在表達式中的位置*/
	private int expIndex;   
	/**	解析器當前處理的標記*/
	private String token;  
	/**	解析器當前處理標記的類型*/
	private int tokenType; 

	/**	變量的數組*/  
	private double vars[] = new double[26];

	/**
	 * 解析一個表達式,返回表達式的值。
	 * @param expStr	表達式字符串
	 * @return
	 * @throws Exception
	 */  
	public double evaluate(String expStr) throws Exception {
		double result;
		this.exp = expStr;
		this.expIndex = 0;

		//獲取第一個標記
		this.getToken();
		if (this.token.equals(EOE)){
			//沒有表達式異常
			this.handleError(NOEXP_ERROR); // no expression present
		}

		//處理賦值語句
		result = this.parseAssign();
		//處理完賦值語句,應該就是表達式結束符,如果不是,則返回異常
		if (!this.token.equals(EOE)){  
			this.handleError(SYNTAX_ERROR);
		}

		return result;
	}

	/**
	 * 處理賦值語句
	 */  
	private double parseAssign() throws Exception {
		double result;//結果
		int varIndex;//變量下標
		String oldToken;//舊標記
		int oldTokenType;//舊標記的類型

		//如果標記類型是變量
		if (this.tokenType == VARIABLE_TOKEN) {
			// 保存當前標記  
			oldToken = new String(this.token);
			oldTokenType = this.tokenType;
			// 取得變量的索引,本解析器只支持一個字目的變量,
			//如果用戶的變量字母長度大于1,則取第一個字母當作變量  
			varIndex = Character.toUpperCase(this.token.charAt(0)) - 'A';
			
			//獲得下一個標記
			this.getToken();
			//如果當前標記不是等號=
			if (!this.token.equals("=")) {
				//回滾
				this.putBack();  
				// 不是一個賦值語句,將標記恢復到上一個標記  
				this.token = new String(oldToken);
				this.tokenType = oldTokenType;
			} else {
				//如果當前標記是等號=,即給變量賦值,形式如a = 3 + 5;
				//則計算等號后面表達式的值,然后將得到的值賦給變量
				this.getToken();
				//因為加減法的優先級最低,所以計算加減法表達式。
				result = this.parseAddOrSub();
				//將表達式的值賦給變量,并存在實例變量vars中。
				this.vars[varIndex] = result;
				//返回表達式的值
				return result;
			}
		}
		//如果當前標記類型不是變量,或者不是賦值語句,則用加減法計算表達式的值。
		return this.parseAddOrSub();
	}

	/**
	 * 計算加減法表達式
	 */ 
	private double parseAddOrSub() throws Exception {
		char op;//操作符
		double result;//結果
		double partialResult;//子表達式的結果
		//用乘除法計算當前子表達式的值
		result = this.parseMulOrDiv();
		//如果當前標記的第一個字母是加減號,則繼續進行加減法運算。
		while ((op = this.token.charAt(0)) == '+' || op == '-') {
			//取下一個標記
			this.getToken();
			//用乘除法計算當前子表達式的值
			partialResult = this.parseMulOrDiv();
			switch (op) {
			case '-':
				//如果是減法,則用已處理的子表達式的值減去當前子表達式的值
				result = result - partialResult;
				break;
			case '+':
				//如果是加法,用已處理的子表達式的值加上當前子表達式的值
				result = result + partialResult;
				break;
			}
		}
		return result;
	}

	/**
	 * 計算乘除法表達式,包括取模運算
	 */ 
	private double parseMulOrDiv() throws Exception {
		char op;//操作符
		double result;//結果
		double partialResult;//子表達式的結果
		//用指數運算計算當前子表達式的值
		result = this.parseExponent();
		//如果當前標記的第一個字母是乘、除或者取模運算符,則繼續進行乘除法運算。
		while ((op = this.token.charAt(0)) == '*' || op == '/' || op == '%') {
			//取下一個標記
			this.getToken();
			//用指數運算計算當前子表達式的值
			partialResult = this.parseExponent();
			switch (op) {
			case '*':
				//如果是乘法,則用已處理子表達式的值乘以當前子表達式的值
				result = result * partialResult;
				break;
			case '/':
				//如果是除法,先判斷當前子表達式的值是否為0,如果為0,則拋出被0除異常
				//除數不能為0
				if (partialResult == 0.0){
					this.handleError(DIVBYZERO_ERROR);
				}
				//除數不為0,則進行除法運算
				result = result / partialResult;
				break;
			case '%':
				//如果是取模運算,也要判斷當前子表達式的值是否為0
				//如果為0,則拋出被0除異常
				if (partialResult == 0.0){
					this.handleError(DIVBYZERO_ERROR);
				}
				//進行取模運算
				result = result % partialResult;
				break;
			}
		}
		return result;
	}

	/**
	 * 計算指數表達式
	 * @throws Exception
	 */  
	private double parseExponent() throws Exception {
		double result;//結果
		double partialResult;//子表達式的值
		double ex;//指數的底數
		int t;//指數的冪

		//用一元運算計算當前子表達式的值(底數)
		result = this.parseUnaryOperator();
		//如果當前標記為"^"運算符,則為指數計算
		if (this.token.equals("^")) {
			//獲取下一個標記,即獲取指數的冪
			this.getToken();
			partialResult = this.parseExponent();
			ex = result;
			if (partialResult == 0.0) {
				//如果指數的冪為0,則指數的值為1
				result = 1.0;
			} else {
				//否則,指數的值為個數為指數冪的底數相乘的結果。
				for (t = (int) partialResult - 1; t > 0; t--){
					result = result * ex;
				}
			}
		}
		return result;
	}

	/**
	 * 計算一元運算,+,-,表示正數和復數
	 */  
	private double parseUnaryOperator() throws Exception {
		double result;//結果
		String op;//操作符

		op = "";
		//如果當前標記類型為分隔符,而且分隔符的值等于+或者-。
		if ((this.tokenType == DELIMITER_TOKEN) && 
				this.token.equals("+") || this.token.equals("-")) {
			op = this.token;
			this.getToken();
		}
		//用括號運算計算當前子表達式的值
		result = this.parseBracket();
		if (op.equals("-")){
			//如果操作符為-,則表示負數,將子表達式的值變為負數
			result = -result;
		}

		return result;
	}

	/**
	 * 計算括號運算
	 */  
	private double parseBracket() throws Exception {
		double result;//結果
		//如果當前標記為左括號,則表示是一個括號運算
		if (this.token.equals("(")) {
			//取下一個標記
			this.getToken();
			//用加減法運算計算子表達式的值
			result = this.parseAddOrSub();
			//如果當前標記不等于右括號,拋出括號不匹配異常
			if (!this.token.equals(")")){
				this.handleError(UNBALPARENS_ERROR);
			}
			//否則取下一個標記
			this.getToken();
		} else {
			//如果當前標記不是左括號,表示不是一個括號運算,則用原子元素運算計算子表達式的值
			result = this.parseAtomElement();
		}

		return result;
	}

	/**
	 * 計算原子元素運算,包括變量和數字
	 * @return
	 * @throws Exception
	 */  
	private double parseAtomElement() throws Exception {
		double result = 0.0;//結果
		
		switch (this.tokenType) {
		case NUMBER_TOKEN:
			//如果當前標記類型為數字
			try {
				//將數字的字符串轉換成數字值
				result = Double.parseDouble(this.token);
			} catch (NumberFormatException exc) {
				this.handleError(SYNTAX_ERROR);
			}
			//取下一個標記
			this.getToken();
			break;
		case VARIABLE_TOKEN:
			//如果當前標記類型是變量,則取變量的值
			result = this.findVar(token);
			this.getToken();
			break;
		default:
			this.handleError(SYNTAX_ERROR);
			break;
		}
		return result;
	}

	/**
	 * 根據變量名獲取變量的值,如果變量名長度大于1,則只取變量的第一個字符
	 * @param vname	變量名
	 * @throws Exception
	 */ 
	private double findVar(String vname) throws Exception {
		//如果變量的第一個字符不是字母,則拋出語法異常
		if (!Character.isLetter(vname.charAt(0))) {
			handleError(SYNTAX_ERROR);
			return 0.0;
		}
		//從實例變量數組vars中取出該變量的值
		return vars[Character.toUpperCase(vname.charAt(0)) - 'A'];
	}

	/**
	 * 回滾,將解析器當前指針往前移到當前標記位置
	 */
	private void putBack() {
		if (this.token == EOE){
			return;
		}
		//解析器當前指針往前移動
		for (int i = 0; i < this.token.length(); i++) {
			this.expIndex--;
		}
	}

	/**
	 * 處理異常情況
	 * @param errorType	錯誤類型
	 * @throws Exception
	 */
	private void handleError(int errorType) throws Exception {
		//遇到異常情況時,根據錯誤類型,取得異常提示信息,將提示信息封裝在異常中拋出
		//可以考慮用自定義異常,而不用Exception
		throw new Exception(ERROR_MESSAGES[errorType]);
	}

	/**
	 * 獲取下一個標記
	 */  
	private void getToken() {
		//初始值
		this.tokenType = NONE_TOKEN;
		this.token = "";

		// 檢查表達式是否結束
		// 如果解析器當前指針已經到達了字符串的長度,則表明表達式已經結束,置當前標記的置為EOE
		if (this.expIndex == this.exp.length()) {
			this.token = EOE;
			return;
		}

		// 跳過表達式中的空白符 
		while (this.expIndex < this.exp.length()
				&& Character.isWhitespace(this.exp.charAt(this.expIndex))) {
			++this.expIndex;
		}

		// 再次檢查表達式是否結束 
		if (this.expIndex == this.exp.length()) {
			this.token = EOE;
			return;
		}
		
		//取得解析器當前指針指向的字符
		char currentChar = this.exp.charAt(this.expIndex);
		//如果當前字符是一個分隔符,則認為這是一個分隔符標記,給當前標記和標記類型賦值,并將指針后移
		if (isDelim(currentChar)) {  
			this.token += currentChar;
			this.expIndex++;
			this.tokenType = DELIMITER_TOKEN;
			
		} else if (Character.isLetter(currentChar)) {
			//如果當前字符是一個字母,則認為是一個變量標記。
			//將解析器指針往后移,直到遇到一個分隔符,之間的字符都是變量的組成部分
			while (!isDelim(currentChar)) {
				this.token += currentChar;
				this.expIndex++;
				if (this.expIndex >= this.exp.length()) {
					break;
				} else {
					currentChar = this.exp.charAt(this.expIndex);
				}
			}
			//設置標記類型為變量
			this.tokenType = VARIABLE_TOKEN;
			
		} else if (Character.isDigit(currentChar)) { 
			// 如果當前字符是一個數字,則認為當前標記的類型為數字
			// 將解析器指針往后移,直到遇到一個分隔符,之間的字符都是該數字的組成部分
			while (!isDelim(currentChar)) {
				this.token += currentChar;
				this.expIndex++;
				if (this.expIndex >= this.exp.length()){
					break;
				} else {
					currentChar = this.exp.charAt(this.expIndex);
				}
			}
			//設置標記類型為數字
			this.tokenType = NUMBER_TOKEN;
		} else { 
			//無法識別的字符,則認為表達式結束
			this.token = EOE;
			return;
		}
	}

	/**
	 * 判斷一個字符是否為分隔符。
	 * 表達式中的字符包括: 
	 * 加"+"、減"-"、乘"*"、除"/"、取模"%"、指數"^"、賦值"="、左括號"("、右括號")"
	 * @param c
	 * @return
	 */ 
	private boolean isDelim(char c) {
		if ((" +-/*%^=()".indexOf(c) != -1))
			return true;
		return false;
	}

	public static void main(String[] args) throws Exception {
		ExpressionParser test = new ExpressionParser();
		String exp1 = "a = 5.0";
		System.out.println("exp1(\"a = 4.0\") = " + test.evaluate(exp1));
		String exp2 = "b = 3.0";
		System.out.println("exp2(\"b = 3.0\") = " + test.evaluate(exp2));

		String exp3 = "(a+b) * (a-b)";
		System.out.println("exp3(\"(a+b) * (a-b)\") = " + test.evaluate(exp3));

		String exp4 = "3*5-4/2";
		System.out.println("exp4(\"3*5-4/2\") = " + test.evaluate(exp4));

		String exp5 = "(4-2)*((a+b)/(a-b))";
		System.out.println("exp5(\"(4-2)*((a+b)/(a-b))\") = " + test.evaluate(exp5));
		
		String exp6 = "5 % 2";
		System.out.println("exp6(\"5%2\") = " + test.evaluate(exp6));
		String exp7 = "3^2 * 5 + 4";
		System.out.println("exp7(\"3^2 * 5 + 4\") = " + test.evaluate(exp7));
		
		/**
		 * 一個簡單的表達式根據運算時的優先級從高到底為:
		 * (1)原子元素表達式,包括數字和變量;
		 * (2)括號表達式;
		 * (3)一元表達式,取數的負數;
		 * (4)指數表達式;
		 * (5)乘、除、取模表達式;
		 * (6)加、減表達式
		 * (7)賦值表達式;
		 * 因此,在計算一個表達式的值時,應該按優先級從高到底進行運算。
		 * 在本程序中,每個優先級的表達式的運算都用一個私有方法實現。在私有方法中,首先計算更高優先級的表達式。
		 * 即采用了類似遞歸調用的方式,盡管在evaluate方法中最先調用的是優先級最低的表達式的值,
		 * 但在實質上卻是優先級最高的表達式的私有方法最先被執行完。這就保證了表達式的運算是按照優先級從高到底的順序執行的。
		 */
	}
}

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
日韩亚洲欧美一区二区三区| 精品久久久久一区| 国产一区二区0| 一区二区三区精密机械公司| 久久婷婷成人综合色| 欧美性videosxxxxx| 国产精品一区专区| 香港成人在线视频| 亚洲欧洲av在线| 久久久亚洲高清| 欧美美女一区二区三区| 91视频免费播放| 国产精品66部| 麻豆国产精品官网| 亚洲成av人片| 亚洲免费观看高清| 国产精品全国免费观看高清| 日韩一区二区三区免费看 | 欧美性受极品xxxx喷水| 成人午夜大片免费观看| 另类调教123区| 日韩成人伦理电影在线观看| 亚洲一区二区三区四区在线观看 | 欧美日韩激情在线| 色悠悠久久综合| 91老司机福利 在线| 国产69精品久久99不卡| 激情国产一区二区| 激情综合色综合久久综合| 日韩福利视频导航| 日韩激情视频在线观看| 亚洲成a人片在线不卡一二三区| 国产精品伦理一区二区| 国产欧美一区二区精品婷婷| 精品91自产拍在线观看一区| 精品欧美一区二区三区精品久久| 欧美一区二区三区性视频| 欧美精品久久久久久久多人混战 | 国产精品麻豆久久久| 久久久久高清精品| 日本一区二区久久| 国产精品免费视频网站| 中文字幕精品一区二区三区精品| 国产免费成人在线视频| 国产精品欧美综合在线| 中文字幕在线不卡一区二区三区| 中文字幕亚洲区| 亚洲精品国产a| 亚洲成av人片在线观看| 日韩国产高清在线| 久久国产三级精品| 国产成人午夜视频| 99re6这里只有精品视频在线观看| 99国产精品久| 欧美日韩亚洲另类| 欧美一级生活片| 精品精品欲导航| 国产亚洲欧美激情| 亚洲视频在线观看一区| 亚洲国产wwwccc36天堂| 奇米一区二区三区| 国产精品一区二区久激情瑜伽| 国产精品中文字幕欧美| 色综合婷婷久久| 91麻豆精品国产91久久久更新时间| 日韩一区二区三区视频在线观看| 久久久不卡网国产精品二区| 亚洲日本电影在线| 日韩影院免费视频| 国产成人亚洲综合a∨婷婷| 色94色欧美sute亚洲线路二| 在线成人av影院| 久久精品一区蜜桃臀影院| 亚洲人成伊人成综合网小说| 偷拍自拍另类欧美| 国产99久久久精品| 欧美视频三区在线播放| 久久综合九色欧美综合狠狠| 国产精品家庭影院| 欧美aaaaa成人免费观看视频| 国产一区二区三区在线观看免费视频 | 日韩一二三区视频| 国产精品美女久久福利网站| 成人午夜电影网站| 欧美亚洲国产一卡| 久久久久久久久99精品| 亚州成人在线电影| 国产69精品久久久久777| 欧美日韩久久久一区| 国产午夜精品在线观看| 亚洲尤物在线视频观看| 成人妖精视频yjsp地址| 欧美日韩二区三区| 亚洲三级电影网站| 国产东北露脸精品视频| 欧美一区二区视频在线观看| 中文字幕一区二区三区不卡在线| 日韩国产欧美一区二区三区| 99久久99久久免费精品蜜臀| 精品日韩一区二区三区| 一区二区三区毛片| jlzzjlzz国产精品久久| 欧美电影免费观看高清完整版在| 亚洲欧美成人一区二区三区| 国产一区 二区 三区一级| 欧美日韩高清一区二区三区| 亚洲天天做日日做天天谢日日欢 | 欧洲中文字幕精品| 中文在线一区二区| 国产综合色视频| 日韩欧美国产精品一区| 亚洲大片一区二区三区| 97se亚洲国产综合自在线| 国产亚洲欧洲997久久综合| 美腿丝袜亚洲色图| 欧美精品18+| 天天射综合影视| 91黄色免费观看| 亚洲欧美成人一区二区三区| 波多野结衣91| 中文字幕免费一区| 风流少妇一区二区| 欧美国产成人在线| 国产成人精品一区二区三区网站观看| 欧美大片在线观看一区二区| 日本欧美一区二区在线观看| 欧美军同video69gay| 亚洲图片欧美综合| 91精品91久久久中77777| 亚洲激情图片小说视频| 日本韩国欧美三级| 亚洲免费观看高清完整版在线观看 | 日韩国产欧美一区二区三区| 欧美色偷偷大香| 亚洲高清三级视频| 欧美日韩免费观看一区二区三区| 亚洲欧美日韩国产综合在线 | 欧美精品一区二区三区高清aⅴ | 91视视频在线观看入口直接观看www | 粗大黑人巨茎大战欧美成人| 国产欧美日韩一区二区三区在线观看| 国产一区二区三区在线观看免费视频| 精品久久久久久久久久久院品网| 韩国av一区二区三区四区 | 亚洲伦理在线精品| 99久久综合狠狠综合久久| 日韩毛片精品高清免费| 91国产免费看| 石原莉奈一区二区三区在线观看| 欧美日韩国产首页| 久久av中文字幕片| 国产亚洲精品aa| 99re66热这里只有精品3直播| 亚洲卡通动漫在线| 欧美日产在线观看| 国产在线不卡一卡二卡三卡四卡| 国产日韩精品一区二区三区| jlzzjlzz亚洲女人18| 亚洲国产色一区| 日韩欧美一二区| 国产成人日日夜夜| 亚洲一区二区视频在线观看| 在线成人av网站| 国产69精品久久久久毛片| 樱花草国产18久久久久| 欧美一区二区在线播放| 国产久卡久卡久卡久卡视频精品| 1024国产精品| 欧美一级生活片| 国产mv日韩mv欧美| 亚洲综合色婷婷| 久久久久久久久伊人| 91麻豆自制传媒国产之光| 日韩高清在线一区| 亚洲国产精品成人综合| 欧美视频在线观看一区| 国产寡妇亲子伦一区二区| 亚洲一区在线观看免费| 精品成人a区在线观看| 色综合久久久久综合体| 老司机午夜精品99久久| 自拍偷自拍亚洲精品播放| 日韩欧美国产综合| 欧美做爰猛烈大尺度电影无法无天| 玖玖九九国产精品| 亚洲一区在线观看免费 | www.亚洲免费av| 青青青爽久久午夜综合久久午夜| 国产精品嫩草影院com| 欧美一区二区视频在线观看2020 | 精品国产91久久久久久久妲己| 91网页版在线| 亚洲国产精品传媒在线观看| 91麻豆免费在线观看| 九九视频精品免费| 亚洲午夜久久久| 国产精品―色哟哟| 精品免费一区二区三区| 欧美日韩日本视频| 99国产精品国产精品久久|