版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第六章函數(shù)與編譯預(yù)處理6.1模塊化程序設(shè)計(jì)與函數(shù)6.2函數(shù)的定義與調(diào)用6.3函數(shù)的遞歸調(diào)用6.4變量的作用域與存取方式6.5編譯預(yù)處理C語(yǔ)言程序設(shè)計(jì)教程2025/1/1516.1模塊化程序設(shè)計(jì)與函數(shù)在設(shè)計(jì)較復(fù)雜的程序時(shí),我們一般采用的方法是:把問(wèn)題分成幾個(gè)部分,每部分又可分成更細(xì)的若干小部分,逐步細(xì)化,直至分解成很容易求解的小問(wèn)題。這樣的話,原來(lái)問(wèn)題的解就可以用這些小問(wèn)題來(lái)表示。2基本概念基本模塊模塊模塊模塊模塊模塊模塊模塊模塊模塊2025/1/153模塊與函數(shù)C語(yǔ)言程序由基本語(yǔ)句和函數(shù)組成,每個(gè)函數(shù)可完成相對(duì)獨(dú)立的任務(wù),依一定的規(guī)則調(diào)用這些函數(shù),就組成了解決某個(gè)特定問(wèn)題的程序。4模塊與函數(shù)把大任務(wù)分解成若干功能模塊,用多個(gè)函數(shù)來(lái)實(shí)現(xiàn)這些功能模塊。通過(guò)函數(shù)的調(diào)用來(lái)實(shí)現(xiàn)完成大任務(wù)的全部功能。
5模塊與函數(shù)任務(wù)、模塊與函數(shù)的關(guān)系:一個(gè)大任務(wù)分成多個(gè)功能模塊,
功能模塊則由一個(gè)或多函數(shù)實(shí)現(xiàn)。
模塊化的程序設(shè)計(jì)是靠設(shè)計(jì)函數(shù)和調(diào)用函數(shù)實(shí)現(xiàn)的。6例:分?jǐn)?shù)排序任務(wù):輸入三個(gè)數(shù),從大到小的順序的輸出。如果大 于等于85,在該數(shù)后面輸出‘A’,小于85且大 于等于70,則輸出‘B’,小于70且大于等于60, 輸出‘C’,如果小于60,則輸出‘D’。思路:scanf()輸入分?jǐn)?shù)
另建一個(gè)排序函數(shù)
判斷并輸出等級(jí)函數(shù)
打印分?jǐn)?shù)及等級(jí)的函數(shù)雖然也可以由一個(gè)主函數(shù)來(lái)完成,但這樣做可讀性及操作性會(huì)更好。7
voidmain(){floata,b,c;
scanf("%f,%f,%f",&a,&b,&c);/*輸入*/
sortabc(&a,&b,&c);/*排序*/
putabc(a,b,c);/*輸出a,b,c三個(gè)數(shù)*/}8voidsortabc(a,b,c)floata,b,c;{floatt;if(a<b){t=a;a=b;b=t;}/*交換a,和b的值*/
if(b<c){t=b;b=c;c=t;}/*交換b,和c的值*/
if(a<b){t=a;a=b;b=t;}/*交換a,和b的值*/}9chargrade(x)/*根據(jù)x的值,得到等級(jí)標(biāo)準(zhǔn)*/
floatx;{if(x>=85)return('A');elseif(x>=70)return('B');elseif(x>=60)return('C');else
return('D');
}10
voidputabc(a,b,c)floata,b,c;{charg;g=grade(a);/*判別等級(jí)*/
printf("%6.1f:%c",a,g);g=grade(b);printf("%6.1f:%c",b,g);g=grade(c);printf("%6.1f:%c",c,g);}
11模塊設(shè)計(jì)的原則模塊獨(dú)立規(guī)模適當(dāng)層次分明功能專一12獨(dú)立性原則表現(xiàn)在模塊完成獨(dú)立的功能,和其它模塊間的關(guān)系簡(jiǎn)單,各模塊可以單獨(dú)調(diào)試。修改某一模塊,不會(huì)造成整個(gè)程序的混亂。每個(gè)模塊完成一個(gè)相對(duì)獨(dú)立的特定子功能。在對(duì)任務(wù)逐步分解時(shí),要注意對(duì)問(wèn)題的綜合。例如,一些模塊的相似的子任務(wù),可以把它們綜合起來(lái)考慮,找出它們的共性,把它們做成一個(gè)完成特定任務(wù)的單獨(dú)模塊。每個(gè)模塊有特定功能13模塊之間最好只通過(guò)數(shù)據(jù)傳遞發(fā)生聯(lián)系,而不發(fā)生控制聯(lián)系。例如,C語(yǔ)言禁止goto語(yǔ)句作用到另一個(gè)函數(shù),就是為了保證函數(shù)的獨(dú)立性。每個(gè)模塊力求簡(jiǎn)單14模塊內(nèi)使用的數(shù)據(jù),對(duì)于不需要這些數(shù)據(jù)的其它模塊來(lái)說(shuō),應(yīng)該不允許使用;在一個(gè)模塊內(nèi)的變量的修改不會(huì)影響其它模塊的數(shù)據(jù)。即模塊的私有數(shù)據(jù)只屬于這個(gè)模塊。C語(yǔ)言的局部變量,就是滿足模塊獨(dú)立的的需要。每個(gè)模塊應(yīng)用獨(dú)立變量15模塊不能太大,但也不能太小。模塊的功能復(fù)雜,可讀性就不好,而且也違背獨(dú)立性原則。但如果做得太小,實(shí)際上也會(huì)復(fù)雜各個(gè)模塊間反復(fù)調(diào)用,可讀性也會(huì)降低。這點(diǎn)需要慢慢積累經(jīng)驗(yàn),好好把握。16算法簡(jiǎn)介算法簡(jiǎn)介算法簡(jiǎn)介什么是算法?通俗地說(shuō),算法是解決一類特定問(wèn)題的方法和步驟。
算法是一個(gè)有限操作的序列。算法的每一步都是確定的。算法的每一步計(jì)算機(jī)都能操作。有一個(gè)或多個(gè)的輸入或輸出。17算法的描述算法描述的任務(wù)是將解題步驟和方法用一定的形式表示出來(lái),要清楚、準(zhǔn)確、嚴(yán)謹(jǐn),還要可讀性好,方便實(shí)現(xiàn)。
算法兩大要素:
一是操作,用類計(jì)算機(jī)語(yǔ)句或自然語(yǔ)言描述。
二是控制結(jié)構(gòu),描述算法一般可以用流程圖描述。18例6.2
設(shè)計(jì)算法:找出a,b兩數(shù)中的較大者,并輸出分析:這個(gè)問(wèn)題分三個(gè)步驟:
輸入兩個(gè)數(shù);
找出其中的大數(shù);
輸出大數(shù)。19開(kāi)始輸入a,ba<b交換a,b輸出a結(jié)束非00圖6.3找出a,b兩數(shù)中的較大者算法流程圖
2025/1/15206.2函數(shù)的定義與調(diào)用在C語(yǔ)言中,函數(shù)(Function)是一個(gè)處理過(guò)程,可以進(jìn)行數(shù)值運(yùn)算、信息處理、控制決策,即一段程序的工作放在函數(shù)中進(jìn)行,函數(shù)結(jié)束時(shí)可以攜帶或不帶處理結(jié)果。
庫(kù)函數(shù)(標(biāo)準(zhǔn)函數(shù)):系統(tǒng)提供
自定義函數(shù):用戶自己寫(xiě)
21C語(yǔ)言程序處理過(guò)程全部都是以函數(shù)形式出現(xiàn),最簡(jiǎn)單的程序至少也有一個(gè)main函數(shù)。函數(shù)必須先定義和聲明后才能調(diào)用。22標(biāo)準(zhǔn)庫(kù)函數(shù)C語(yǔ)言有豐富的庫(kù)函數(shù),這些函數(shù)的說(shuō)明在不同的頭文件(*.h)中。想要調(diào)用標(biāo)準(zhǔn)的庫(kù)函數(shù),就必須include。#include<stdio.h>
main()
{printf(“%d”,1024*768);
}調(diào)用printf函數(shù)時(shí),
必須include<stdio.h>23自定義函數(shù)可以把完成一個(gè)任務(wù)的過(guò)程寫(xiě)成函數(shù)。int
A_to_a(intcapital)
{intsmall;
if(capital>=‘A’&&capital<=‘Z’)
small=capital–(‘A’-’a’);
returnsmall;
}返回值類型名函數(shù)名注意不要與已有庫(kù)函數(shù)重名參數(shù)說(shuō)明和參數(shù)列表調(diào)用函數(shù)時(shí)輸入?yún)?shù)的格式要與之相同定義局部變量最好只使用局部變量,這樣將方便調(diào)試。返回值如果不需返回則可return0;另外請(qǐng)注意這樣的判斷,如寫(xiě)成‘A’<capital<‘Z’是不行的24“函數(shù)”的主要知識(shí)點(diǎn)
函數(shù)的定義函數(shù)的參數(shù)和返回值
函數(shù)的調(diào)用嵌套和遞歸變量的作用域25函數(shù)舉例#include<conio.h>
main()
{inta,b,m;
/*說(shuō)明變量*/
int
max(int
a,intb);
/*函數(shù)聲明*/
scanf("%d,%d",&a,&b);
/*調(diào)用庫(kù)函數(shù)scanf*/
m=max(a,b);
/*調(diào)用字定義函數(shù)max*/
printf("max=%d\n",m));
/*調(diào)用庫(kù)函數(shù)printf*/
getch();
/*調(diào)用庫(kù)函數(shù)getch*/
}
26函數(shù)舉例int
max(int
a,intb)
/*定義函數(shù)max*/
{
inty;
y=(a>b)?a:b;/*條件表達(dá)式*/
returny;
}if(a>b)y=a;
elsey=b;27自定義函數(shù)的聲明自定義函數(shù)在調(diào)用前應(yīng)先聲明。使系統(tǒng)知道將要用到某個(gè)函數(shù)及它的類型,以便處理。函數(shù)聲明應(yīng)與該函數(shù)定義時(shí)給出的函數(shù)類型與名字、形參的個(gè)數(shù)、類型、次序相一致。#include“stdio.h”
voidmain()
{floatx,y;
intn;
floatpower(floatx,intn);
scanf("%f,%d",&x,&n);
y=power(x,n);printf(“%8.2f”,y);
}floatpower(floatx,intn)
{inti;
floatt=1;
for(i=1;i<=n;i++)
t=t*x;
returnt;
}28求1!+2!+3!+…+10!算法
i=1;s=0;
當(dāng)i<=10s=s+
i!
定義求i!的函數(shù)29求1!+2!+3!+…+10!程序voidmain(){longmm(int);/*自定義求階乘函數(shù)應(yīng)先聲明*/
inti;longs=0;for(i=1;i<=10;i++)s+=mm(i);/*調(diào)用求階乘函數(shù),求I的階乘*/
printf(“\n%ld”,s);}30定義求n!的函數(shù)longmm(intn){longt=1;inti;for(i=1;i<=n;i++)t*=i;returnt;}31同樣的,在調(diào)用
m=max(a,b)時(shí),其形參
的值是a和b
而m將會(huì)得到y(tǒng)的值函數(shù)的參數(shù)int
max(int
a,intb)
{
inty;
y=(a>b)?a:b;
returny;
}調(diào)用時(shí):m=max(3,6);
m=max(a,b);
括號(hào)里是形式參數(shù)返回值括號(hào)里是實(shí)參在這一句調(diào)用時(shí),
形參的值是3和6其返回值y將被賦給
調(diào)用語(yǔ)句中的m32形式參數(shù)與實(shí)際參數(shù)的關(guān)系形式參數(shù)在函數(shù)中是變量名,
在函數(shù)調(diào)用時(shí),形參被分配相應(yīng)的內(nèi)存實(shí)際參數(shù)是表達(dá)式
負(fù)責(zé)向?qū)?yīng)的形參標(biāo)識(shí)的內(nèi)存單元傳遞數(shù)據(jù)實(shí)參與形參必須個(gè)數(shù)相同對(duì)應(yīng)的形參和實(shí)參的類型必須一致
實(shí)參給形參傳遞值得時(shí)候,按順序傳遞,與形參名無(wú)關(guān)。所以實(shí)參與形參可以不同名。33實(shí)參與形參例:主調(diào)函數(shù)中有如下語(yǔ)句:
scanf("%d,%d",&a,&b);
m=max(a,b+3);如果輸入6,2函數(shù)int
max(int
a,intb)形參a得到第一個(gè)實(shí)際參數(shù)a的值6形參b得到第二個(gè)實(shí)際參數(shù)b+3的值5
34函數(shù)返回值函數(shù)返回值通過(guò)return語(yǔ)句獲得函數(shù)返回值的類型就是函數(shù)的類型
returny;
將變量y的值返回給調(diào)用者
returny+3;
將表達(dá)式的值返回給調(diào)用者35return的數(shù)據(jù)類型與函數(shù)的類型矛盾時(shí),自動(dòng)將數(shù)據(jù)轉(zhuǎn)換成函數(shù)的類型intfunct1(){charch;
while
((ch=getch())<'a'||(ch>'z')
;
returnch;}調(diào)用:i=funct1();/*返回的是int類型*/36函數(shù)沒(méi)有返回值,函數(shù)定義成空類型voidputline()
{inti;
for(i=0;i<35;i++)
printf("-");
printf("\n");
}函數(shù)的功能就是輸出35個(gè)‘-’
調(diào)用:putline();
應(yīng)該的語(yǔ)句形式
i=putline();是錯(cuò)的37調(diào)用函數(shù)a=function(x,y);
或者
function(x,y);
取返回值
只是操作解決更復(fù)雜問(wèn)題時(shí)可以嵌套調(diào)用。longfac(intk)
{longf=1;
inti;
for(i=1;i<=k;i++)
f=f*i;
returnf;
}
longcombination(intn,intm)
{longc;
inti;
c=fac(m)/(fac(n)*fac(m-n));
returnc;
}
主函數(shù):
main()
{intn,m;
longc;
scanf(“%d,%d”,&n,&m);
c=combination(n,m);
printf(“%ld”,c);
}理論上可以a(b(d(e(x))),c(f))
般嵌套無(wú)數(shù)層。386.3函數(shù)的遞歸調(diào)用函數(shù)調(diào)用它本身,稱為遞歸。直接在函數(shù)內(nèi)調(diào)用自己為直接遞歸,通過(guò)別的函數(shù)調(diào)用自己為間接遞歸。voida()
{......
a();
......
}voida()
{......
b();......
}
voidb()
{......
a();
......
}遞歸在解決某些問(wèn)題中,是一個(gè)十分有用的方法。因?yàn)槠湟?有的問(wèn)題它本身就是遞歸定義的;其二,它可以使某些看起來(lái)不易解決的問(wèn)題變得容易解決,寫(xiě)出的程序較簡(jiǎn)短。39遞歸方法求n!由于n!=n*(n-1)!是遞歸定義所以求n!
(n-1)!
(n-1)!
(n-2)!
(n–2)!
(n-3)!
……
0!的問(wèn)題,
根據(jù)公式有0!=1。
再反過(guò)來(lái)依次求出1!,2!……直到最后求出n!。40遞歸方法求n!longfac(intn)
{longf;
if(n==0)
f=1;
else
f=n*fac(n-1);
returnf;
}
main()
{longy;
intn;
scanf(“%d”,&n);
y=fac(n);
printf(“%d!=%ld”,n,y);
}剛開(kāi)始的時(shí)候,這個(gè)n是前面
輸入的需要階乘的n所以在這里帶入的值是n而這個(gè)函數(shù)里又調(diào)用
了本身,不過(guò)參數(shù)已經(jīng)
變成了n-1所以這里再次調(diào)用時(shí)
參數(shù)已經(jīng)變成了n-1注意:上次調(diào)用fac(n)
還沒(méi)有完,只是由于遇到
了fac(n-1)而執(zhí)行fac(n-1)
去了.而在調(diào)用fac(n-1)時(shí)同樣
遇到了要調(diào)用fac(n-2)的問(wèn)題,于是一層一層的
包裹下去,每次調(diào)用的
時(shí)候都會(huì)在內(nèi)部調(diào)用一
個(gè)結(jié)構(gòu)相同但變量不同
的函數(shù),直到。。。直到調(diào)用到fac(0)時(shí),由于內(nèi)部if判斷,已經(jīng)
不需要再繼續(xù)調(diào)用另一
個(gè)fac(n-1),而直接有了f=1fac(0)已經(jīng)執(zhí)行完畢,它的
返回值被fac(1)中的f=n*fac(n-1)
語(yǔ)句賦給了f值,同時(shí)返回了f。而這個(gè)返回的f又被fac(2)乘上
當(dāng)前的n值以后繼續(xù)返回f直到最后的fac(n)都做完了,
f的值被返回到了它的調(diào)用點(diǎn):
主函數(shù)中,這樣就是一個(gè)遞歸
運(yùn)算。41遞歸舉例問(wèn)題:第1個(gè)月有1對(duì)兔子過(guò)2個(gè)月,兔子就可每個(gè)月生1對(duì)兔子問(wèn)第n個(gè)月有多少對(duì)兔子?
分析:設(shè)第n個(gè)月有f(n)對(duì)兔子根據(jù)題意有f(0)=0,f(1)=1f(n)=f(n-1)+f(n-2)f(n-1):前一個(gè)月的兔子數(shù)
f(n-2):本月生的兔子數(shù)
42斐波那契其人1170年生于意大利的比薩,在北非的布吉亞,即今阿爾及利亞的貝加亞長(zhǎng)大并且接受教育。大約在1200年,他才重新回到比薩。斐波那契無(wú)疑在啟蒙教育時(shí)期就受到過(guò)阿拉伯?dāng)?shù)學(xué)家的影響或者接受過(guò)他們的輔導(dǎo)。他寫(xiě)過(guò)大量的數(shù)學(xué)論文,取得了一些重大的數(shù)學(xué)發(fā)現(xiàn)。這使他的著作在意大利非常流行,并且引發(fā)了當(dāng)時(shí)羅馬帝國(guó)皇帝弗雷德里克二世的注意,他曾邀請(qǐng)斐波那契到他在比薩宮廷覲見(jiàn)。斐波那契于1250年去世。1202年,他在所著的《算珠原理》中,提出了一個(gè)著名而有趣的兔子問(wèn)題:假定一對(duì)小兔子經(jīng)過(guò)一個(gè)月后能夠長(zhǎng)成一對(duì)大兔子,而一對(duì)大兔子經(jīng)過(guò)一個(gè)月后能夠生了一對(duì)小兔子.現(xiàn)在我們從一對(duì)小兔子開(kāi)始,用表示第個(gè)月兔子的總對(duì)數(shù),顯然,(第1個(gè)月只有一對(duì)小兔子,第2個(gè)月只有一對(duì)大兔子),(第3個(gè)月一對(duì)大兔子生出一對(duì)小兔子,總共兩對(duì)兔子.
于是我們得到一個(gè)數(shù)列:1,1,2,3,5,8,13,…
仔細(xì)觀察這個(gè)數(shù)列,從第3項(xiàng)起每一項(xiàng)都是它前相鄰兩項(xiàng)的和,這就是著名的斐波那契數(shù)列.43定義函數(shù)f(n)longf(intn)
{
switch(n){case0:return0;break;case1:return1;break;
default:returnf(n-1)+f(n-2);/*調(diào)用函數(shù)f(n)*/}}44兔子問(wèn)題主函數(shù)voidmain(){longf(intn);/*自定義函數(shù)聲明*/
intn;
printf(“\ninputn:”);
scanf(“%d”,&n);
printf(“\nf(%d)=%ld”,n,f(n));
/*調(diào)用函數(shù)f(n)*/}45斐波那契數(shù)列有一系列奇妙的性質(zhì),現(xiàn)簡(jiǎn)列以下幾條,供大家欣賞.
1.從首項(xiàng)開(kāi)始,我們依次計(jì)算每一項(xiàng)與它的后一項(xiàng)的比值,并精確到小數(shù)是第四位.如果將這一工作不斷地繼續(xù)下去,這個(gè)比值將無(wú)限趨近于某一個(gè)常數(shù),這個(gè)常數(shù)位于1.6180與1.6181之間,它還能準(zhǔn)確地用黃金數(shù)表示出黃金分割率。
2.在自然界中,斐波那契數(shù)列也常見(jiàn)到,比如:向日葵花冠上的螺旋,如果前一道螺旋直徑為21的話,下一道螺旋直徑則為34,依次形成連續(xù)的斐波那契數(shù)字;松果的外弧為順時(shí)針或逆時(shí)針?lè)较虻穆菪?,期相同間隔之間螺旋的直徑也能構(gòu)成斐波那契數(shù)列;在上等的鸚鵡螺身上,每圈羅紋的直徑與相鄰羅紋直徑之比亦是1:1.618,菠蘿是又一種可以檢驗(yàn)斐波那契數(shù)的植物;菠蘿表皮方塊形鱗苞形成兩組旋向相反的螺線,它們的條數(shù)必須是這個(gè)級(jí)數(shù)中緊鄰的兩個(gè)數(shù)字(如左旋8行,右旋13行)。
463.有一種兩人游戲,名叫“尼姆”。游戲方法是由兩個(gè)人輪流取一堆粒數(shù)不限的砂子。先取的一方可以取任意粒,但不能把這堆砂子全部取走。后取的一方,取數(shù)也多少不拘,但最多不能超過(guò)對(duì)方所取砂子數(shù)的一倍。然后又輪到先取的一方來(lái)取,但也不能超過(guò)對(duì)方最后一次所取砂子的一倍。這樣交替地進(jìn)行下去,直到全部砂子被取光為止,誰(shuí)能拿到最后一粒砂子,誰(shuí)就算勝利者。在這個(gè)游戲中,若所有砂子的粒數(shù)是個(gè)斐波那契數(shù)的話,那么后取的一方穩(wěn)操勝券,但所有的砂子不是一個(gè)斐波那契數(shù)的話,那么先取的一方穩(wěn)勝。47輾轉(zhuǎn)相除法求最大公約數(shù)求m和n的公約數(shù)算法if(m%n)==0
n是公約數(shù);
else
求n和m%n的公約數(shù);
48用歐幾里德算法(輾轉(zhuǎn)相除法)求兩個(gè)數(shù)的最大公約數(shù)的步驟如下:
1.若r是a÷b的余數(shù),則
gcd(a,b)=gcd(b,r)
2.a和其倍數(shù)之最大公因子為a。
49求最大公約數(shù)的遞歸算法
int
gcd(intm,intn)
{if(m%n)==0
returnn;
else
returngcd(n,
m%n);}50求最大公約數(shù)的主函數(shù)voidmain(){intm,n,t;
int
gcd(intm,intn);
scanf(“%d%d”,&m,&n);
if(m<n)
{t=m;m=n;n=t;}
t=gcd(m,n);/*調(diào)用函數(shù)gcd(m,n);
*/print(“\ngcd=%d”,t);}51漢諾塔(又稱河內(nèi)塔)問(wèn)題是印度的一個(gè)古老的傳說(shuō)。開(kāi)天辟地的神勃拉瑪在一個(gè)廟里留下了三根金剛石的棒,第一根上面套著64個(gè)圓的金片,最大的一個(gè)在底下,其余一個(gè)比一個(gè)小,依次疊上去,廟里的眾僧不倦地把它們一個(gè)個(gè)地從這根棒搬到另一根棒上,規(guī)定可利用中間的一根棒作為幫助,但每次只能搬一個(gè),而且大的不能放在小的上面。面對(duì)龐大的數(shù)字(移動(dòng)圓片的次數(shù))18446744073709551615,看來(lái),眾僧們耗盡畢生精力也不可能完成金片的移動(dòng)。漢諾塔52后來(lái),這個(gè)傳說(shuō)就演變?yōu)闈h諾塔游戲:
1.有三根桿子A,B,C。A桿上有若干碟子。
2.每次移動(dòng)一塊碟子,小的只能疊在大的上面。
3.把所有碟子從A桿全部移到C桿上。經(jīng)過(guò)研究發(fā)現(xiàn),漢諾塔的破解很簡(jiǎn)單,就是按照移動(dòng)規(guī)則向一個(gè)方向移動(dòng)金片,如3階漢諾塔的移動(dòng):A→C,A→B,C→B,A→C,B→A,B→C,A→C此外,漢諾塔問(wèn)題也是程序設(shè)計(jì)中的經(jīng)典遞歸問(wèn)題。
算法思路:
1.如果只有一個(gè)金片,則把該金片從源移動(dòng)到目標(biāo)棒,結(jié)束。
2.如果有n個(gè)金片,則把前n-1個(gè)金片移動(dòng)到輔助的棒,然后把自己移動(dòng)到目標(biāo)棒,最后再把前n-1個(gè)移動(dòng)到目標(biāo)棒
53漢諾塔是一個(gè)很繁雜的游戲,但用遞歸的方法解決起來(lái)異常簡(jiǎn)單。規(guī)則:(1)一次只能移動(dòng)一個(gè)
(2)大的不能放在小的上面
(3)只能在三個(gè)位置中移動(dòng)54問(wèn)題可分為三個(gè)步驟對(duì)于把n個(gè)金片從第一根針a上移到第三根針c的問(wèn)題可以分解成如下步驟:
(1)將n-1個(gè)金片從a經(jīng)過(guò)c移動(dòng)到b。(2)將第n個(gè)金片移動(dòng)到c。(3)再將n-1個(gè)盤(pán)子從b經(jīng)過(guò)a移動(dòng)到c。這樣我們就將移動(dòng)n個(gè)金片的問(wèn)題變成了移動(dòng)n-1個(gè)金片的問(wèn)題。這樣做下去的話最后就會(huì)變成移動(dòng)一個(gè)金片的問(wèn)題。55遞歸方法解漢諾塔voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}n=1時(shí),直接將金片
從a移動(dòng)到cn-1個(gè)金片從a經(jīng)過(guò)
c移動(dòng)到b將第n個(gè)金片
從a移動(dòng)到c再將n-1個(gè)金片從
b經(jīng)過(guò)a移動(dòng)到cmain()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}56遞歸漢諾塔步驟voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}main()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}輸入3。則n=357遞歸漢諾塔步驟voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}main()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}
主函數(shù)調(diào)用hanoi(n,1,2,3);第一次調(diào)用。第一次調(diào)用hanoi(n,a,b,c)(第一層)即要把三個(gè)金片移到cn=358遞歸漢諾塔步驟voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}main()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}由于n>1則執(zhí)行hanoi(n-1,a,c,b)
(第二次調(diào)用)n=359遞歸漢諾塔步驟voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}main()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}由于仍然n>1則執(zhí)行
hanoi(n-1,a,c,b)
(第三次調(diào)用)n=260遞歸漢諾塔步驟voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}main()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}由于n=1則printf(“%d->%d”,a,c);
即把金片從a移動(dòng)到c
n=161遞歸漢諾塔步驟voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}main()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}第三層執(zhí)行完畢,返回到第二層,即下去執(zhí)行printf(“%d->%d”,a,c);把第二個(gè)金片擺到第二根針上n=262遞歸漢諾塔步驟voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}main()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}執(zhí)行下一條語(yǔ)句,又調(diào)用第三層hanoi(1,3,1,2)n=263遞歸漢諾塔步驟voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}main()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}n=1,執(zhí)行結(jié)果為32n=164遞歸漢諾塔步驟voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}main()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}第二層也執(zhí)行完了,返回第一層,執(zhí)行接下來(lái)的語(yǔ)句,結(jié)果為13。n=365遞歸漢諾塔步驟voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}main()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}執(zhí)行接下來(lái)的語(yǔ)句,再次調(diào)用
第二層hanoi(2,2,1,3)n=366遞歸漢諾塔步驟voidhanoi(intn,inta,intb,intc)
{
if(n==1)
printf(“%d->%d”,a,c);
else
{hanoi(n-1,a,c,b);
printf(“%d->%d”,a,c);
hanoi(n-1,b,a,c);
}
}main()
{intn;
printf(“inputn:”);
scanf(“%d”,&n);
hanoi(n,1,2,3);
}676.4變量的作用域與存儲(chǔ)方式先看一個(gè)例子,錯(cuò)在那里?:voidf1(){intt=2;a*=t;b/=t;}main(){inta,b;
printf(“Entera,b:”);
scanf(“%d,%d”,&a,&b);f1();/*調(diào)用函數(shù)f1()*/
printf(“a=%d,b=%d”,a,b);}編譯程序會(huì)提示出錯(cuò):Undefinedsymbol‘a(chǎn)’和Undefinedsymbol‘b’
。為什么?2025/1/1568一.變量的作用域
即變量的有效范圍1.變量按作用域分為全局變量和局部變量2.比較:全局變量(外部變量)局部變量(內(nèi)部變量)定義位置:函數(shù)體外函數(shù)體內(nèi)作用域:從定義處到本源從定義處到本函數(shù)結(jié)束文件結(jié)束舉例:所有函數(shù)體外定義的變量(1)所有在函數(shù)體內(nèi)定義(2)形式參數(shù)注意與局部變量同名的處理局部變量屏蔽全局變量不同函數(shù)中同名局部變量互不干擾
2025/1/1569#include<stdio.h>inta,b;/*a,b為全局變量*/voidf1(intx){intt1,t2,a;a=t1=x*4;t2=b*3;b=10;
printf(“f1:t1=%d,t2=%d,a=%d,b=%d\n”,t1,t2,a,b);}main(){a=2;b=4;/*此a,b是全局變量,賦值*/
f1(a);/*調(diào)用函數(shù)f1()*/
printf(“main:a=%d,b=%d”,a,b);}
程序輸出結(jié)果為:
f1:t1=8,t2=12,a=8,b=10main:a=2,b=102025/1/1570若將程序改為:#include<stdio.h>inta=2,b=4;/*a,b為全局變量*/
voidf1(){intt1,t2;t1=a*2;t2=b*3;b=100;
printf(“t1=%d,t2=%d,b=%d\n”,t1,t2,b);}main(){intb=4;/*此b是局部變量,賦值*/
f1();/*調(diào)用函數(shù)f1()*/
printf(“a=%d,b=%d”,a,b);}結(jié)論:全局變量與局部變量同名時(shí),局部變量起作用,全局變量被屏蔽(不影響),應(yīng)小心使用程序輸出結(jié)果為:t1=4,t2=12,b=100a=2,b=42025/1/1571二.變量的存儲(chǔ)特性1.變量按存在時(shí)間分
靜態(tài)變量動(dòng)態(tài)變量靜態(tài)存儲(chǔ)類型的變量的生存期為程序執(zhí)行的整個(gè)過(guò)程,在該過(guò)程中占有固定的存儲(chǔ)空間,通常稱它們?yōu)橛谰么鎯?chǔ)。動(dòng)態(tài)存儲(chǔ)類型變量只生存在某一段時(shí)間內(nèi)。例如,函數(shù)的形參和函數(shù)體或分程序中定義的變量,只是在程序進(jìn)入該函數(shù)或分程序時(shí)才分配存儲(chǔ)空間,當(dāng)該函數(shù)或分程序執(zhí)行完后,變量對(duì)應(yīng)的存儲(chǔ)空間又被撤銷了。2.c語(yǔ)言中每一個(gè)變量有兩個(gè)屬性:數(shù)據(jù)類型,存儲(chǔ)特性完整的變量定義:[存儲(chǔ)特性][數(shù)據(jù)類型]變量名;2025/1/15723.變量的存儲(chǔ)特性自動(dòng)型auto
靜態(tài)型static
寄存器型register
外部型extern(1)auto型每次進(jìn)入程序是自動(dòng)分配內(nèi)存,不長(zhǎng)期占用內(nèi)存例如:形式參數(shù),自動(dòng)型局部變量(2)static型①局部靜態(tài)變量②全局靜態(tài)變量長(zhǎng)期占用內(nèi)存2025/1/1573例1:分析執(zhí)行結(jié)果f(inta){intb=0;staticintc=3;b++;c++;printf(“%5d%5d%5d”,a,b,c);return(a+b+c);}main(){inta=2,k;for(k=0;k<3;k++)printf(“%5d\n”,f(a));}靜態(tài)變量只初始化一次。再次調(diào)用定義它的函數(shù)時(shí)變量保存了前一次被調(diào)用后留下的值。結(jié)果:214(a,b,c)7(f(a))215821692025/1/1574(3)register型將使用頻率高的變量定義為register型,可以提高運(yùn)行速度.數(shù)據(jù)內(nèi)存運(yùn)算器運(yùn)算器結(jié)果控制器數(shù)據(jù)寄存器寄存器變量只限于整型、字符型、指針型的局部變量。寄存器變量是動(dòng)態(tài)變量,而且數(shù)目有限,一般僅允許說(shuō)明兩個(gè)寄存器變量。例如:
registerintd;registercharc;2025/1/1575(4)extern型引用:extern類型變量名;如果某個(gè)模塊文件中要用到另一個(gè)模塊文件中的全局變量,就要用extern說(shuō)明例如:程序模塊file1.c中定義了全局變量
ints;而在另一個(gè)程序模塊file2.c中的函數(shù)fun1()中需要使用這個(gè)變量s。為此,可以在file2.c的函數(shù)fun1()中加上外部變量說(shuō)明語(yǔ)句:fun1(){externints;/*表明變量s是在其他文件定義的*/.......}定義時(shí)分配內(nèi)存,其他文件引用時(shí)不再分配內(nèi)存.2025/1/15766.5編譯預(yù)處理
“編譯預(yù)處理”是C語(yǔ)言編譯系統(tǒng)的一個(gè)組成部分。是在編譯前由編譯系統(tǒng)中的預(yù)處理程序?qū)υ闯绦虻念A(yù)處理命令進(jìn)行加工。源程序中的預(yù)處理命令均以“#”開(kāi)頭,結(jié)束不加分號(hào),以區(qū)別源程序中的語(yǔ)句,它們可以寫(xiě)在程序中的任何位置,作用域是自出現(xiàn)點(diǎn)到源程序的末尾。預(yù)處理命令包括執(zhí)行宏定義(宏替換)、包含文件和條件編譯。2025/1/1577一.宏定義簡(jiǎn)單宏定義1.一般形式為:#define宏名串(宏體)如:#definePI3.14159/*定義后,可以用PI來(lái)代替串3.14159*/2.宏定義的作用在宏定義之后,該程序中宏名就代表了該字符串。3.說(shuō)明①可以用#undef命令終止宏定義的作用域。例如:#undefPI②宏定義的嵌套使用#defineR3.0#definePI3.1415926#defineL2*PI*R/*宏體是表達(dá)式*/#defineSPI*R*R2025/1/1578main(){printf("L=%f\nS=%f\n",L,S);/*2*PI*R替換L,PI*R*R替換S*/}程序運(yùn)行結(jié)果如下:L=18.849556S=28.247333③雙引號(hào)內(nèi)與宏同名的字母不作宏展開(kāi).(見(jiàn)上例)帶參數(shù)的宏定義1.帶參數(shù)的宏定義的一般形式為#define宏名(參數(shù)表)字符串如:#defineS(a,b)a*b#definePR(x)printf("s=%f\n”,x)2025/1/15792.帶實(shí)參的宏名被展開(kāi)宏名被所定義的宏體替換,宏體中的形參按從左到右的順序被實(shí)參替換。例如:#defineL(x)(x*x+2*x+x)宏調(diào)用:y=L(5);調(diào)用時(shí)用實(shí)參5去代替形參
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 花生致敏蛋白Ara h 3免疫層析試紙快速檢測(cè)方法的建立
- 2025年北京戲曲藝術(shù)職業(yè)學(xué)院高職單招高職單招英語(yǔ)2016-2024歷年頻考點(diǎn)試題含答案解析
- 2025年北京交通運(yùn)輸職業(yè)學(xué)院高職單招高職單招英語(yǔ)2016-2024歷年頻考點(diǎn)試題含答案解析
- 2025年內(nèi)蒙古豐州職業(yè)學(xué)院高職單招語(yǔ)文2018-2024歷年參考題庫(kù)頻考點(diǎn)含答案解析
- 2025年克孜勒蘇職業(yè)技術(shù)學(xué)院高職單招職業(yè)適應(yīng)性測(cè)試近5年??及鎱⒖碱}庫(kù)含答案解析
- 2025年保定職業(yè)技術(shù)學(xué)院高職單招高職單招英語(yǔ)2016-2024歷年頻考點(diǎn)試題含答案解析
- 2025年云南外事外語(yǔ)職業(yè)學(xué)院高職單招語(yǔ)文2018-2024歷年參考題庫(kù)頻考點(diǎn)含答案解析
- 2025年三亞城市職業(yè)學(xué)院高職單招語(yǔ)文2018-2024歷年參考題庫(kù)頻考點(diǎn)含答案解析
- 移動(dòng)端觸覺(jué)反饋設(shè)計(jì)-洞察分析
- 疫苗與宿主相互作用-洞察分析
- 農(nóng)民工工資表格
- 【寒假預(yù)習(xí)】專題04 閱讀理解 20篇 集訓(xùn)-2025年人教版(PEP)六年級(jí)英語(yǔ)下冊(cè)寒假提前學(xué)(含答案)
- 2024年智能監(jiān)獄安防監(jiān)控工程合同3篇
- 幼兒園籃球課培訓(xùn)
- 統(tǒng)編版(2024新版)七年級(jí)《道德與法治》上冊(cè)第一單元《少年有夢(mèng)》單元測(cè)試卷(含答案)
- 100道20以內(nèi)的口算題共20份
- 高三完形填空專項(xiàng)訓(xùn)練單選(部分答案)
- 護(hù)理查房高鉀血癥
- 項(xiàng)目監(jiān)理策劃方案匯報(bào)
- 《職業(yè)培訓(xùn)師的培訓(xùn)》課件
- 建筑企業(yè)新年開(kāi)工儀式方案
評(píng)論
0/150
提交評(píng)論