c語言高級(jí)教程第四章.ppt_第1頁
c語言高級(jí)教程第四章.ppt_第2頁
c語言高級(jí)教程第四章.ppt_第3頁
c語言高級(jí)教程第四章.ppt_第4頁
c語言高級(jí)教程第四章.ppt_第5頁
已閱讀5頁,還剩24頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

李堂秋 廈門大學(xué)計(jì)算機(jī)科學(xué)編寫,C與C+程序設(shè)計(jì) 第四章 函數(shù)和程序結(jié)構(gòu),前言,使用函數(shù),可以把大的計(jì)算任務(wù)分解,換句話說,可以使用許多函數(shù)的組合來完成復(fù)雜的任務(wù)。而且在C中,并非所有的函數(shù)都要自己定義,可以使用別人已做好的程序模塊。在設(shè)計(jì)主函數(shù)的時(shí)候,可以將不必要的細(xì)節(jié)蘊(yùn)藏起來,以便更容易把握主線和全局。如果程序太大,還可以將C語言寫的程序分放多個(gè)文件,分別編譯,最后再聯(lián)接起來成為整體。,4.1 函數(shù)的基礎(chǔ),看看我們?nèi)绾尉幰粋€(gè)程序, 首先要明確我們要做什么事請(qǐng),比如要讀一個(gè)文件,找出所有包含某一字符串的行并把它打印出來。 思路: while (讀入一個(gè)新行) if (如果這個(gè)新行包含指定的字符串) 打印這個(gè)新行,讀入一個(gè)新行,打印這一行,判斷這一行是否指定的字符串,函數(shù)的基礎(chǔ)(續(xù)), () 除了和()、 其他都可以省略,如: dummy( ) ;,數(shù)據(jù)傳入,數(shù)據(jù)通過 return ; 傳回給調(diào)用函數(shù),#include #define MAXLINE 1000 int getline(char line , int max); int strindex(char source , char searchfor ); char pattern = “ould”; /* pattern to search for */ /* find all lines matching pattern */ main ( ) char lineMAXLINE; int found = 0; while (getline(line, MAXLINE) 0) if (strindex(line, pattern) = 0) printf(“%s”, line); found+; return found; ,主函數(shù),/*getline: get line into s, return length*/ int getline (char s , int lim) int c, i; i = 0; while ( -lim 0 ,子函數(shù),4.2 返回非整數(shù)的函數(shù),在使用返回值不是整數(shù)的函數(shù)時(shí),正確地進(jìn)行函數(shù)的定義和函數(shù)說明十分重要。 函數(shù)定義時(shí)一定要說明返回值類型,否則缺省為整數(shù)。 為了使調(diào)用函數(shù)知道被調(diào)用函數(shù)的類型,函數(shù)調(diào)用前一定要進(jìn)行原形說明,否則,如果函數(shù)定義的類型與調(diào)用類型出現(xiàn)不一致: 如果調(diào)用和被調(diào)用函數(shù)在同一個(gè)文件中定義,編譯器會(huì)提出警告,這是實(shí)行原型說明的好處。 如果不在一個(gè)文件中定義,編譯器不會(huì)發(fā)現(xiàn)問題,即: 在調(diào)用前沒有原型說明的函數(shù),被理解為返回整數(shù),而對(duì)它的變?cè)翢o假定。 函數(shù)原型說明中沒有給出變量說明的,編譯器對(duì)變?cè)蛔鋈魏螜z查。,子函數(shù)把字符串轉(zhuǎn)換成浮點(diǎn)數(shù),#include /* atof: convert string s to double*/ double atof (char s ) double val, power; int i, sign; for (i = 0; isspace(si); i+) /*skip leading spaces*/ ; sign = (si = -) ? -1 : 1; if (si = + | si = -) i+; for ( val = 0.0; isdigit(si); i+) val = 10 * val + (si - 0); if (si = .) i+; for (power = 1.0; isdigit(si); i+) val = 10 * val + (si - 0); power *= 10.0; return sign * val / power; ,主函數(shù)讀入數(shù)字并把它們累加起來,#include #define MAXLINE 100 /* a rudimentary calculator */ main ( ) double sum, atof(char ); char lineMAXLINE; int getline(char line , int max); sum = 0; while (getline(line, MAXLINE) 0) printf(“t%gn”, sum += atof(line); return 0; ,4.3 外部變量-全局變量,全局變量是在所有函數(shù)外部定義的變量,它有如下的特性: 全程可見性:對(duì)程序中全局變量,通過適當(dāng)說明,所有函授都可以通過它的唯一的“名字”對(duì)它存取,即使這些函數(shù)是在不同文件并且是分別編譯的。 可見性可控:當(dāng)然,也可以通過適當(dāng)?shù)恼f明,使某些全局變量只在一個(gè)文件中有效。 全程生命周期:全局變量從程序執(zhí)行時(shí)就存在,并且一直存在直到程序結(jié)束。 可增加效率:可以用來保留中間結(jié)果,如果許多函數(shù)使用大量的共同數(shù)據(jù),適度的使用外部變量,可以避免大量數(shù)據(jù)的傳遞,對(duì)于簡化程序是有益的。 函數(shù)是全局的:C程序是由一系列外部變量和函數(shù)組成的,C中所有的函數(shù)都是全局的,不能在函數(shù)中定義函數(shù)。,局部變量或內(nèi)部變量(2),全局變量又叫外部變量,它與內(nèi)部變量相對(duì)應(yīng),函數(shù)的參數(shù)變量和函數(shù)內(nèi)部定義的變量叫內(nèi)部變量。 內(nèi)部變量的可見性是局部的:內(nèi)部變量又稱局部變量,只在函數(shù)內(nèi)可見,當(dāng)局部變量與某全局變量同名時(shí),全局變量受到屏蔽。其好處是,不同的函數(shù)的局部變量可以同名,他們之間不會(huì)產(chǎn)生混淆。 局部變量的生命周期短:從函數(shù)被調(diào)用的時(shí)刻起存在,到函數(shù)調(diào)用結(jié)束時(shí)消亡。 函數(shù)的局部動(dòng)態(tài)變量在兩次調(diào)用之間沒有關(guān)系,更不會(huì)相互影響。 使用局部變量,可以保證程序的模塊化 但在特定的情況下使用全局變量會(huì)簡化參數(shù)的傳遞。權(quán)衡,例子:說明外部變量的正確使用,設(shè)計(jì)一個(gè)可以做加減乘除的計(jì)算器,輸入采用反序波蘭表達(dá)式: 1 2 - 4 5 + * 表示:(1 - 2)*(4 + 5) 處理的算法如下: while(下一個(gè)字符是操作數(shù)或操作符并且不是文件結(jié)束) if (是數(shù)字) 壓入棧中 else if (是操作符) 彈出操作數(shù) 實(shí)行操作 壓入棧中 else if (是新行) 彈出操作數(shù)并打印結(jié)果 else 出錯(cuò) 這里的主要問題是決策:公共存取的變量放在何處?-外部還是局部?,主程序,#include #include #define MAXOP 100 #define NUMBER 0 int getop(char ); /*原型說明*/ void push(double); double pop(void): /*reverse polish calculator*/ main ( ) int type; double op2; char sMAXOP; 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 divisorn”); break; case n:printf(“t%.8gn”, pop( ); break; default: printf(“error: unknown command %sn”, s); break; return 0; ,子程序1,/*解決堆棧和出棧的數(shù)據(jù)存儲(chǔ)和操作* /#define MAXVAL 100 int sp = 0; double valMAXVAL; /*value stack*/ /*push: push f onto value stack*/ void push (double f) if (sp 0) return val-sp; else printf(“error: stack emptyn”): return 0.0; ,子程序2,#include int getch(void); void ungetch(int); /*getch: get next operator or numeric operand 解決數(shù)據(jù)和操作符的輸入*/ int getop (char s ) int i, c; while(s0 = c = getch( ) = | c = t) ; s1 = 0; if ( !isdigit(c) ,子程序3,/*緩沖式的字符輸入*/ #define BUFSIZE 100 char bufBUFSIZE; /* buffer for ungetch*/ int bufp = 0; /*next buffer position*/ /* get a character (possibly pushed back) */ int getch(void) return (bufp 0) ? buf-bufp : getchar( ); /* ungetch: push character back on input */ void ungetch(int c) if (bufp = BUFSIZE) printf(“ungetch: too many charactersn”); else bufbufp+ = c; ,4.4 變量轄域,某變量的轄域是指可以通過該變量的名字對(duì)之存取的程序部分。 函數(shù)的形式參數(shù)和在函數(shù)前部定義或說明的局部變量的定義域是整個(gè)函數(shù)。不同函數(shù)中同名的變量間沒有任何關(guān)系。 在程序開頭定義的全局變量的轄域是所在文件的這個(gè)變量定義以后的其余部分。 但是一個(gè)程序可以分放在幾個(gè)文件中,預(yù)先編譯好的程序也可以從程序庫中導(dǎo)入,連接成更大的程序。由于存在一個(gè)文件使用另一個(gè)文件中定義的全程變量,此時(shí)存在如下問題: 如何寫變量的說明使得能正確編譯? 如何安排變量說明,使得程序裝入內(nèi)存時(shí)能正確地連接? 如何保證是外部變量只有一份拷貝? 如何對(duì)全局變量初始化? 下面回答這個(gè)問題:,變量轄域(續(xù)),外部變量的轄域是從定義或說明它們的地方起直到文件的結(jié)束: main( ) . int sp = 0; double valMAXVAL; void push(double f) . double pop(viod) . 如果要在定義函數(shù)時(shí)需要訪問尚未定義的外部變量或需要訪問另一文件中定義的外部變量,則在使用它的文件(或函數(shù))的開頭必須加外部變量說明。說明以后它在文件(或函數(shù))的其余部分是可見的了。 要注意外部變量的定義和說明之間的區(qū)別,說明只指出變量的類型,定義還涉及內(nèi)存的分配。在整個(gè)程序中一個(gè)外部變量只能定義一次,其它文件用extern說明加以關(guān)聯(lián)。 外部變量只能在定義的地方初始化一次,不能在extern說明時(shí)進(jìn)行初始化。,正常的情況是:main無法存取它后面定 義的變量和函數(shù)。如果main要存取sp,val, push,和pop,則必須在這里或main 的開頭加: extern int sp; extern double val ; void push(double); double pop(void):,4.5 頭文件,當(dāng)程序分成好幾個(gè)文件時(shí),為了共享外部變量和函數(shù),一般的做法是把說明集中寫在一個(gè)頭文件中,然后在必要的文件中加以包含:,/*calc.h*/ #define NUMBER 0 void push(double); double pop(void); int getop(char ); int getch(void); void ungetch(int);,/*getop.c*/ #include #include #include “calc.h” getop( ) ,/*getch.c*/ #include #define BUFSIZE 100 char bufBUFSIZE; int bufp = 0; int getch(void) . void ungetch(int c) . ,/*main.c*/ #include #include #include “calc.h” #define MAXOP 100 main( ) ,/*stack.c*/ #include #include “calc.h” #define MAXVAL 100 int sp = 0; double valMAXVAL; void push(double f) double pop( ) . ,針對(duì)性問題:只有在 特別大的程序中才考 慮使用多個(gè)頭文件,4.6 靜態(tài)變量,為了使一個(gè)外部變量的轄域僅限于一個(gè)文件,不讓其它文件存取這個(gè)變量,或者讓其它文件可以使用同樣的外部變量名而不與這個(gè)變量相混淆,可以在該外部變量之前加static前綴: 函數(shù)也可以說明成為static,說明成static的函數(shù)只在本文件可見。 局部變量也可以說明成static, 靜態(tài)局部變量仍然是局部的,但它有永久的、私有的內(nèi)存空間,因此函數(shù)調(diào)用的結(jié)果可以保留下來,直到此函數(shù)以后的調(diào)用中將之改變。這一特性十分重要!,/*getch.c*/ #include #define BUFSIZE 100 static char bufBUFSIZE; static int bufp = 0; int getch(void) . void ungetch(int c) . ,/*stack.c*/ #include #include “calc.h” #define MAXVAL 100 static int sp = 0; static double valMAXVAL; void push(double f) double pop( ) . ,4.7 寄存器變量,對(duì)于常用的變量(特別是循環(huán)變量)可以說明成寄存器變量,要求編譯器將其安排在機(jī)器的寄存器中,其格式是在說明之間加register前綴: register int x; register char c; 寄存器變量存取的速度快,但只能把局部變量和函數(shù)的形式參數(shù)說明成寄存器變量,而且也只有一定類型(整型)的變量能被指定成寄存器變量: fun (register unsigned n, register long n) register int i; 根據(jù)機(jī)器的不同,可同時(shí)指定為寄存器變量的數(shù)目不同,編譯器可對(duì)過多的寄存器變量說明不予理會(huì)。一般說來,只把使用頻繁的循環(huán)變量指定為寄存器變量。 寄存器變量沒有地址,不管它實(shí)際存放在寄存器上與否。,4.8 塊結(jié)構(gòu),C語言不是嚴(yán)格的塊結(jié)構(gòu)語言,不能在函數(shù)內(nèi)定義函數(shù),但可以在函數(shù)內(nèi)甚至程序塊內(nèi)定義局部變量: if (n 0) int i; for (i = 0; i n; i+) /* 這變量只在程序執(zhí)行這個(gè)塊時(shí)建立,塊結(jié)束時(shí)消亡*/ 局部變量對(duì)塊外的同名變量和函數(shù)會(huì)起屏蔽作用,如: int x; int y; fun (double x) double y; /* 在函數(shù)內(nèi),這兩個(gè)變量與外部的變量無關(guān),這也是一個(gè)十分重要的特點(diǎn),編程時(shí)最好避免這種情況 */,這個(gè) i 是局部于這個(gè)程序塊,4.9 變量初始化,在沒有明確指定初始化公式情況下:全程變量和靜態(tài)變量初始化為0。自動(dòng)變量(局部和參數(shù))和寄存器變量的初值是不確定的。 數(shù)值性的變量可以初始化: char squote = ; long day = 1000L*60L*60L*24L; 全局變量和靜態(tài)變量的初始化公式只能是常數(shù)表達(dá)式,并且只初始化一次(程序執(zhí)行前);局部的非靜態(tài)變量初始化公式可以是任意的,而且在每一次進(jìn)入函數(shù)時(shí)進(jìn)行一次初始化。 int bisearch (int x, int v , int n) int low = 0, high = n - 1, mid; 數(shù)組的初始化: int days = 31,28,31,30,31,30,31,31,30,31,30,31; 對(duì)于任何類型的變量,在指明元素個(gè)數(shù)時(shí),初始化不足的元素為0;初始化過多時(shí)出錯(cuò);沒有辦法表示元素值重復(fù);無法省略前導(dǎo)元素 字符數(shù)組的初始化可以使用如下特殊的形式: char s = “hello”; /*它是下式的簡寫*/ char s = h,e,l,l,o,0;,4.10 遞歸,C語言允許遞歸調(diào)用,即一個(gè)函數(shù)直接或間接地調(diào)用它自身。有許多需要遞歸調(diào)用的場合,例一,打印一個(gè)整數(shù),由于最先得到的是最低位,但最先要打印的是最高位,遞歸可以解決此類問題: #include /* printd:print n in decimal */ void printd(int n) if (n 0) putchar(-); n = -n; if (n / 10) printd(n / 10); putchar(n % 10 + 0); 另一個(gè)例子是快速排序,給定一個(gè)數(shù)組,選擇一個(gè)元素,把其它元素根據(jù)比該元素大小分成兩個(gè)集合,然后遞歸調(diào)用快速排序算法,直到集合的元素少于兩個(gè),排序完成:,遞歸(續(xù)),/*qsort: sort vleft . vright into increasing order */ void qsort(int v , int left, int right) int i, last; void swap(int v , int i, int j); if (left = right) return; swap(v, left, (left + right) / 2); /* move partition element to elem */ last = left; for (i = left+1; i = right; i+) if (vi vleft) swap(v, +last, i); swap(v, left, last); /* restore partition elem */ qsort(v, left, last - 1); qsort(v, last + 1, right); /* swap: interchange vi, and vj */ void swap(int v , int i, int j) int temp; temp = vi; vi = vj; vj = temp; ,許多問題既可以用遞歸方法,也可以用非遞歸方法:在許多情況下,用遞歸寫的程序會(huì)更緊湊、更容易理解,特別對(duì)于處理遞歸設(shè)計(jì)的數(shù)據(jù)特別方便,但是遞歸在內(nèi)存和時(shí)間上都不會(huì)節(jié)省。,4.11 C預(yù)處理器,C在文件編譯之前對(duì)被編譯的文件提供預(yù)了許多預(yù)處理手段,其中包括:文件包含;宏定義;條件編譯。 1.文件包含: 一般格式: #include /* 在缺省的文件目錄尋找filename */ #include “filename” /* 在原程序所在的目錄尋找,若找不到 在缺省的文件目錄尋找filename */ #include將由filename的文件內(nèi)容所取代。,應(yīng)用文件包含的目的是把個(gè)文件共同需要的宏定義, 外部變量說明,庫函數(shù)的原型說明等(stdio.h)插入到文 件的開頭。這樣可更好地保證每一個(gè)文件需要的常數(shù) 定義和子函數(shù)的定義都是一樣的。,C預(yù)處理器(續(xù)),#define(宏代換) 一般格式: #define #define forever for( ; ; ); /*在編譯前將文本中的前者(不 包括在字符串中的)用后者替換*/ 可帶變量 #define max(A, B) (A) (B) ? (A) : (B) x = max(p+q,r+s) 替換成x = (p+q) (r+s) ? (p+q) : (r+s) 盡管宏定義是十分有用的,但要注意如下的調(diào)用或定義的問題-特別要注意重復(fù)執(zhí)行問題和運(yùn)算的優(yōu)先級(jí)問題: max(i+, j+); #define square(x) x*x #把實(shí)參變成字符串 #define dpri

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論