1. 程式人生 > >the c programming language second edition 第四章函式與程式結構筆記及練習題中

the c programming language second edition 第四章函式與程式結構筆記及練習題中

the c programming language second edition 第四章函式與程式結構筆記

4.3外部變數

  • C語言程式可以看成由一系列的外部物件構成,這些外部物件可能是變數或函式
  1. 外部變數和函式具有以下性質:通過同一個名字對外部變數的所有引用實際上都是引用同一個物件。(標準把這一性質稱為外部連結)
  2. 因為外部變數可以在全域性範圍內訪問,這就為函式之間的資料交換提供了一種可以代替函式引數與返回值的方式。
  3. 外部變數的用途還表現在它們與內部變數相比具有更大的作用域和更長的生存期,外部變數是永久存在的它們的值在一次函式呼叫到下一次函式呼叫之間保持不變。因此在需要函式共享某些資料時最方便的方式是把這些共享資料定義為外部變數而不是作為函式引數傳遞。

用逆波蘭表示法表示
在逆波蘭表示法中所有運算子都跟在運算元後面,比如
(1-2)(4+5) == 12-45+
while(下一個運算子或運算元不是檔案結束指示符)
if(是數)
將該數壓入棧中
else if(是運算子)
彈出所需數目的運算元
執行運算
將結果壓入到棧中
else if(是換行符)
彈出並列印棧頂的值
else
出錯

  1. 棧的壓入與彈出操作比較簡單,但是,如果把錯誤檢測與恢復操作都加進來,該程式就很長,最好把它們設計成獨立的函式,而不要把它們作為程式中重複的程式碼使用。另外還需要一個單獨的函式來取下一個輸入運算子或運算元
  2. main函式不需要了解控制棧的變數資訊,它只進行壓入與彈出操作。因此可以把棧及相關資訊放在外部變數中,並只提供push與pop函式訪問,而不能被main函式訪問
#include···//包含一些標頭檔案
#define···//一些define定義
main(){}
void push (double f){}
double pop(void){}
int getop(char s[]){}
  • 逆波蘭計算器強化版
#include <stdio.h>
#include<math.h>
#include <string.h>
#include<stdlib.h>
#include<ctype.h>
#define MAXOP 100//運算元或運算子的最大長度
#define NUMBER '0'
//標識找到了一個數 void push(double);//把f壓入到值棧中 double pop(void);//彈出並返回棧頂的值 int getop(char []);//擷取下一個運算子或數值運算元 int getch(void);//讀取下一個待處理的字元 int ungetch(int);//用於把字元放回到輸入中 //程式中經常會出現這樣的情況:程式不能確定它已經讀入的輸入是否足夠,除非超前多讀入一些輸入 void clear(void); int main() { int type; double op1,op2; char s[MAXOP]; while((type=getop(s))!=EOF){ switch(type){ case NUMBER: push(atof(s)); break; case '+': push(pop()+pop()); break; case '*': push(pop()*pop()); break; case '-'://不滿足交換律運算子左右運算元必須加以區分 op2=pop(); push(pop()-op2); break; case '/': op2=pop(); if(op2!=0.0) push(pop()/op2); else printf("error:zero dibisor\n"); break; case '%': op2=pop(); if(op2!=0.0) push(fmod(pop(),op2)) else printf("error: zero divisor\n"); case '\n': printf("\t%.8g\n",pop()); break; case '?'://在不彈出元素的情況下列印棧頂元素 op2=pop(); printf("\t%.8g\n",op2); push(op2); break; case 'c'://清空棧 clear(); break; case 's'://交換棧頂兩個元素 op1=pop(); op2=pop() push(op1); push(op2); break; case 'd'://複製棧頂元素 op2=pop(); push(op2); push(op2); break; default: printf("error:unknown command %s\n",s); break; } } return 0; } //------------------------------------------------- #define BUFSIZE 100 #define maxval 100//val的最大深度 int sp=0;//下一個空閒棧位置 double val[maxval];//值棧 void push(double f)//把f壓入到值棧中 { if(sp<maxval)val[sp++]=f; else printf("error:stack full %g failed\n",f); } double pop(void)//彈出並返回棧頂的值 { if(sp>0) return val[--sp]; else { printf("error:stack empty\n"); return 0.0; } void clear(void)//清空棧 { sp=0; } } //------------------------------------------------- //------------------------------------------------- char buf[BUFSIZE];//用於ungetch函式的緩衝區 int bufp=0;//buf中下一個空閒位置 int getch(void) { return (bufp>0)?buf[--bufp]:getchar(); } int ungetch(int c) { if(bufp>=BUFSIZE) printf("ungetch: too many characters\n"); else buf[bufp++]=c; } //------------------------------------------------- int getop(char s[])//擷取下一個運算子或數值運算元 { int i,c; while((s[0]=c=getch())==' '||c=='\t'); s[1]='\0'; if(!isdigit(c)&&c!='.'&&c!='-')return c;//不是數 i=0; if(c=='-')//考慮負數的情況 { if(isdigit(c=getch())||c=='.') s[++i]; } if(isdigit(c))//收集整數部分 while(isdigit(s[++i]=c=getch())); if(c=='.')//收集小數部分 while(isdigit(s[++i]=c=getch())); s[i]='\0'; if(c!=EOF)ungetch(c); return NUMBER; } //-------------------------------------------------