第五章 從問題到程序-再談函數(shù) 云南_第1頁
第五章 從問題到程序-再談函數(shù) 云南_第2頁
第五章 從問題到程序-再談函數(shù) 云南_第3頁
第五章 從問題到程序-再談函數(shù) 云南_第4頁
第五章 從問題到程序-再談函數(shù) 云南_第5頁
已閱讀5頁,還剩79頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

從問題到程序

-再談函數(shù)導(dǎo)言小明一天的生活去食堂吃早飯去教室上第一節(jié)課去教室上第二節(jié)課去教室上第三節(jié)課去教室上第四節(jié)課陪女友吃午飯陪女友逛街陪女友上自習(xí)去教室上第五節(jié)課去教室上第六節(jié)課去教室上第七節(jié)課去教室上第八節(jié)課陪女友吃晚飯陪女友逛街陪女友上自習(xí)回寢室打dota睡覺函數(shù)的出現(xiàn)程序規(guī)模增大代碼量增長重復(fù)代碼增多難以閱讀,難以修改處理復(fù)雜事情的基本方法將復(fù)雜事物分解為較簡單的部分,分別處理。由各部分的解構(gòu)造出整個問題的解。為支持復(fù)雜程序開發(fā),各種程序抽象機(jī)制被引進(jìn)程序語言。使人能把程序片段從整體中抽象出來單獨(dú)運(yùn)算。小明的一天吃早飯上午上課上午陪女友下午上課下午陪女友回寢室活動程序抽象機(jī)制函數(shù),過程,模塊---封裝固定的運(yùn)算過程,計算抽象結(jié)構(gòu)---封裝相關(guān)的數(shù)據(jù),存儲抽象面向?qū)ο蠛瘮?shù)抽象機(jī)制的意義:重復(fù)片段可用唯一的函數(shù)定義和一些形式簡單的函數(shù)調(diào)用取代,使程序更簡短清晰同樣計算片段只描述一次,易于修改可獨(dú)立考慮函數(shù)定義與使用,大大提高工作效率C語言的庫函數(shù)C語言很小,ANSIC定義了標(biāo)準(zhǔn)庫,其中提供最常用的與平臺無關(guān)的功能。庫函數(shù)實現(xiàn)常用計算,可按規(guī)定方式調(diào)用,不必自己實現(xiàn),也不必關(guān)心怎樣實現(xiàn)。各平臺(操作系統(tǒng))還定義了擴(kuò)展庫DOS上的C系統(tǒng)提供與DOS有關(guān)的功能函數(shù)Windows上的系統(tǒng)提供與Windows有關(guān)的函數(shù)UNIX系統(tǒng)上的系統(tǒng)提供與UNIX接口的函數(shù)標(biāo)準(zhǔn)庫功能輸入輸出、文件操作、內(nèi)存管理數(shù)學(xué)函數(shù)、數(shù)據(jù)轉(zhuǎn)換函數(shù)類型判斷。。。。。類型判斷(<ctype.h>)isalpha(c) c是字母字符isdigit(c) c是數(shù)字字符isalnum(c) c是字母或數(shù)字字符isspace(c) c是空格、制表符、換行符isupper(c) c是大寫字母islower(c) c是小寫字母iscntrl(c) c是控制字符isprint(c) c是可打印字符,包括空格isgraph(c) c是可打印字符,不包括空格isxdigit(c) c是十六進(jìn)制數(shù)字字符ispunct(c) c是標(biāo)點(diǎn)符號inttolower(intc) 轉(zhuǎn)為對應(yīng)小寫字母inttoupper(intc) 轉(zhuǎn)為對應(yīng)大寫字母統(tǒng)計文件里的數(shù)字和小寫/大寫字母。用庫函數(shù)更方便#include<stdio.h>#include<ctype.h>intmain(){intc,cd=0,cu=0,cl=0;while((c=getchar())!=EOF){if(isdigit(c))++cd;if(isupper(c))++cu;if(islower(c))++cl;}printf("digits:%d\n",cd);printf("uppers:%d\n",cu);printf("lowers:%d\n",cl);return0;}函數(shù)定義和程序的函數(shù)分解庫函數(shù)有限,編寫復(fù)雜程序時需要自己定義函數(shù)。一個C程序主要是一系列的函數(shù)定義。函數(shù)定義形式:

返回值類型函數(shù)名(參數(shù)表)

{

函數(shù)體}主函數(shù)mainmain的返回值規(guī)定為int。這個返回值在程序結(jié)束時送給外部(如操作系統(tǒng))可用這個值.一般用返回0表示程序正常結(jié)束,其他值表示出錯程序本身不允許調(diào)用mainmain函數(shù)中使用的其他函數(shù)一定要在main函數(shù)前定義看不見的main函數(shù)intmain(){/*一般寫法*/......return0;}什么樣的程序片段應(yīng)該定義為函數(shù):重復(fù)出現(xiàn)的相同/相似計算片段。根據(jù)不同的x,y,z的值計算x+3y+5z的結(jié)果長計算過程中有邏輯獨(dú)立性的片段。解碼器中讀取文件,解碼,渲染等步驟問題寫程序打印下面這類字符圖形方法一:通過putchar調(diào)用打印星號和空格。。。。方法二:程序里寫一系列printf調(diào)用。例:intmain(){/*打印菱形*/printf("*");printf("**");printf("***);....../*下略*/}每個程序需要寫一組輸出語句,很羅嗦,沒意思無論是修改圖形大小或形狀,代碼都需要全部重寫如需要畫出新圖形,已做工作對新工作毫無價值應(yīng)考慮畫這類圖形的“基本動作”,定義為函數(shù)。需要畫的圖形比較規(guī)范,一行有兩種情況:一段連續(xù)字符;在兩個特定位置的字符??煽紤]定義兩個函數(shù),其頭部分別為:

voidline(intbegin,intend)voidpoints(intfst,intsnd)分別從begin到end輸出*,或者在fst和snd輸出*。字符圖形未必用星號,可推廣,引進(jìn)一個字符參數(shù)voidline(charc,intbegin,intend)voidpoints(charc,intfst,intsnd)雖然兩個函數(shù)還沒定義,由于其功能很清楚,已可以使用它們畫圖形,檢驗其設(shè)計合理性了。例如畫菱形:for(i=10,j=10;i>4;--i,++j)points('*',i,j);for(i+=2,j-=2;i<=j;++i,--j)points('*',i,j);兩個函數(shù)就是先輸出一些空格和字符,最后換行:voidline(charc,intbegin,intend){inti;for(i=0;i<begin;++i)putchar('');for(;i<=end;++i)putchar(c);putchar('\n');}voidpoints(charc,intfirst,intsecond){inti;for(i=0;i<first;++i)putchar('');putchar(c);for(++i;i<second;++i)putchar('');if(first<second)putchar(c);putchar('\n');}也可引入附加參數(shù),將兩個函數(shù)合而為一:voidline(charc,intbegin,intend,intfill)在fill為0值時在兩端點(diǎn)輸出,非0時連續(xù)輸出字符。還可基于它們定義畫各種基本幾何圖形的函數(shù)。設(shè)計函數(shù)時需要選定合適參數(shù)。例如畫矩形的函數(shù):voidrect(charc,intbegin,intlen,inthigh){...for(i=0;i<high;i++)

line(c,begin,begin+len,1);

...}這些函數(shù)又形成另一層抽象層次。定義好這樣一組函數(shù)后,就可以在新的層次上寫字符圖形程序了。再談函數(shù)對函數(shù)的兩種觀點(diǎn)函數(shù)定義和函數(shù)調(diào)用,參數(shù)傳遞函數(shù)原型程序結(jié)構(gòu)和變量不同種類的變量黑客帝國中,每個人就是一段代碼,在虛擬的世界中可能是一個普通職員,但是內(nèi)心如何只有自己知道封裝把函數(shù)內(nèi)外隔成兩個世界。不同世界形成了對函數(shù)的兩種觀點(diǎn)。函數(shù)接口定義規(guī)定了兩個世界的交流方式。函數(shù)接口的定義是函數(shù)定義者(實現(xiàn)者)和使用者共同討論的結(jié)果函數(shù)定義者通過定義函數(shù)接口來描述函數(shù)對外提供的服務(wù)函數(shù)使用者通過函數(shù)接口看函數(shù)如何使用接口定義好以后,可以分別開發(fā)實參與形參函數(shù)定義intadd(int

a,intb){returna+b;}函數(shù)使用….intm=8,n=9,k;k=add(m,n);形參全稱為“形式參數(shù)”是在定義函數(shù)名和函數(shù)體的時候使用的參數(shù),目的是用來接收調(diào)用該函數(shù)時傳遞的參數(shù)形參變量只有在被調(diào)用時才分配內(nèi)存單元,在調(diào)用結(jié)束時,即刻釋放所分配的內(nèi)存單元。實參全稱為“實際參數(shù)”是在調(diào)用時將實參的值傳遞給函數(shù)的形式參數(shù).值傳遞時,實參的值不會被改變函數(shù)定義intadd(int

a){returna++;}函數(shù)使用….intm=8;add(m);printf(”%d”,m);值傳遞時,有可能會引起類型轉(zhuǎn)換,編譯器會報警,但是不會報錯intadd(inta){returna++;}…..longlongb=1;add(b);C語言的參數(shù)機(jī)制稱為值參數(shù)函數(shù)調(diào)用是先計算各實參表達(dá)式的值把實參的值傳給對應(yīng)形參后執(zhí)行函數(shù)體intadd(inta){returna+1;}…..intb=1,c;c=add(b+2);++的困惑函數(shù)原型C語言規(guī)定,a函數(shù)如果調(diào)用了b的函數(shù),寫代碼時那么b函數(shù)定義必須出現(xiàn)在a函數(shù)定義前面。否則編譯器會報錯,因為編譯器是順序執(zhí)行的。inta(){….}intb(){a();}不美觀,有點(diǎn)丑陋…….C語言允許將被調(diào)用者函數(shù)原型放在調(diào)用者前面即可inta();//函數(shù)原型,函數(shù)申明……intb(){a();}inta(){….}函數(shù)原型也叫函數(shù)申明,是函數(shù)頭加“;”即可但必須保證函數(shù)申明和函數(shù)頭除“;”以外是一致的養(yǎng)成寫函數(shù)原型到c文件頭部的好習(xí)慣程序結(jié)構(gòu)與變量C程序是由一系列的函數(shù)和變量構(gòu)成的。局部變量:函數(shù)中定義的變量(包括main函數(shù))全局變量(外部變量):函數(shù)外定義的變量….inta=1;//全局變量intmain(){

intb=1;//局部變量}程序為全局變量分配了存儲空間,即使程序未運(yùn)行,全局變量的存儲空間也存在,所以全局變量的生命周期與程序的生命周期一致。

程序沒有為局部變量分配空間,局部變量的空間在函數(shù)運(yùn)行時才分配,所以,局部變量的生命周期與其最近的花括號相同(作用域)不同作用域中可以定義同名變量(壞習(xí)慣)#include<stdio.h>intmain(){{intc=1;printf("%d",c);}

printf(“%d”,c);//編譯器報錯return1;}當(dāng)變量與變量重名時,程序會按照最近原則取變量的值。#include<stdio.h>intc=444;intmain(){{intc=1;printf("%d",c);}//此時局部變量c已經(jīng)不存在

printf(“%d”,c);//取全局變量c的值return1;}變量的作用域(有效區(qū)域)局部變量-花括號ifforwhileswitch函數(shù)函數(shù)中任意地方全局變量-整個程序?qū)⑺械木植孔兞繉懺诤瘮?shù)體的開始是一個非常非常好的習(xí)慣大型c程序由多個文件組成,如果某文件想用其他文件定義的全局變量,需要在自己的文件頭部寫上

externinta;只想本文件中的函數(shù)看見這個變量,那么需要將這個變量聲明成靜態(tài)全局變量。

staticinta;靜態(tài)全局變量不能被extern,編譯器會報錯小知識:靜態(tài)函數(shù)(只要在函數(shù)名稱和函數(shù)聲明前加static,本函數(shù)只能被本文件內(nèi)的其他函數(shù)使用,不能被其他文件的函數(shù)使用)

變量的作用域(有效區(qū)域)局部變量-花括號全局變量-整個程序靜態(tài)全局變量-所在文件(如xxx.c)more,出于安全性的考慮,我想設(shè)計一種變量在某函數(shù)(或某花括號)內(nèi)部使用,其他函數(shù)無法使用在函數(shù)被多次調(diào)用過程中,始終使用這個局部變量局部變量加上static前綴就是靜態(tài)局部變量靜態(tài)局部變量:只具有局部的作用域,但是卻有全局的生命周期,這個變量只初始化一次。靜態(tài)局部變量僅能夠初始化一次。#include<stdio.h>voidstaticTest(){

staticinta=0;a++;printf("%d",a);}intmain(){inti;for(i=1;i<10;i++){staticTest();}return1;}靜態(tài)局部變量可采用其他設(shè)計方式替代(全局變量或靜態(tài)全局變量)小知識:類似全局變量,編譯器為靜態(tài)局部變量分配了固定的存儲空間。變量的作用域(有效區(qū)域)局部變量-花括號全局變量-整個程序靜態(tài)全局變量-所在文件(如xxx.c)靜態(tài)局部變量-花括號變量生命周期變量的作用域(空間)和生命周期(時間)不同你可以活一百年(生命周期),但是只是在地球上(作用域)作用域變量在代碼的哪個范圍內(nèi)有效生命周期變量存在的時間變量的生命周期(存在-消失)局部變量-所在花括號內(nèi)全局變量-程序開始運(yùn)行到程序結(jié)束靜態(tài)全局變量-程序開始運(yùn)行到程序結(jié)束靜態(tài)局部變量-程序開始運(yùn)行到程序結(jié)束變量的初始化全局變量,靜態(tài)局部變量都只初始化一次局部變量每次進(jìn)入定義域時都會被初始化若初始化時變量沒有被賦值,其值是不確定的一定要養(yǎng)成變量定義時就賦值的習(xí)慣#include<stdio.h>inta=0;intmain(){inti;for(i=1;i<10;i++){intb=0;staticintc=0;a++;b++;c++;printf("%d,%d,%d\n",a,b,c);}return1;}常變量用關(guān)鍵字const定義的變量。是變量,但不允許二次賦值,只能初始化的時候賦值,其作用域中總代表同一個值:

constintnum=10;若出現(xiàn)在局部作用域里,那么也動態(tài)建立和初始化,每次初始化的值可以不同:for(i=2;i<=200;i+=2){constintn=i*i;......}可用const定義常參數(shù),函數(shù)體里不能重新賦值。預(yù)處理C程序加工分為三步:預(yù)處理,編譯,連接。預(yù)處理程序是C系統(tǒng)的一部分,處理源程序的預(yù)處理命令行,產(chǎn)生修改后的源程序。預(yù)處理命令行以“#”開頭#include……(頭文件-展開操作)#defineMAX5………(宏定義-替換操作)#if#else(條件編譯-選擇編譯操作)預(yù)處理頭文件

把指定文件內(nèi)容包含到當(dāng)前源文件#include<windows.h> 形式1#include“myapp.h" 形式2形式1用于包含系統(tǒng)頭文件,預(yù)處理程序到指定目錄找文件(通常指定幾個系統(tǒng)文件目錄)。形式2用于包含自己的文件。預(yù)處理程序先在源文件所在的目錄里找,找不到時再到指定目錄中去找。預(yù)編譯宏簡單的宏定義在預(yù)編譯階段宏被替換成相應(yīng)的正文

#defineMAXLEN

20替代正文可以寫任何東西。若定義:

#defineSLDstaticlongdouble程序中的:

SLDx=2.4,y=9.16;替換后變成:

staticlongdoublex=2.4,y=9.16;帶參數(shù)的宏定義#define宏名字(參數(shù)列表)替代正文如:

#definemin(A,B)((A)<(B)?(A):(B))……z=min(x+y,x*y);預(yù)處理中將被展開為:z=((x+y)<(x*y)?(x+y):(x*y));宏帶來的問題替換后語法錯誤難以檢查#defineMAX15)intmain(){inta=0;if(a>MAX)printf("ok");}return1;}會有意想不到的錯誤

#definesquare(x)x*x在特定環(huán)境下可能出問題,例如:

z=square(x+y);展開后是

x+y*x+y不是我們所想的

(x+y)*(x+y)

正確的定義是

#definesquare(x)(x)*(x)有些標(biāo)準(zhǔn)庫“函數(shù)”用宏實現(xiàn)。ctype.h里字符類型判斷。宏只有在你非常清晰會不會出問題的時候使用一般使用宏定義常量#defineMAXLEN256//ok謹(jǐn)慎使用宏定義邏輯,宏展開后的確會比函數(shù)快一點(diǎn)點(diǎn),但是出錯時代價巨大

宏定義從一般從定義處起作用直到文件結(jié)束。如果需要中途取消此宏的定義,使用#undef#include<stdio.h>#defineMAX0intmain(){inta=1;if(a>MAX)printf("ok");#undefMAXif(a>MAX)printf("ok");return1;}條件編譯例子:你寫了一段代碼打開操作系統(tǒng)的文件,需要在windows和mac上運(yùn)行Win:

intopenfile(constchar*name,intmode)Mac:

intfileop(intmode,constchar*name)方法1,寫到兩個文件中去,不同平臺下選擇不同的文件進(jìn)行編譯非常麻煩,多個平臺下需要多個文件#ifWINDOWSopenfile………#elseMACfileop………#elifLINUX………#endif如何定義時哪個平臺#defineWINDOWS條件編譯的條件應(yīng)該是整數(shù)表達(dá)式,0表示條件不成立,否則條件成立。謂詞defined。使用形式:

defined標(biāo)識符 或defined(標(biāo)識符)當(dāng)標(biāo)識符是有定義的宏名字時,defined(標(biāo)識符)

得到1,否則得0

#ifdef標(biāo)識符 相當(dāng)于#ifdefined(標(biāo)識符)#ifndef標(biāo)識符相當(dāng)于#if!defined(標(biāo)識符)常量定義定義“常量”有三種方式:用enum定義枚舉常量,enum{MON=1,TUE…..}用const定義常值變量,

constintMON=1;用預(yù)處理命令“定義常量”#defineMON1宏定義是簡單正文代換,無語法和語義限制??蓪?biāo)識符代換為任何東西,容易使源程序意義難以理解。原則是:能用其他方式的地方絕不應(yīng)該用宏。枚舉常量值為int,只能用于定義int常量。這種常量可用在需要“常量表達(dá)式”的地方,如作為case標(biāo)號,初始化其他枚舉常量和外部變量等。

enum{MON=1,TUE=2}switch(day){caseMON:printf(“…….”);break;caseTUE:printf(“…….”);break;}const是變量,但不能賦值。const可為任何類型的。const不能用于常量表達(dá)式。如不能用作case標(biāo)號,不能用于初始化外部變量或枚舉常量。還有其他的要求“常量表達(dá)式”的情況,后面介紹。許多書籍用宏定義的方式定義常量。如寫#definelen20#definePi3.14159265建議盡可能用枚舉常量和const。后面程序也這樣做(我保留

溫馨提示

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

最新文檔

評論

0/150

提交評論