朋的博客

          MySQL資料,Java技術,管理思想,博弈論,Ajax,XP極限編程,H.264,HEVC,HDR
          隨筆 - 86, 文章 - 59, 評論 - 1069, 引用 - 0
          數據加載中……

          算術表達式的實現

          /****算術表達式的分析和計算,文件名:Exp_c.cpp****
          ***** 在VC6和Dev-C下調試通過 ****/
          #include
          #include
          #include
          #include
          #include

          #define EXP_LEN 100 //定義輸入字符緩沖區的長度

          /*------------出錯代碼的宏定義--------------*/
          #define INVALID_CHAR_TAIL 0 //表達式后跟有非法字符
          #define CHAR_AFTER_RIGHT 1 //右括號后連接非法字符
          #define LEFT_AFTER_NUM 2 //數字后非法直接連接左括號
          #define INVALID_CHAR_IN 3 //表達式中含有非法字符
          #define NO_RIGHT 4 //缺少右括號
          #define EMPTY_BRACKET 5 //括號內無表達式
          #define UNEXPECTED_END 6 //預期外的算術表達式結束

          using namespace std;

          const string ErrCodeStr[]= //表達式出錯信息
          {
          "表達式后跟有非法字符!",
          "右括號后連接非法字符!",
          "數字后非法直接連接左括號!",
          "表達式中含有非法字符!",
          "缺少右括號!",
          "括號內無表達式或表達式不完整!",
          "表達式非法結束或表達式不完整!"
          };

          static char expr[EXP_LEN]; //算術表達式輸入字符緩沖區
          static int pos; //字符指示器標志:用來保存正在分析的字符的位置
          static jmp_buf errjb; //出錯跳轉緩沖器

          //********以下是函數聲明*********
          //產生式“E -> T+E | T-E | T”的函數,用來分析加減算術表達式。
          int E_AddSub();
          //產生式“T -> F*T | F/T | F”的函數,用來分析乘除算術表達式。
          int T_MulDiv();
          //產生式“F -> i | (E)”的函數,用來分析數字和括號內的表達式。
          int F_Number();
          //出錯處理函數,可以指出錯誤位置,出錯信息。
          void Error(int ErrCode);

          int main()
          {
          int ans; //保存算術表達式的計算結果
          bool quit=false; //是否退出計算

          do
          {
          //在此設定一個跳轉目標,如果本程序的其他函數調用longjmp,
          //執行指令就跳轉到這里,從這里繼續執行。
          if(setjmp(errjb)==0) //如果沒有錯誤
          {
          pos=0; //初始化字符指示器為0,即指向輸入字符串的第一個字符。

          cout<<"請輸入一個算術表達式(輸入“Q”或“q”退出):"< cin>>expr; //輸入表達式,填充表達式字符緩沖區。

          if(expr[0]=='q'||expr[0]=='Q')
          //檢查第一個字符,是否退出?
          quit=true;

          else
          {
          //調用推導式“E -> T+E | T-E | T”的函數,
          //從起始符號“E”開始推導。
          ans=E_AddSub();

          //此時,程序認為對表達式的語法分析已經完畢,下面判斷出錯的原因:

          //如果表達式中的某個右括號后直接跟著數字或其他字符,
          //則報錯,因為數字i不屬于FOLLOW())集。
          if(expr[pos-1]==')'&&expr[pos]!='\0')
          Error(CHAR_AFTER_RIGHT);

          //如果表達式中的某個數字或右括號后直接跟著左括號,
          //則報錯,因為左括號不屬于FOLLOW(E)集。
          if(expr[pos]=='(')
          Error(LEFT_AFTER_NUM);

          //如果結尾有其他非法字符
          if(expr[pos]!='\0')
          Error(INVALID_CHAR_TAIL);

          cout<<"計算得出表達式的值為:"< }
          }
          else
          {
          //setjmp(errjb)!=0的情況:
          cout<<"請重新輸入!"< }
          }
          while(!quit);

          return 0;
          }

          //產生式“E -> T+E | T-E | T”的函數,用來分析加減算術表達式。
          //返回計算結果
          int E_AddSub()
          {
          int rtn=T_MulDiv(); //計算加減算術表達式的左元

          while(expr[pos]=='+'||expr[pos]=='-')
          {
          int op=expr[pos++]; //取字符緩沖區中當前位置的符號到op
          int opr2=T_MulDiv();//計算加減算術表達式的右元

          //計算求值
          if(op=='+') //如果是"+"號
          rtn+=opr2; //則用加法計算
          else //否則(是"-"號)
          rtn-=opr2; //用減法計算
          }
          return rtn;
          }

          //推導式“T -> F*T | F/T | F”的函數,用來分析乘除算術表達式。
          //返回計算結果
          int T_MulDiv()
          {
          int rtn=F_Number(); //計算乘除算術表達式的左元

          while(expr[pos]=='*'||expr[pos]=='/')
          {
          int op=expr[pos++]; //取字符緩沖區中當前位置的符號到op
          int opr2=F_Number();//計算乘除算術表達式的右元

          //計算求值
          if(op=='*') //如果是"*"號
          rtn*=opr2; //則用乘法計算
          else //否則(是"\"號)
          rtn/=opr2; //用除法計算
          }
          return rtn;
          }

          //產生式“F -> i | (E)”的函數,用來分析數字和括號內的表達式。
          int F_Number()
          {
          int rtn; //聲明存儲返回值的變量

          //用產生式F->(E)推導:
          if(expr[pos]=='(') //如果字符緩沖區當前位置的符號是"("
          {
          pos++; //則指示器加一指向下一個符號
          rtn=E_AddSub(); //調用產生式“E -> T+E | T-E | T”的分析函數

          if(expr[pos++]!=')')//如果沒有與"("匹配的")"
          Error(NO_RIGHT);//則產生錯誤

          return rtn;
          }


          if(isdigit(expr[pos]))//如果字符緩沖區中當前位置的字符為數字
          {
          //則用產生式F -> i推導
          //把字符緩沖區中當前位置的字符串轉換為整數
          rtn=atoi(expr+pos);
          //改變指示器的值,跳過字符緩沖區的數字部分,找到下一個輸入字符。
          while(isdigit(expr[pos]))
          pos++;
          }
          else //如果不是數字則產生相應的錯誤
          {
          if(expr[pos]==')') //如果發現一個")"
          Error(EMPTY_BRACKET); //則是括號是空的,即括號內無算術表達式。
          else if(expr[pos]=='\0') //如果此時輸入串結束
          Error(UNEXPECTED_END); //則算術表達式非法結束
          else
          Error(INVALID_CHAR_IN); //否則輸入字符串中含有非法字符
          }

          return rtn;
          }

          //出錯處理函數,輸入錯誤代碼,可以指出錯誤位置,出錯信息。
          void Error(int ErrCode)
          {
          cout<<'\r'; //換行
          while(pos--)
          cout<<' '; //打印空格,把指示錯誤的"^"移到輸入字符串的出錯位置
          cout<<"^ 語法錯誤 !!! "
          < <
          longjmp(errjb,1); //跳轉到main()函數中的setjmp調用處,并設置setjmp(errjb)的返回值為1
          }

          研究ing,這段時間重新復習數據結構了……

          posted on 2005-09-21 21:23 benchensz 閱讀(1787) 評論(1)  編輯  收藏 所屬分類: Java技術

          評論

          # re: 算術表達式的實現[未登錄]  回復  更多評論   

          是錯的啊
          2008-11-15 22:04 | hehe
          主站蜘蛛池模板: 湘潭市| 普洱| 军事| 濉溪县| 湘潭市| 吴江市| 武宣县| 镇赉县| 江油市| 石河子市| 慈利县| 宁强县| 靖边县| 沁水县| 东阳市| 成都市| 商洛市| 泾阳县| 乌鲁木齐县| 青海省| 环江| 武邑县| 门头沟区| 农安县| 饶阳县| 敖汉旗| 和平区| 平江县| 哈尔滨市| 博湖县| 平凉市| 双桥区| 静乐县| 萨迦县| 浦城县| 湘潭市| 日土县| 万荣县| 塔河县| 磐石市| 濉溪县|