编译原理中中间代码生成---C语言实现
一.前言
今天有點(diǎn)累,就不想廢話了。直接進(jìn)入正題吧。(新增)第二次實(shí)驗(yàn)課還是這個(gè)內(nèi)容,不過新增了一個(gè)功能和再處理了一下其他bug。
二.內(nèi)容
一、授課內(nèi)容:
(一) 授課科目:編譯原理
(二) 授課內(nèi)容:實(shí)驗(yàn)三 代碼生成
(三) 授課類型:實(shí) 驗(yàn)
二、教學(xué)目的要求:
1.目的:通過設(shè)計(jì)、編制、調(diào)試一個(gè)具體的算術(shù)表達(dá)式求值的程序,加深對(duì)編譯器計(jì)算表達(dá)式方法的理解,并掌握從中綴式到后綴式的轉(zhuǎn)換方法。
2.要求:
(1)輸入一個(gè)算術(shù)表達(dá)式 ,求出對(duì)應(yīng)的后綴式(逆波蘭式);
(2)選擇數(shù)據(jù)結(jié)構(gòu)——棧結(jié)構(gòu),計(jì)算表示的值;
(3)輸出中綴式和求得的后綴式以及計(jì)算出的值;
(4)輸出后綴式的四元式(新增)
三、教學(xué)設(shè)想:
1.教學(xué)方法設(shè)想:舉例說明中綴式到后綴式的轉(zhuǎn)換方法,并把主要算法進(jìn)行解釋,然后讓學(xué)生進(jìn)行變程。實(shí)驗(yàn)為主。
2.教具運(yùn)用設(shè)想:多媒體(或遠(yuǎn)程教學(xué)軟件)。
四、教學(xué)過程:
1、課題:逆波蘭式求值。
2、算法:將中綴式放入char str[max]中,轉(zhuǎn)換后的逆波蘭式存放在char ex[max]中,根據(jù)優(yōu)先級(jí)和結(jié)合關(guān)系使用棧結(jié)構(gòu)完成后綴式的轉(zhuǎn)換,再根據(jù)逆波蘭式求值,(每個(gè)操作數(shù)后都加了一個(gè)‘#’作為特殊標(biāo)記,方便后面的計(jì)算)。
三.效果圖
(1)面對(duì)輸入非法報(bào)錯(cuò)提示:
(2)正常輸入
(3)小數(shù)輸入
(4)輸出后綴式的四元式(新增)
(5)面對(duì)括號(hào)不匹配,忽略括號(hào),直接算結(jié)果。(括號(hào)是英文狀態(tài)下的括號(hào),否則會(huì)被認(rèn)為是非法字符)(新增)
(5)用戶忘記輸入#結(jié)束標(biāo)志,系統(tǒng)自動(dòng)加上(新增)
四.代碼
#include<stdio.h> #include<math.h> #include<stdlib.h> #include<string.h> #define max 100 char ex[max]; /*存儲(chǔ)后綴表達(dá)式*/ void trans(){ /*將算術(shù)表達(dá)式轉(zhuǎn)化為后綴表達(dá)式*/char str[max]; /*存儲(chǔ)原算術(shù)表達(dá)式*/ //str數(shù)組循環(huán)變量,指針從0開始char stack[max]; /*作為棧使用*/char ch;int sum,i,j,t,top=0;printf("*****************************************\n");printf("*輸入一個(gè)求值的表達(dá)式,以#結(jié)束。*\n");printf("******************************************\n");printf("算數(shù)表達(dá)式:");i=0; /*獲取用戶輸入的表達(dá)式*/scanf("%c",&str[i]);while(str[i]!='#' && i!=max){i++;//1scanf("%c",&str[i]);} // strcat(str,"#");//加上的 //3sum=i;//sum為輸入字符長(zhǎng)度// printf("\n\t原來表達(dá)式:"); // for(j=0;j<=sum;j++)//7 // printf("%c",str[j]);t=1;//ex數(shù)組循環(huán)變量,指針從1開始i=0;//2ch=str[i]; // i++;while(ch!='#'){switch(ch){case '(': /*判定為左括號(hào)*/top++;//棧頂指針從1開始stack[top]=ch;break;case ')': /*判定為右括號(hào)*/while(stack[top]!='('){ ex[t]=stack[top];//)低于+ - * / ,出棧top--;t++;}top--; //(遇到) (出棧break;case '+': /*判定為加減號(hào)*/case '-': while(top!=0&&stack[top]!='('){ //+ - 運(yùn)算符低于 ),*,/運(yùn)算符,出棧ex[t]=stack[top];top--;t++;}top++;//+ - 運(yùn)算符高于( ,入棧stack[top]=ch;break;case '*': /*判定為乘除號(hào)*/ case '/': //*,/ 運(yùn)算符遇到* /運(yùn)算符,出棧while(stack[top]=='*'||stack[top]=='/'){ex[t]=stack[top];top--;t++;}//* / 運(yùn)算符高于( ) + - ,入棧top++;stack[top]=ch;//stack[top]=ch;//7break;case ' ':break; //遇到空格跳過default:if(ch>='0'&&ch<='9'||ch=='.'){/*判定為數(shù)字*/ // flag=0;while(ch>='0'&&ch<='9'){ ex[t]=ch;t++;//為ex數(shù)組下一個(gè)做準(zhǔn)備 i++;ch=str[i];// i++;//5//i++;}if(ch=='.'){//識(shí)別小數(shù) ex[t]=ch;t++;//為ex數(shù)組下一個(gè)做準(zhǔn)備 i++;ch=str[i];while(ch >='0'&&ch<='9'){ex[t]=ch;t++;//為ex數(shù)組下一個(gè)做準(zhǔn)備 i++;ch=str[i];}}i--;ex[t]='#';//每個(gè)操作數(shù)后都加了一個(gè)'#'作為特殊標(biāo)記,方便后面的計(jì)算t++;}else if(ch!='('||ch!=')'||ch!='+'||ch!='-'||ch!='*'||ch!='/') {printf("輸入非法字符!!\n");//新增的 應(yīng)對(duì)非法字符 exit(0); }}i++;ch=str[i];//i++;//6}while(top!=0){//運(yùn)算棧中有東西ex[t]=stack[top];t++;top--;}ex[t]='#';printf("\n\t原來表達(dá)式:");for(j=0;j<sum;j++)//7printf("%c",str[j]);printf("\n\t后綴表達(dá)式:",ex);for(j=1;j<t;j++)printf("%c",ex[j]); } void compvalue(){ /*計(jì)算后綴表達(dá)式的值*/double stack[max],d; /*作為棧使用*/char ch;int t=1,top=0; /*t為ex下標(biāo),top為stack下標(biāo)*/double _num;//小數(shù)部分int len;//小數(shù)個(gè)數(shù) double num; ch=ex[t];t++;while(ch!='#'){switch(ch){case '+':stack[top-1]=stack[top-1]+stack[top];top--;break;case '-':stack[top-1]=stack[top-1]-stack[top];top--;break;case '*':stack[top-1]=stack[top-1]*stack[top];top--;break;case '/':if(stack[top]!=0)stack[top-1]=stack[top-1]/stack[top];else{ printf("\n\t除零錯(cuò)誤!\n");exit(0); /*異常退出*/}top--;break;default: //新增 應(yīng)對(duì)小數(shù)點(diǎn) d=0;_num=0;len=0; num=0;while(ch>='0'&&ch<='9'){//整數(shù)部分 d=10*d+ch-'0'; /*將數(shù)字字符轉(zhuǎn)化為對(duì)應(yīng)的數(shù)值*/ ch=ex[t];t++;}if(ch=='.'){//小數(shù)部分 // t++;ch=ex[t];t++;while(ch >='0'&&ch<='9'){_num=_num*10+ch-'0'; //小數(shù)部分 len++;ch=ex[t];t++;}}num=d+_num/(pow(10,len));top++;stack[top]=num;}ch=ex[t];t++;}printf("\n\t計(jì)算結(jié)果:%g\n",stack[top]); } main(){ trans();compvalue();return 0; }新增的功能的完整代碼:(新增)
#include<stdio.h> #include<math.h> #include<stdlib.h> #include<string.h> #define max 100 typedef struct {char operate_sign;//算符double operator_1;//操作數(shù)1double operator_2;//操作數(shù)2double result;//結(jié)果 } S;//四元元式類型 S siyuan[max];//四元式數(shù)組,存放四元式 //四元數(shù)組下標(biāo)從0開始 int siyuan_flag=0;//記錄四元式數(shù) char ex[max]; /*存儲(chǔ)后綴表達(dá)式*/ void trans(){ /*將算術(shù)表達(dá)式轉(zhuǎn)化為后綴表達(dá)式*/char str[max]; /*存儲(chǔ)原算術(shù)表達(dá)式*/ //str數(shù)組循環(huán)變量,指針從0開始char stack[max]; /*作為棧使用*/char ch;//int flag_1=0;//左括號(hào)標(biāo)志位//int flag_2=0;//右括號(hào)標(biāo)志位int sum,i,j,t,top=0;printf("*****************************************\n");printf("*輸入一個(gè)求值的表達(dá)式,以#結(jié)束。*\n");printf("******************************************\n");printf("算數(shù)表達(dá)式:");i=0; /*獲取用戶輸入的表達(dá)式*///scanf("%c",&str[i]);//while(str[i]!='#' && i!=max){// i++;//1// scanf("%c",&str[i]);//} // strcat(str,"#");//加上的 //3gets(str);//獲取用戶輸入的表達(dá)式 //新增功能 用戶忘記輸入#結(jié)束標(biāo)志,系統(tǒng)自動(dòng)加上sum=strlen(str);//sum為輸入字符長(zhǎng)度strcat(str,"#");//如果用戶忘記輸入#結(jié)束標(biāo)志,系統(tǒng)自動(dòng)加上// printf("\n\t原來表達(dá)式:"); // for(j=0;j<=sum;j++)//7 // printf("%c",str[j]);t=1;//ex數(shù)組循環(huán)變量,指針從1開始i=0;//2ch=str[i]; // i++;while(ch!='#'){switch(ch){case '(': /*判定為左括號(hào)*/top++;//棧頂指針從1開始stack[top]=ch; // flag_1=1;break;case ')': /*判定為右括號(hào)*/// if(flag_1){while(stack[top]!='('){ ex[t]=stack[top];//)低于+ - * / ,出棧top--;t++;}// }// else{// printf("missing (\n");// }top--; //(遇到) (出棧break;case '+': /*判定為加減號(hào)*/case '-': while(top!=0&&stack[top]!='('){ //+ - 運(yùn)算符低于 ),*,/運(yùn)算符,出棧ex[t]=stack[top];top--;t++;}top++;//+ - 運(yùn)算符高于( ,入棧stack[top]=ch;break;case '*': /*判定為乘除號(hào)*/ case '/': //*,/ 運(yùn)算符遇到* /運(yùn)算符,出棧while(stack[top]=='*'||stack[top]=='/'){ex[t]=stack[top];top--;t++;}//* / 運(yùn)算符高于( ) + - ,入棧top++;stack[top]=ch;//stack[top]=ch;//7break;case ' ':break; //遇到空格跳過default:if(ch>='0'&&ch<='9'||ch=='.'){/*判定為數(shù)字*/ // flag=0;while(ch>='0'&&ch<='9'){ ex[t]=ch;t++;//為ex數(shù)組下一個(gè)做準(zhǔn)備 i++;ch=str[i];// i++;//5//i++;}if(ch=='.'){//識(shí)別小數(shù) ex[t]=ch;t++;//為ex數(shù)組下一個(gè)做準(zhǔn)備 i++;ch=str[i];while(ch >='0'&&ch<='9'){ex[t]=ch;t++;//為ex數(shù)組下一個(gè)做準(zhǔn)備 i++;ch=str[i];}}i--;ex[t]='#';//每個(gè)操作數(shù)后都加了一個(gè)'#'作為特殊標(biāo)記,方便后面的計(jì)算t++;}else if(ch!='('||ch!=')'||ch!='+'||ch!='-'||ch!='*'||ch!='/') {printf("輸入非法字符!!\n");//新增的 應(yīng)對(duì)非法字符 exit(0); }}i++;ch=str[i];//i++;//6}while(top!=0){//運(yùn)算棧中有東西ex[t]=stack[top];t++;top--;}ex[t]='#';printf("\n\t原來表達(dá)式:");for(j=0;j<sum;j++)//7printf("%c",str[j]);printf("\n\t后綴表達(dá)式:",ex);for(j=1;j<t;j++)printf("%c",ex[j]); }void compvalue(){ /*計(jì)算后綴表達(dá)式的值*/int i;//循環(huán)變量double stack[max],d; /*作為棧使用*/char ch;int t=1,top=0; /*t為ex下標(biāo),top為stack下標(biāo)*/double _num;//小數(shù)部分int len;//小數(shù)個(gè)數(shù) double num; ch=ex[t];t++;while(ch!='#'){switch(ch){case '+':siyuan[siyuan_flag].operate_sign ='+';//開始記錄四元式siyuan[siyuan_flag].operator_1=stack[top];siyuan[siyuan_flag].operator_2=stack[top-1];stack[top-1]=stack[top-1]+stack[top];siyuan[siyuan_flag].result=stack[top-1];siyuan_flag++;//為記錄下一個(gè)四元式做準(zhǔn)備top--;break;case '-':siyuan[siyuan_flag].operate_sign ='-';//開始記錄四元式siyuan[siyuan_flag].operator_1=stack[top];siyuan[siyuan_flag].operator_2=stack[top-1];stack[top-1]=stack[top-1]-stack[top];siyuan[siyuan_flag].result=stack[top-1];siyuan_flag++;//為記錄下一個(gè)四元式做準(zhǔn)備top--;break;case '*':siyuan[siyuan_flag].operate_sign ='*';//開始記錄四元式siyuan[siyuan_flag].operator_1=stack[top];siyuan[siyuan_flag].operator_2=stack[top-1];stack[top-1]=stack[top-1]*stack[top];siyuan[siyuan_flag].result=stack[top-1];siyuan_flag++;//為記錄下一個(gè)四元式做準(zhǔn)備top--;break;case '/':if(stack[top]!=0){siyuan[siyuan_flag].operate_sign ='/';//開始記錄四元式siyuan[siyuan_flag].operator_1=stack[top];siyuan[siyuan_flag].operator_2=stack[top-1];stack[top-1]=stack[top-1]/stack[top];siyuan[siyuan_flag].result=stack[top-1];siyuan_flag++;//為記錄下一個(gè)四元式做準(zhǔn)備}else{ printf("\n\t除零錯(cuò)誤!\n");exit(0); /*異常退出*/}top--;break;default: //新增 應(yīng)對(duì)小數(shù)點(diǎn) d=0;_num=0;len=0; num=0;while(ch>='0'&&ch<='9'){//整數(shù)部分 d=10*d+ch-'0'; /*將數(shù)字字符轉(zhuǎn)化為對(duì)應(yīng)的數(shù)值*/ ch=ex[t];t++;}if(ch=='.'){//小數(shù)部分 // t++;ch=ex[t];t++;while(ch >='0'&&ch<='9'){_num=_num*10+ch-'0'; //小數(shù)部分 len++;ch=ex[t];t++;}}num=d+_num/(pow(10,len));top++; //棧頂指針從1開始stack[top]=num;}ch=ex[t];t++;}printf("\n\t計(jì)算結(jié)果:%g\n",siyuan[siyuan_flag-1].result);printf("\n\t四元式:\n");for(i=0;i<siyuan_flag;i++){printf("\t(%c,%g,%g,%g)\n",siyuan[i].operate_sign,siyuan[i].operator_2,siyuan[i].operator_1,siyuan[i].result);} } main(){ trans();compvalue();return 0; }總結(jié)
以上是生活随笔為你收集整理的编译原理中中间代码生成---C语言实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 红队技巧:绕过ESET_NOD32抓取密
- 下一篇: c++中运算符重载