c語言課程設計--輸入一個表達式_輸出其結果_第1頁
已閱讀1頁,還剩16頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

1、<p>  課 程 設 計 報 告</p><p>  課程名稱 C語言程序設計 </p><p>  課題名稱 輸入一個表達式,輸出其結果 </p><p>  專 業(yè) 通信工程 </p><p>  班 級 通信1101

2、 </p><p>  2012年 6月 29 日</p><p><b>  湖南工程學院</b></p><p>  課 程 設 計 任 務 書</p><p>  課程名稱 C語言程序設計 </p><p>  課 題 輸入一個表達式,輸出其結果 </p&g

3、t;<p>  專業(yè)班級 通信1101 </p><p>  任務書下達日期 2012 年 6 月 15 日</p><p>  任務完成日期 2012 年 6 月 29日</p><p><b>  一、設計思想</b></p><p>  兩種算法首

4、先都要建立兩個棧,一個是存放操作數(shù)的數(shù)棧OdStack,一個是存放運算符的符棧OpStack。數(shù)棧采用double型的用來存放浮點數(shù),符棧采用char型的用來存放運算符,由于考慮到運算符有優(yōu)先級的問題,所以事先做了一個Type用來存儲運算符的優(yōu)先級。棧建立好了之后做棧的相關操作,初始化棧,入棧,出棧,看棧頂。其中入棧要判滿,出棧和看棧頂要判空。</p><p>  中綴轉后綴再計算的算法。</p>

5、<p>  此算法的基本思路是先將中綴表達式轉換成后綴表達式,之后再利用后綴表達式的算法對表達式進行計算。</p><p>  首先,用一個char數(shù)組將中綴表達式讀入,對數(shù)組中的每一個元素進行處理,區(qū)分哪些是數(shù),哪些是運算符。如果是數(shù)元素(或小數(shù)點元素),則依次存入用來存儲后綴表達式的char數(shù)組,直到一個整合數(shù)存完之后用空格將其與后面的元素分開。如果是運算符元素,則根據(jù)當前運算符的優(yōu)先級和棧里面的運

6、算符的優(yōu)先級進行處理。如果棧內元素的優(yōu)先級小于當前元素的優(yōu)先級或者棧內為空,則將當前運算符入棧;如果棧內元素的優(yōu)先級大于等于當前元素的,則依次將出棧元素存入后綴表達式,并用空格將其與后面的元素分開,直到棧內元素的優(yōu)先級小或者棧內為空。對于左括號來說,無條件進棧,并只在有右括號出現(xiàn)的時候才有可能出棧。對于右括號來說,無條件讓棧內元素出棧,直到左括號出棧。依次將每個元素進行處理直到中綴表達式索引完畢。至此,已經(jīng)實現(xiàn)了將中綴表達式轉換成了后綴

7、表達式,在數(shù)組的最后加上結束符以便下一步的調用。</p><p>  第二步,讀出后綴表達式并進行計算。如果索引到空格則將索引標志后推1位。之后要先對char型的數(shù)字元素進行整合,從后綴表達式中依次取出數(shù)字元素(連同小數(shù)點)存入一個新的char型數(shù)組,直到一整個數(shù)取完后通過atof函數(shù)將char型轉換成浮點型存入數(shù)棧,并將新數(shù)組初始化用來存儲下一個數(shù)。如果是索引到運算符,則在數(shù)棧中出棧兩個數(shù)字與當前運算符進行運算

8、,先出棧的數(shù)字放在運算符后面,后出棧的數(shù)字放在運算符的前面,將運算以后的結果再次存入數(shù)棧。依次進行計算直到后綴表達式索引完畢。此時對棧內剩余元素進行操作。每在符棧出棧一個運算符,就從數(shù)棧出棧兩個數(shù)進行計算,算法同上,將運算以后的結果再次存入數(shù)棧。循環(huán)操作直到符棧???,此時數(shù)棧出棧元素即為最后結果。</p><p><b>  二、算法流程圖</b></p><p> 

9、 中綴轉后綴再計算的算法分兩個流程,第一步是中綴表達式轉換成后綴表達式;</p><p>  圖1 中綴轉后綴算法流程圖</p><p>  第二步是將后綴表達式進行計算輸出。</p><p>  三.調試分析過程描述</p><p>  1.首先,設計的程序每運行一次只能進行一次計算:</p><p>  int m

10、ain()</p><p><b>  {</b></p><p>  printf(" ******歡迎進入小型計算器******\n請輸入算術表達式:");</p><p>  char str[N]; </p><p>

11、  double result; </p><p>  scanf("%s",str);</p><p>  result=Calu(str); </p><p>  printf("輸出計算結果: %f\n",result);&l

12、t;/p><p><b>  }</b></p><p>  為了改進程序,我在主函數(shù)里加了一個循環(huán):</p><p>  int main()</p><p><b>  {</b></p><p><b>  int a;</b></p>

13、<p>  printf(" ******歡迎進入小型計算器******\n請輸入算術表達式:");</p><p>  for(a=0;;a++)</p><p><b>  {</b></p><p>  char str[N]; &

14、lt;/p><p>  double result; </p><p>  scanf("%s",str);</p><p>  result=Calu(str); </p><p>  printf("輸出計算結

15、果: %f\n",result);</p><p>  printf("〉〉");</p><p><b>  }</b></p><p><b>  }</b></p><p>  為了人性化原則,想什么時候退出計算就退出計算,我對程序又進行了改進,輸入字母e退出計算

16、:</p><p>  if(exp1[index1]=='(') </p><p><b>  {</b></p><p>  tempsign.Type=exp1[index1];</p><p>  tempsign.level=-1;

17、OpPush(&OpStack,&tempsign);</p><p><b>  index1++;</b></p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b>&l

18、t;/p><p>  if(exp1[index1]==')') </p><p><b>  {</b></p><p>  while(OpPeek(&OpStack).level != -1) {</p><p

19、>  exp2[index2]=OpPop(&OpStack).Type;</p><p><b>  index2++;</b></p><p>  exp2[index2]=' '; index2++;</p><p><b>  }</b></p&

20、gt;<p>  OpPop(&OpStack); index1++;</p><p><b>  }</b></p><p>  else if(exp1[index1]=='e') /*exit(0);</p><p

21、><b>  else</b></p><p><b>  Error();</b></p><p><b>  }</b></p><p><b>  四.程序運行結果</b></p><p><b>  五.程序源代碼</b>

22、;</p><p>  #include<stdio.h></p><p>  #include<stdlib.h></p><p>  #include<stdlib.h></p><p>  #define N 100/*N為數(shù)棧和表達式數(shù)組容量*/</p><p> 

23、 #define M 100/*M為符棧和其他數(shù)組容量*/</p><p>  typedef struct /*定義運算符類型,level為運算符等級*/</p><p><b>  {</b></p><p>  char Type;</p><p>  int l

24、evel;</p><p>  }Type;/*做一個Type用來存儲運算符的優(yōu)先級*/</p><p>  typedef struct /*定義存放操作數(shù)的數(shù)棧*/</p><p><b>  {</b></p><p>  double stack[N];<

25、;/p><p><b>  int top;</b></p><p><b>  }OdStack;</b></p><p>  typedef struct /*定義存放運算符的符棧*/</p><p><b>  {</b></p

26、><p>  Type stack[M];</p><p><b>  int top;</b></p><p><b>  }OpStack;</b></p><p>  void Init_OdStack(OdStack *s) /*定義初始化數(shù)棧*/</p><p

27、><b>  { </b></p><p>  (*s).top=0; </p><p>  } //初始化棧頂,賦等級0值</p><p>  void OdPush(OdStack *s,double n) /*進數(shù)棧*/</p><p><b>  {</b&g

28、t;</p><p>  if((*s).top==N-1) /*如果棧滿則報錯退出程序*/</p><p><b>  Error();</b></p><p><b>  else</b></p><p><b>  {</b><

29、/p><p>  (*s).stack[(*s ).top]=n;//將數(shù)棧中的值變?yōu)閚</p><p>  (*s).top++;//棧頂?shù)闹导?</p><p><b>  }</b></p><p><b>  }</b></p><p>  double

30、OdPop(OdStack *s) /*定義出數(shù)棧*/</p><p><b>  {</b></p><p>  if ((*s).top==0) /*如果??談t報錯退出程序*/</p><p><b>  Error();</b></p>

31、<p><b>  else</b></p><p><b>  {</b></p><p>  (*s).top--;//棧頂?shù)闹禍p1</p><p>  return (*s).stack[(*s).top];//返回數(shù)棧中的值</p><p><b> 

32、 }</b></p><p><b>  }</b></p><p>  void Init_OpStack(OpStack *s) /*定義初始化符棧*/</p><p><b>  { </b></p><p>  (*s).top=0; </p&g

33、t;<p>  }//初始化棧頂,賦等級0值</p><p>  void OpPush(OpStack *s,Type *sign) /*定義進符棧*/</p><p><b>  {</b></p><p>  if((*s).top==M-1) /*如果棧滿則報錯退

34、出程序*/</p><p><b>  Error();</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  (*s).stack[(*s).top]=*sign;</p><p>  (

35、*s).top++;//棧頂?shù)闹导?</p><p><b>  }</b></p><p><b>  }</b></p><p>  Type OpPop(OpStack *s) /*定義出符棧*/</p><p><b>  {</b

36、></p><p>  if ((*s).top==0) /*??談t報錯退出程序*/</p><p><b>  Error();</b></p><p><b>  else</b></p><p><b>  {</b><

37、/p><p>  (*s).top--;</p><p>  return (*s).stack[(*s).top];//返回符棧的值</p><p><b>  }</b></p><p><b>  }</b></p><p>  Type OpPeek(OpStack

38、*s) /*定義看符棧頂*/</p><p><b>  {</b></p><p><b>  Type ren;</b></p><p>  if ((*s).top==0) /*判???,空則賦等級0值*/</p><p>&l

39、t;b>  {</b></p><p>  ren.level=0;//運算優(yōu)先級為等級0值</p><p>  return ren;</p><p><b>  }</b></p><p><b>  else</b></p><p>  re

40、turn (*s).stack[(*s).top-1];</p><p><b>  }</b></p><p>  int Error() /*報錯函數(shù)*/</p><p><b>  {</b></p><p>  printf(&q

41、uot;輸入錯誤!\n");</p><p><b>  exit(1);</b></p><p><b>  }</b></p><p>  int Com(char tempch) /*定義運算符等級*/</p><p><b>  {&

42、lt;/b></p><p>  int level; /*給不同運算符定級*/</p><p>  switch (tempch)</p><p><b>  {</b></p><p><b>  case '+':</b>

43、;</p><p>  case '-':level=1;break;</p><p><b>  case '*':</b></p><p>  case '/':level=2;break;//乘除優(yōu)先加減</p><p><b>  }</b>&

44、lt;/p><p>  return level;//返回運算符等級</p><p><b>  }</b></p><p>  double Oper(double a,double b,char tempch) /*定義運算過程*/</p><p><b>  {</b></p&g

45、t;<p>  double ren;</p><p>  switch (tempch) /*對不同運算符執(zhí)行運算并返回結果*/</p><p><b>  {</b></p><p>  case '+':ren=b+a;break;</p><p>

46、  case '-':ren=b-a;break;</p><p>  case '*':ren=b*a;break;</p><p>  case '/':ren=b/a;break;</p><p><b>  }</b></p><p>  return ren;&l

47、t;/p><p><b>  }</b></p><p>  double Calu(char *exp1)//</p><p><b>  {</b></p><p>  OdStack OdStack; /*定義數(shù)棧*/</p><p>

48、  OpStack OpStack; /*定義符棧*/</p><p>  Type tempsign; /*定義Type型運算符*/</p><p>  char exp2[N],tempexp[M],tempch; /*定義后綴表達式數(shù)組exp2,整合數(shù)組tempexp,tempch為運算符*/</

49、p><p>  int index1,index2,tempindex;/*index1為主要索引,index2為次要索引,tempindex為附加索引*/</p><p>  double number,a,b,c; /*number為整合數(shù),a、b、c為運算數(shù)*/</p><p>  Init_OdStack(&OdSt

50、ack); /*初始化數(shù)棧*/</p><p>  Init_OpStack(&OpStack); /*初始化符棧*/</p><p>  index1=0; /*初始化索引,附加索引*/</p><p><b>  index2=0;</b>&

51、lt;/p><p>  tempindex=0;</p><p>  tempexp[0]='\0'; /*初始化整合數(shù)組*/</p><p>  while(exp1[index1]!='\0') /*處理初始表達式轉化成后綴表達式*/</p><p>&

52、lt;b>  {</b></p><p>  if((exp1[index1]>='0'&& exp1[index1]<='9')) /*處理數(shù)字元素*/</p><p><b>  {</b></p><p>  while((exp1[index1]&g

53、t;='0'&& exp1[index1]<='9') || exp1[index1]=='.' )</p><p><b>  { </b></p><p>  exp2[index2]=exp1[index1]; /*連續(xù)的數(shù)字元素不分開并依次存入后綴表達式*/</p><

54、;p><b>  index2++;</b></p><p><b>  index1++;</b></p><p><b>  }</b></p><p>  exp2[index2]=' '; /*結束后用空格將其與后面的元素分開*/</

55、p><p><b>  index2++;</b></p><p><b>  }</b></p><p>  else//不是數(shù)字或小數(shù)點元素</p><p><b>  { </b></p><p>  if(exp1[index1]=='

56、+'||exp1[index1]=='-'||exp1[index1]=='*'||exp1[index1]=='/') //是運算符/*處理運算符元素*/</p><p><b>  {</b></p><p>  tempsign.Type=exp1[index1];</p

57、><p>  tempsign.level=Com(tempsign.Type); /*求運算符等級*/</p><p>  while(OpPeek(&OpStack).level>=tempsign.level) /*當棧中符的等級大于當前等級時則取出符存入后綴表達式*/</p><p><b>  {</b>

58、</p><p>  exp2[index2]=OpPop(&OpStack).Type;</p><p><b>  index2++;</b></p><p>  exp2[index2]=' '; /*每兩個運算符之間用空格分開*/</p><p><b&

59、gt;  index2++;</b></p><p><b>  }</b></p><p>  OpPush(&OpStack,&tempsign); /*結束后將當前運算符入棧*/</p><p><b>  index1++;</b></p><p>

60、;<b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  if(exp1[index1]=='(') /*如果是左括號則無條件進棧*/</p><p><b&g

61、t;  {</b></p><p>  tempsign.Type=exp1[index1];</p><p>  tempsign.level=-1; /*進棧后等級為-1,以便遇到右括號出棧*/</p><p>  OpPush(&OpStack,&tempsign);</p><p>&l

62、t;b>  index1++;</b></p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  if(exp1[index1]==')')

63、 /*右括號規(guī)則*/</p><p><b>  {</b></p><p>  while(OpPeek(&OpStack).level != -1) /*遇到右括號則不斷出棧存入后綴表達式直到尋到左括號*/</p><p><b>  {</b></p><p>  ex

64、p2[index2]=OpPop(&OpStack).Type;</p><p><b>  index2++;</b></p><p>  exp2[index2]=' '; /*每兩個運算符之間用空格分開*/</p><p><b>  index2++;</b></p>

65、<p><b>  }</b></p><p>  OpPop(&OpStack); /*直到遇到左括號將左括號出棧*/</p><p><b>  index1++;</b></p><p><b>  }</b></p><p>  else

66、if(exp1[index1]=='e') </p><p><b>  exit(0);</b></p><p>  else/*如果輸入了非法字符則報錯退出程序*/</p><p><b>  Error();</b></p>&l

67、t;p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }</b></p><p>  while(OpPeek(&OpStack).level !=0)

68、 /*原表達式結束后對棧進行操作直到棧空*/</p><p><b>  {</b></p><p>  if(OpPeek(&OpStack).level==-1) /*如果有為用掉的左括號則報錯退出程序*/</p><p><b>  Error();</b></p><p>

69、;  exp2[index2]=OpPop(&OpStack).Type;</p><p><b>  index2++;</b></p><p>  exp2[index2]=' ';</p><p><b>  index2++;</b></p><p><b>

70、;  }</b></p><p>  exp2[index2]='\0' ; /*最后結束后綴表達式*/</p><p>  index1=0; /*索引歸零,開始計算結果*/</p><p>  while(exp2[index1]

71、!= '\0') /*循環(huán)直到后綴表達式結束*/</p><p><b>  {</b></p><p>  if((exp2[index1]>='0'&& exp2[index1]<='9')) /*整合數(shù)并入棧*/</p&g

72、t;<p><b>  {</b></p><p>  while((exp2[index1]>='0'&& exp2[index1]<='9') || exp2[index1]=='.' ) /*用附加索引判斷數(shù)的長度并整合入整合數(shù)組*/</p><p><b>

73、;  {</b></p><p>  tempexp[tempindex]=exp2[index1];</p><p><b>  index1++;</b></p><p>  tempindex++;</p><p><b>  }</b></p><p> 

74、 tempexp[tempindex]='\0'; /*結束整合數(shù)組*/</p><p>  if( tempexp[0] != '\0') /*如果整合數(shù)組有值則轉換成浮點型存入數(shù)棧*/</p><p><b>  {</b></p><p>  number = atof

75、(tempexp);</p><p>  OdPush(&OdStack ,number);</p><p>  tempexp[0]='\0'; /*入棧后初始化整合數(shù)組和附加索引以便下次整合*/</p><p>  tempindex=0;</p><p><b>  }</b

76、></p><p><b>  }</b></p><p><b>  else</b></p><p><b>  {</b></p><p>  if(exp2[index1]==' ') /*判斷空格,有則跳過*/</p>

77、<p><b>  {</b></p><p>  while(exp2[index1]==' ')</p><p><b>  index1++;</b></p><p><b>  }</b></p><p><b>  else&l

78、t;/b></p><p><b>  {</b></p><p>  if(exp2[index1]=='+'||exp2[index1]=='-'||exp2[index1]=='*'||exp2[index1]=='/') /*對加減乘除進行運算*/</p><p>

79、<b>  {</b></p><p>  a=OdPop(&OdStack);</p><p>  b=OdPop(&OdStack);</p><p>  tempch=(exp2[index1]);</p><p>  c=Oper(a,b,tempch);</p><p>

80、  OdPush(&OdStack,c); /*將計算結果放入數(shù)棧*/</p><p><b>  index1++;</b></p><p><b>  }</b></p><p><b>  }</b></p><p><b>  }<

81、/b></p><p><b>  }</b></p><p>  return OdPop(&OdStack) ; /*彈出結果*/</p><p><b>  }</b></p><p>  int main()</p><p><b&g

82、t;  {</b></p><p><b>  int a;</b></p><p>  printf(" ******歡迎進入小型計算器******\n字母e結輸入束計算!\n請輸入算術表達式:");</p><p>  for(a=0;;a++)</p><p><

83、b>  {</b></p><p>  char str[N]; /*定義數(shù)組以存儲表達式*/</p><p>  double result; /*定義result以存儲結果*/ </p><p>  scanf("%s",

84、str);</p><p>  result=Calu(str); /*計算表達式并返回結果值*/ </p><p>  printf("輸出計算結果: %f\n",result);</p><p>  printf("〉〉");</p><p><

85、;b>  }</b></p><p><b>  }</b></p><p><b>  六.總結</b></p><p>  通過對本次程序的學習和編寫,了解了關于電腦對計算表達式的計算過程,并且學會了從中綴變成后綴的方法。在本次編寫的時候遇到了不少問題和麻煩,通過對C語言的復習和對算法的分析,最終也一

86、一解決。也是這次的編寫讓我更加認識到算法的重要性和算法的趣味性,特別是中綴轉后綴如直接計算的差別體現(xiàn)了算法的發(fā)展歷程和一個好的算法對于程序的關鍵性。通過本次編寫也意識到了清晰的程序結構對于以后的更新和更改都有很重要的意義,方便的利用函數(shù)體來定義一些算法比直接在主函數(shù)中設置算法要好的多。更關鍵的是了解到了棧的性質和用途,一些適當?shù)膯栴}使用棧不僅僅可以迎刃而解,有時還能夠起到事倍功半的效果。從棧的構建、定義到入棧、出棧、看棧頂?shù)鹊牟僮骶帉懀?/p>

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
  • 5. 眾賞文庫僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論