布爾表達式


題目鏈接:http://noi.openjudge.cn/ch0303/6263/
總時間限制: 1000ms    內存限制: 65536kB
描述

輸入一個布爾表達式,請你輸出它的真假值。 比如:( V | V ) & F & ( F | V ) 
V表示true,F表示false,&表示與,|表示或,!表示非。 
上式的結果是F

輸入
輸入包含多行,每行一個布爾表達式,表達式中可以有空格,總長度不超過1000
輸出
對每行輸入,如果表達式為真,輸出"V",否則出來"F"
樣例輸入
( V | V ) & F & ( F| V)
!V | V & V & !F & (F | V ) & (!F | F | !V & V)
(F&F|V|!V&!F&!(F|F&V))
樣例輸出
F
V
V
分析:(來源:http://blog.csdn.net/INCINCIBLE/article/details/51151222?locationNum=5&fps=1)
原理很簡單,將中綴表達式轉化為前綴表達式在計算,只是代碼實現比較麻煩。
中綴轉前綴的步驟如下:
(1) 首先構造一個運算符棧(也可放置括號),運算符(以括號分界點)在棧內遵循越往棧頂優先級不降低的原則進行排列。
(2)從右至左掃描中綴表達式,從右邊第一個字符開始判斷:
如果當前字符是數字,則分析到數字串的結尾並將數字串直接輸出。
如果是運算符,則比較優先級。如果當前運算符的優先級大於等於棧頂運算符的優先級(當棧頂是括號時,直接入棧),則將運算符直接入棧;否則將棧頂運算符出棧並輸出,直到當前運算符的優先級大於等於棧頂運算符的優先級(當棧頂是括號時,直接入棧),再將當前運算符入棧。
如果是括號,則根據括號的方向進行處理。如果是右括號,則直接入棧;否則,遇左括號前將所有的運算符全部出棧並輸出,遇右括號后將左右的兩括號一起刪除。
(3) 重復上述操作(2)直至掃描結束,將棧內剩余運算符全部出棧並輸出,再逆綴輸出字符串。中綴表達式也就轉換為前綴表達式了。
 
右括號有最高的優先級,左括號優先級最低。

代碼:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<queue>
 5 #include<stack>
 6 #include<cstring>
 7 using namespace std;
 8 char calculate(char x, char y,char oper )// 計算 x oper y 
 9 {
10     bool a=(x=='V'),b=(y=='V'),ans;
11     if(oper=='|') ans=(a||b);
12     else if(oper=='&') ans=(a&&b);
13     return ans?'V':'F';
14 }
15 char reverse(char x) //將邏輯值取反。其實就是‘!’運算符 
16 {
17     if(x=='V')return 'F';
18     return 'V';
19 }
20 int main()
21 {
22     string in;
23     int i,j,len;
24     
25     while(getline(cin,in))
26     {
27         stack<char> Oper,num; //oper保存運算符,num保存運算結果 
28         queue<char> s;        //s就是前綴表達式 
29         len=in.length();
30         i=len;
31         in=" "+in;
32         while(i>0)// 從右往左,中綴表達式轉前綴表達式 
33         {
34             if(in[i]==' ')
35             {
36                 i--;continue;
37             }
38             else if(isalpha(in[i])) s.push(in[i--]);//isalpha()函數:如果參數是字母字符,函數返回非零值,否則返回零值
39             else if(in[i]=='!')  s.push(in[i--]);    //最高級的運算,直接進入表達式(這里主要是因為!運算符是單目運算符) 
40             else
41             {
42                 if(in[i]=='&'||in[i]=='|'||in[i]==')')  //低級運算,進棧 
43                     Oper.push(in[i--]);
44                 else if(in[i]=='(')  //一個括號結束,彈出中間的所有運算符 
45                 {  
46                     while(Oper.top()!=')')
47                     {
48                         s.push(Oper.top());
49                         Oper.pop();
50                     }
51                     Oper.pop();
52                     i--;
53                 }
54             }
55         }
56         while(!Oper.empty())  //棧中剩下的運算符 
57             s.push(Oper.top()),Oper.pop();
58         
59         while(!s.empty())  //計算前綴表達式 
60         {       
61             char ch=s.front(); s.pop();
62             if(isalpha(ch))  num.push(ch);
63             else Oper.push(ch);
64             if(!num.empty()&&!Oper.empty()&&Oper.top()=='!')  //單目運算符‘!’;
65             {   
66                 char x=num.top();
67                 num.pop();Oper.pop();
68                 num.push(reverse(x));
69             }
70             else if(num.size()>=2&&!Oper.empty())  //雙目運算符 
71             {
72                 char oper=Oper.top(),x,y;
73                 Oper.pop();
74                 x=num.top();num.pop();
75                 y=num.top();num.pop();
76                 num.push(calculate(x,y,oper));
77             }
78         }
79         cout<<num.top()<<endl;
80     }
81 }

 

另外,可以參考http://www.ithao123.cn/content-10400535.html

 第二種思路,遞歸求解。

代碼來源:北大郭煒老師MOOC課程的代碼。可以參考中綴表達式計算這篇文章的分析。

  1 #include <iostream>
  2 #include <cstdio>
  3 using namespace std;
  4 
  5 char wholeExp[1500];//表示整個表達式的字符串 
  6 int ptr = 0;
  7 
  8 bool exp();//讀入一個表達式並返回其值 
  9 bool item();//讀入一個項並返回其值 
 10 bool factor();//讀入一個因子並返回其值 
 11 bool notExp();//將表達式取反的操作
 12 /*
 13 表達式:由單獨的"項"或者"項"與"|"運算符連接形成;
 14 項:由單獨的"因子"或"因子"和&運算符連接而成;
 15 因子:可以是單獨的V或F,也可以是用括號括起來的"表達式"。
 16 */
 17 int main()
 18 {
 19     freopen("6263.in","r",stdin);
 20     int t = 1;//表示第t個測試樣例 
 21     char c;
 22     int i = 0;
 23     int n = EOF + 1;
 24     while(n != EOF) 
 25     {
 26         n = scanf("%c",&c);
 27         if( n == EOF || c == '\n') 
 28         {
 29             wholeExp[i] = '\0';
 30             if( i > 0) 
 31             {
 32                 ptr = 0;
 33                 bool res = exp();
 34                 if (res) { printf("Expression %d: V\n",t++); }
 35                 else printf("Expression %d: F\n",t++);
 36                 /*if (res) { printf("V\n",t++); }
 37                 else printf("F\n",t++);*/
 38             }
 39             i = 0;
 40         }
 41         else if( c != ' ') wholeExp[i++] = c;
 42     }
 43     return 0;
 44 }
 45 
 46 bool exp() //讀入一個表達式並返回其值 
 47 {
 48     bool result = item();
 49     while(wholeExp[ptr] == '|' ) 
 50     {
 51         ++ptr;
 52         result = result | item();//注意:這里的或運算不能用C語言邏輯或運算符,因為邏輯或運算符在編譯器處理完以后有短路特性,可能會忽略后面的輸入。比如(V|V)&F,若是用邏輯或,可能只掃描到第一個V就返回邏輯真,不再繼續往后掃描了。但是其實應該是邏輯假。  53     }
 54     return result;
 55 }
 56 
 57 bool item() //讀入一個項並返回其值  
 58 {
 59     bool result = factor();
 60     while(wholeExp[ptr] == '&') 
 61     {
 62         ++ptr;
 63         result = result & factor();//同樣地,這個地方不能用邏輯與運算符,否則會錯忽略后面應該掃描的東西從而返回錯誤的結果。比如(F&V)|V。  64     }
 65     return result;
 66 }
 67 
 68 bool factor() //讀入一個因子並返回其值 
 69 {
 70     bool result;
 71     switch( wholeExp[ptr]) 
 72     {
 73         case 'F':
 74             ++ptr;
 75             return false;
 76             break;
 77         case 'V':
 78             ++ptr;
 79             return true;
 80             break;
 81         case '(':
 82             ++ptr;
 83             result = exp();
 84             ++ptr; //skip ')'
 85             return result;
 86             break;
 87         case '!':
 88             result = notExp();
 89             return result;
 90             break;
 91     }
 92 }
 93 
 94 bool notExp() //將表達式取反的操作
 95 {
 96     //wholeExp[ptr] == '!' when called;
 97     ptr++;
 98     bool result;
 99     switch(wholeExp[ptr]) 
100     {
101         case 'F':
102             ++ptr;
103             return true;
104             break;
105         case 'V':
106             ++ptr;
107             return false;
108             break;
109         case '(':
110             ++ptr;
111             result = exp();
112             ++ptr; //skip ')'
113             return !result;
114             break;
115         case '!':
116             result = notExp();
117             return !result;
118             break;
119     }
120 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM