C06函數的應用課件_第1頁
C06函數的應用課件_第2頁
C06函數的應用課件_第3頁
C06函數的應用課件_第4頁
C06函數的應用課件_第5頁
已閱讀5頁,還剩106頁未讀 繼續免費閱讀

付費下載

下載本文檔

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

文檔簡介

16四月2024C06函數的應用2第6章函數的應用3本章主要內容函數系統函數用戶自定義函數函數調用過程中參數傳遞函數重載帶有缺省參數值的函數內聯函數遞歸函數局部變量和全局變量變量的存儲類別4函數的定義C++中的函數由一段相對獨立的程序組成,這段程序能實現某一方面獨立和完整的功能。5例求5!+4!#include<iostream.h>intfactorial(intn){ intz,i; z=1; for(i=1;i<=n;i++) z=z*i; returnz;}voidmain(){ intx; x=factorial(5)+factorial(4); cout<<”5!+4!=”<<x<<endl;}程序運行結果:5!+4!=144函數的定義6注意:

1.有且僅有一個main函數,從它開始執行,它結束則整個程序結束。

2.除main函數外,還可設計任意多個自定義函數,并可將它們劃分存放于1至若干個源程序文件中。

3.各函數的“級別”相同,可相互調用,但不可調main。

4.除上述主體部分外,如有必要,還可在函數之外加入全局量說明及編譯預處理指令等。函數的定義7main()fun2()fun1()fun3()Fun1_1()Fun2_1()Fun2_2()函數調用層次關系函數的定義8

.從使用角度分類

.從函數形式分類.從返回值分類函數的分類9

(1)從使用角度分類從使用角度劃分,可將函數分為:系統預定義的標準庫函數(如,sin,abs等),以及由用戶自定義的函數。程序中可直接使用(調用)系統預定義的標準庫函數,但要求在調用前使用編譯預處理指令include將對應的頭文件包含進來。由用戶自定義的函數與系統預定義的標準庫函數的不同點在于,自定義函數的函數名、參數個數、函數返回值類型以及函數所實現的功能等都完全由用戶程序來規定(指定)。10(2)從函數形式分類

從函數形式劃分,可分為無參函數與有參函數兩類。對無參函數來說,調用它們時不需要提供實際參數;而對有參函數進行調用時,必須提供所需個數的且具有相匹配數據類型的實際參數。11(3)從返回值分類

從返回值劃分,可分為有返回值函數與無返回值函數兩類。對有返回值函數來說,必須用int等類型修飾符說明返回值類型,必須在函數體采用:【return表達式;】結束函數;無返回值函數用void作為類型修飾符,因此也稱為void函數,在無返回值的函數中可以用【return;】結束函數的運行,也可以不用任何return語句。12C++系統函數C++的系統庫中提供了幾百個函數可供程序員使用,包括許多在各種程序中常用的基本任務處理函數,這些庫函數被分成不同的組,例如,數學計算、字符處理、字符串處理、I/O操作、圖形處理等等。例如:求平方根函數(sprt)、求絕對值函數(abs)等。使用系統函數時要包含相應的頭文件。例如:math.h或cmath分別求x的正弦值、余弦值、正切值;x為弧度數doublesin(doublex)doublecos(doublex)doubletan(doublex)lnx即logexlog10xdoublelog(doublex)doublelog10(doublex)x的y次冪e的x次冪doublepow(doublex,doubley)doubleexp(doublex)分別求整型數、長整型、浮點數的絕對值intabs(inti)longlabs(longn)doublefabs(doublex)math.hcmath求x的平方根doublesqrt(doublex)數學C式頭文件C++頭文件功能簡述

原型

類別

C++系統函數注意:在C++中,舊式的C風格的頭文件去掉了后綴.h,加上了前綴C,如stdlib.h在C++中變成了Cstdlib。當使用了:#include<iostream>

usingnamespacestd;時,許多頭文件不需要包含了。在上面的表中,用iostream表示不再需要包含相應的C++風格的頭文件。C式頭文件C++頭文件功能簡述

原型

類別

將整數v按x進制轉成字符串schar*itoa(intv,char*s,intx)time.hctime返回1970/1/1零點到目前的秒數time_ttime(time_t*timer)時間

設置隨機數的種子

產生0-RAND_MAX的隨機數rand(unsignedseed)intrand()stdlib.hiostream將字符串轉化成整數intatoi(char*s)類型轉換memory.hiostream將s指向的內存區域的c個字節拷貝到d指向的區域void*memcpy(void*d,void*s,intc)內存操作unsignedstrlen(char*str)unsignedstrlen(char*str)其它字符串

字符stdlib.hiostream終止正在執行的程序exit(int)string.hiostreamchar*strcpy(char*s1,char*s2)char*strcpy(char*s1,char*s2)將c轉換成小寫、大寫字母inttolower(intc),inttoupper(intc)ctype.hiostreamc是否是字母,c是否是數字intisalpha(intc),intisdigit(intc)math.hcmath分別求x的反正弦值、反余弦值、反正切值doubleasin(doublex)doubleacos(doublex)doubleatan(doublex)數學C++系統函數15查找系統函數的使用說明查編譯系統的庫函數手冊查聯機幫助——VC++6.0聯機幫助的使用方法:help/Contents

->(“活動子集”欄)VisualC++Documentation->VisualC++Documentation

->UsingVisualC++

->VisualC++Programmer'sGuide

->Run-TimeLibraryReference->RunTimeRoutinesbyCategory

->RunTimeRoutinesbyCategoryC++系統函數16例系統函數應用舉例題目:從鍵盤輸入一個角度值,求出該角度的正弦值、余弦值和正切值。分析:系統函數中提供了求正弦值、余弦值和正切值的函數:sin()、cos()、tan(),函數的說明在頭文件math.h中。17#include<iostream>#include<cmath>usingnamespacestd;constdoublepi(3.14159265);voidmain(){doublea,b;cin>>a;b=a*pi/180;cout<<"sin("<<a<<")="<<sin(b)<<endl;cout<<"cos("<<a<<")="<<cos(b)<<endl;cout<<"tan("<<a<<")="<<tan(b)<<endl;}運行結果:30sin(30)=0.5cos(30)=0.866025tan(30)=0.577351718產生隨機函數

必須在使用隨機數產生器前初始化該隨機數產生器

rand()srand(seed)庫ctime中的time()返回系統時鐘自1970年1月1日午夜開始已經消耗的秒數使用time()函數作為srand()函數隨機種子的語法:

srand(time(NULL));可使用:下限+rand()%(上限-下限+1)來指定產生的數值范圍19例找最大數和最小數

constSIZE=15;

voidmain(){intarr[SIZE],i,high,low;for(i=0;i<SIZE;i++)arr[i]=rand()%(100-1+1);cout<<"Herearethe"<<SIZE<<"randomnumbers:"<<endl;for(i=0;i<SIZE;i++)cout<<arr[i]<<'\t';cout<<endl;high=arr[0];//初始化時最大和最小值均為數組首元素low=arr[0];for(i=1;i<SIZE;i++){if(arr[i]>high)high=arr[i]; if(arr[i]<low)low=arr[i];}cout<<"highestvalueis"<<high<<endl;cout<<"lowestvalueis"<<low<<endl;return;}#include<iostream>usingnamespacestd;voidmain(){intx,i(0);

srand(124);//設置種子do{x=rand()%(100-1+1);if(x>=5&&x<=1000){ x=(x/5)*5; cout<<x/10.0<<"\t"; i++;}}while(i<100);}隨機函數例產生100個學生的某門功課的成績,要求精確到0.5分。

解釋:

第10行設置隨機數種子,使用rand()產生隨機數時,以種子為基準,種子相同,每次產生的隨機數也相同。

21控制字符串的大小寫#include<algorithm>將字符串轉換大小寫的函數:

transform(s1.begin(),s1.end(),

s2.begin(),function)轉換結果首地址toupper或tolowerS1串截止位,但不含該位22#include<iostream>#include<algorithm>#include<string>usingnamespacestd;voidmain(){strings,p="";cin>>s;//cin以分隔符作為結束標志transform(s.begin(),s.end(),p.begin(),toupper);cout<<"s:"<<s<<"/size:"<<s.size()<<endl;cout<<"p:"<<p<<"/size:"<<p.size()<<endl;}23函數的定義函數定義的基本格式:

類型修飾符

函數名(形式參數表)函數體幾點說明:函數體:一個復合語句,用{}括起來的語句序列。形式參數表:一系列用逗號隔開的形式參數說明。可以沒有參數,但必須有()。函數根據有無參數分為有參函數和無參函數兩類。類型修飾符:指明函數返回值的類型,如int,double,bool等,類型修飾符也可為void,表示無返回值的函數。函數根據返回值的情況分為有返回值函數和無返回值函數兩類24有返回值函數必須用int等類型修飾符說明返回值類型必須在函數體采用:return表達式;結束函數例:doublesqare(doublen){returnn*n}boolisPositive(intn){ if(n>0) returntrue; else returnfalse; }returnn>0;簡化為25無返回值函數用void作為類型修飾符,因此也稱為void函數。在無返回值的函數中可以用return;結束函數的運行也可以不用任何return語句例:(以下兩種函數定義均可)voidHi(void){cout<<“Hi!”<<endl;return;}voidHi(){cout<<“Hi!”<<endl;}26

關于return語句

return語句(稱為返回語句)具有如下三種使用格式:

return; return<表達式>; return(<表達式>);

第一種格式的return用于立即從被調函數中返回,當函數類型為void時,應使用這種格式的返回語句。 當函數類型為非void型時,應使用第二或第三種格式的return語句,此兩種格式的語句效果完全相同(可將第二種格式看成是第三種格式的省略形式),系統此時都將計算出表達式的值,并“攜帶”該值立即從被調函數中返回。27例設計函數,根據三角形的三邊長求面積。如果不能構成三角形,給出提示信息。分析:函數為計算三角形面積,一般三角形返回面積值,若不能構成三角形則返回-1。設計一個主函數完成函數測試。根據返回值情況輸出相應結果。程序如下:#include<iostream.h>#include<math.h>28floatTriangleArea(floata,floatb,floatc){ if((a+b<=c)||(a+c<=b)||(b+c<=a))return-1; floats;s=(a+b+c)/2; returnsqrt(s*(s-a)*(s-b)*(s-c));}voidmain(){floata,b,c,area; cout<<"輸入三角形三邊a,b,c:"<<endl; cin>>a>>b>>c; area=TriangleArea(a,b,c); if(area==-1) cout<<'('<<a<<','<<b<<','<<c<<')‘<<"不能構成三角形!"<<endl; else cout<<"三角形(“<<a<<','<<b<<','<<c<<")面積為:"<<area<<endl;}調用TriangleArea(3,4,5)函數TriangleArea(3,4,5)return6

area=6三角形(3,4,5)面積為6a=3b=4c=5在C++程序中,使用函數前首先需要對函數原型進行聲明,告訴編譯器函數的名稱、類型和形式參數。在C++中,函數原型聲明原則如下:(1)如果函數定義在先,調用在后,調用前可以不必聲明;

如果函數定義在后,調用在先,調用前必須聲明。(2)在程序設計中,為了使程序設計的邏輯結構清晰,一般

將主要的函數放在程序的起始位置聲明,這樣也起到了

列函數目錄的作用。函數原型聲明

聲明函數原型的形式如下:

例如:

intmax(intx,inty)

;intmax(int,int)

;返回類型

函數名(數據類型1參數1,數據類型2參數2,...);

加上參數名會使函數的功能和參數更清晰。函數原型聲明31#include<iostream.h>intfactorial(intn); //函數原型語句voidmain(){ cout<<”5!+4!=”<<factorial(5)+factorial(4)<<endl;}intfactorial(intn){ intz,i; z=1; for(i=1;i<=n;i++) z=z*i; returnz;}例引入原型的概念后,前例可以改寫為以下的形式:32例求從鍵盤上輸入的兩數中大數的值#include<iostream.h>voidmax(intx,inty);voidmain(){ inta,b; cout<<"Pleaseinputtwointegers:"; cin>>a>>b; max(a,b);}voidmax(intx,inty){ intw; w=x>y?x:y; cout<<"Thebigoneoftwoinputnumberis:"<<w<<endl;}運行結果:Pleaseinputtwointegers:54

-89Thebigoneoftwoinputnumberis:5433(1)形式參數:在被調用函數名后面的()內的變量稱為形式參數(簡稱“形參”)。(2)實際參數:在調用函數名后面的()內中的表達式或變量稱為實際參數(簡稱實參)。

形參和實參34例求從鍵盤上輸入的兩數中的最大值#include<iostream.h>voidmax(intx,inty);voidmain(){ inta,b; cout<<"Pleaseinputtwointegers:"; cin>>a>>b; max(a,b);}voidmax(intx,inty){ intw; w=x>y?x:y; cout<<"Thebigoneoftwoinputnumberis:"<<w<<endl;}運行結果:Pleaseinputtwointegers:54

-89Thebigoneoftwoinputnumberis:54程序中x,y為形參,a,b為實參。35例說明實參和形參對應關系的示例。#include<iostream.h>#include<math.h>floatpower(floatx,intn){//求x的n次冪 floatpow=1; while(n--)pow*=x; returnpow;}voidmain(){intn=3; floatx=4.6; charc='a'; cout<<"power("<<x<<','<<n<<")="<<power(x,n)<<endl; cout<<"power("<<c<<','<<n<<")="<<power(c,n)<<endl; cout<<"power("<<n<<','<<x<<")="<<power(n,x)<<endl;}調用power(4.6,3)函數power(4.6,3)return97.336

主程序后續語句n=3x=4.6c=‘a’36(1)對于被調用函數中的形參變量,在程序未調用該函數前,并不占內存的存儲空間,只有在被調用函數執行時,形參變量才被分配臨時存儲空間。函數調用完畢,形參變量的存儲空間將被內存收回。 (2)實參可以為常量、變量或表達式、數組元素、數組名、指針、結構體變量、枚舉變量、對象、函數名等。形參和實參的說明37(3)形參和實參的結合:函數參數傳遞過程就是形參和實參相結合的過程,形參和實參的結合遵守以下規則:①個數一致:形參有多少個數據項,在調用時實參就必須有多少個數據項。②順序一致:若要把實參v的值傳遞給形參w,在調用時v在實參中的順序必須等于w在形參中的順序。③在(2)的w、v數據類型也要保持一致。形參和實參的說明38在程序中以任何方式對函數的使用都稱為函數調用。函數可以以表達式語句的形式調用,可以被其它函數嵌套調用,也可以作為另一個函數的參數被調用。

函數調用的一般形式為:

函數名(實參1,實參2,…,實參n)。各實際參數表中的實際參數應與形參表中的形參一一對應,即個數相等且對應參數的數據類型相同。函數調用是一個表達式,函數名連同括號是函數調用運算符。表達式的值就是被調函數的返回值,它的類型就是函數定義中指定的函數返回值的類型,即函數的類型。函數調用的一般概念

函數的調用39在一個函數中調用另一個函數,需要具備的條件:首先被調用的函數必須是已經存在的函數。如果調用庫函數,一般還應在文件的開頭用#include命令將調用有關庫函數時所需用到的信息包含到本文件中。如果調用用戶自己定義的函數,則必須使用函數原型對被調函數進行說明。函數原型的形式: 函數值的類型標識符被調用函數名(形參及其類型表);函數原型通常放在程序的頂部,也可以存放到一個頭文件中,然后利用#include語句包含到源文件中。函數函數的調用函數調用過程實際上執行了一個從參數傳遞----執行函數體----返回的過程。其中的函數參數傳遞過程的實質是將實參值通過棧空間一一傳送給實參的過程,這種把實參表達式的值傳送給對應的形參變量傳遞方式稱為“按值傳遞”。

函數的參數傳遞

在C++中,實參和形參間數據傳送的方式有三種:值傳遞、指針傳遞和引用傳遞。先介紹值傳送方式。

值傳送方式:(1)調用函數時,先為形參分配存儲單元,后將實參值傳遞給形參;(2)函數執行過程中均為形參參與運算;

(3)函數調用后,形參所對應的存儲單元被釋放,實參保持原來的值不變。函數的參數傳遞方式426.2.2.函數的傳值調用例交換兩個整數變量的值。#include<iostream.h>voidexch(intx,inty){ intz; z=x; x=y; y=z;}voidmain(){ inta=3,b=5; exch(a,b); cout<<"a="<<a<<",b="<<b<<endl;}//運行結果:a=3,b=5變量a,b的值沒有改變。指針傳遞方式:指針傳遞的是變量的地址或數組的首地址。

在調用函數時,系統將函數實參的地址或實參數組的首地址傳遞給被調用函數的形參或形參數組,使形參和實參指向相同的內存空間。在執行函數過程中,形參值的變化會使實參值同時發生變化,所以指針傳遞是一種“雙向傳遞”。函數的參數傳遞方式44例交換兩個整數變量的值。#include<iostream.h>voidexch(int*x,int*y){ intz; z=*x; *x=*y; *y=z;}voidmain(){ inta=3,b=5,*p1=&a,*p2=&b; exch(p1,p2); cout<<"a="<<a<<",b="<<b<<endl;}//運行結果:a=5,b=3變量a,b的值已經交換。45引用傳遞方式

引用的概念和用法

引用是通過變量存儲地址訪問變量的一種語法機制。函數的參數傳遞方式46C++語言通過取地址運算符“&”引入了一種新的數據類型—“引用類型”。引用類型定義格式如下:

類型&變量,或:類型&變量。

一個引用類型的變量,簡稱為一個引用;格式中“類型”稱為引用的基類型。如int&是對int類型的引用類型,float&是對float類型的引用類型。

引用定義與指針定義格式是十分相似的。本質上,指針是地址變量,而引用一旦定義后其地址是固定的,變化的只是該地址中的內容。函數的參數傳遞方式47

獨立引用是對變量的引用。在定義引用之前必須先定義被引用的變量。

intk; int&k_adr=k;(或int&k_adr=k;)

以上兩行定義了一個int型變量k和它的引用k_adr。相當于為k取了一個別名。 對k的操作和對k_adr的操作對變量的影響是完全相同的。指向變量的指針也可以看作變量的別名。指針變量的值可改變,引用只能與一個變量關聯。48例對變量及其引用的操作#include<iostream.h>voidmain(){ intk=32; int&k_adr=k; cout<<"k="<<k<<"k_adr="<<k_adr<<endl; k++; cout<<"k="<<k<<"k_adr="<<k_adr<<endl; k_adr=-5; cout<<"k="<<k<<"k_adr="<<k_adr<<endl; inti=100; k_adr+=i; cout<<"k="<<k<<"k_adr="<<k_adr<<endl;}運行結果:k=32k_adr=32k=33k_adr=33k=-5k_adr=-5k=95k_adr=9549例交換兩個整數變量的值。#include<iostream.h>voidexch(int&x,int&y){ intz; z=x; x=y; y=z;}voidmain(){ inta=3,b=5;exch(a,b);cout<<"a="<<a<<",b="<<b<<endl;}//運行結果:a=5,b=3變量a,b的值已經交換。50數組參數一維數組作為函數參數時,可以不限定數組元素的個數。二維以上的數組作為形參其第一維可不限定,其余各維須加以限定。在調用具有數組參數的函數時,須以單獨的數組名作為實在參數函數調用,形參數組是對應實參數組的代表,而不是它的副本對形參數組的任何改變實際上就是對實參數組的改變。51例:設計函數sum,它計算并返回參數數組中所有元素的合計值。#include<iostream.h>intsum(intarray[],intsize){ints=0;for(inti=0;i<size;i++)s+=array[i];returns;}voidmain(){intv1[]={43,56,23,65,23};cout<<sum(v1,5)<<endl;//實參為數組名}52設計函數sumAll,計算5列二維數組data第一行元素的合計,并把結果存入一維數組result的對應元素中。#include<iostream.h>voidsumAll(intdata[][5],intresult[],introws){for(inti=0;i<rows;i++){result[i]=0;for(intj=0;j<5;j++)result[i]+=data[i][j];}}voidmain(){intv[][5]={{1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7}};ints[3];sumAll(v,s,5);for(i=0;i<3;i++)cout<<s[i];}二維數組v作為函數第一個參數,一維數組s作為第二個參數,參與函數運算,運算結果是v數組每行的和放在一維數組s中,實參直接參與函數運算,且運算結果帶回主函數中53例:查矩陣中最大元素位置(兩個返回值按引用傳遞參數。)constintmax_row=3;constintmax_col=4;voidlocate(constintmatrix[max_row][max_col],int&row,int&col){introw_ptr,col_ptr;row=0;col=0;for=(row_ptr=0;row_ptr<=max_row-1;row_ptr=row_ptr+1){for(col_ptr=0;col_ptr<=max_col-1;col_ptr=col_ptr+1{if(maxtrix[row_ptr][col_ptr]>matrix[row][col]){row=row_ptr;col=col_ptr;}//if}//for}//for}voidmain(){intmatrix[max_row][max_col];introw_ptr,col_ptr;introw,col;//……輸入矩陣數據locate(matrix,row,col);//……輸出查找結果}54課堂練習1編寫一個求x的n次方的函數#include<iostream>usingnamespacestd;doublepower(doublex,intn);voidmain(void){ cout<<"5tothepower2is"

<<power(5,2)<<endl;}doublepower(doublex,intn){ doubleval=1.0; while(n--) val=val*x; return(val);}55課堂練習2數制轉換題目:輸入一個8位二進制數,將其轉換為十進制數輸出。例如:11012=1(23)+1(22)+0(21)+1(20)

=1310

所以,如果輸入1101,則應輸出1356#include<iostream>usingnamespacestd;doublepower(doublex,intn);voidmain(void){ inti; intvalue=0; charch; cout<<"Enteran8bitbinarynumber"; for(i=7;i>=0;i--) { cin>>ch; if(ch=='1') value+=int(power(2,i)); } cout<<"Decimalvalueis"<<value<<endl;}doublepower(doublex,intn){ doubleval=1.0; while(n--)val*=x; return(val);}運行結果:Enteran8bitbinarynumber01101001Decimalvalueis1055657課堂練習3編寫程序求π的值其中arctan用如下形式的級數計算:直到級數某項絕對值不大于10-15為止;π和x均為double型。58#include<iostream>usingnamespacestd;voidmain(){doublea,b;doublearctan(doublex);//函數原型聲明a=16.0*arctan(1/5.0);b=4.0*arctan(1/239.0);//注意:因為整數相除結果取整,//如果參數寫1/5,1/239,結果就都是0cout<<"PI="<<a-b<<endl;}5859doublearctan(doublex){inti;doubler,e,f,sqr;sqr=x*x;r=0;e=x;i=1;while(e/i>1e-15){f=e/i;r=(i%4==1)?r+f:r-f;e=e*sqr;i+=2;}returnr;}運行結果:PI=3.141595960課堂練習4尋找并輸出11--999之間的數m,它滿足m、m2和m3均為回文數。回文:各位數字左右對稱的整數。

例如:11滿足上述條件

112=121,113=1331。分析:10取余的方法,從最低位開始,依次取出該數的各位數字。按反序重新構成新的數,比較與原數是否相等,若相等,則原數為回文。61#include<iostream>usingnamespacestd;voidmain(){boolsymm(longn);longm;for(m=11;m<1000;m++)if(symm(m)&&symm(m*m)&&symm(m*m*m))cout<<"m="<<m<<"m*m="<<m*m<<"m*m*m="<<m*m*m<<endl;}6162boolsymm(longn){longi,m;i=n;m=0;while(i){m=m*10+i%10;i=i/10;}return(m==n);}62運行結果:m=11m*m=121m*m*m=1331m=101m*m=10201m*m*m=1030301m=111m*m=12321m*m*m=136763163課堂練習5計算如下公式,并輸出結果:其中r、s的值由鍵盤輸入。SINx的近似值按如下公式計算,計算精度為10-6:64#include<iostream>#include<cmath>usingnamespacestd;voidmain(){doublek,r,s;doubletsin(doublex);cout<<"r=";cin>>r;cout<<"s=";cin>>s;if(r*r<=s*s)k=sqrt(tsin(r)*tsin(r)+tsin(s)*tsin(s));elsek=tsin(r*s)/2;cout<<k<<endl;}6465doubletsin(doublex){doublep=0.000001,g=0,t=x;intn=1;do{g=g+t;n++;t=-t*x*x/(2*n-1)/(2*n-2);}while(fabs(t)>=p);returng;}運行結果:r=5s=81.377816566課堂練習6投骰子的隨機游戲游戲規則是:每個骰子有六面,點數分別為1、2、3、4、5、6。游戲者在程序開始時輸入一個無符號整數,作為產生隨機數的種子。每輪投兩次骰子,第一輪如果和數為7或11則為勝,游戲結束;和數為2、3或12則為負,游戲結束;和數為其它值則將此值作為自己的點數,繼續第二輪、第三輪...直到某輪的和數等于點數則取勝,若在此前出現和數為7則為負。由rolldice函數負責模擬投骰子、計算和數并輸出和數。67#include<iostream>#include<cstdlib>usingnamespacestd;introlldice(void);voidmain(){intgamestatus,sum,mypoint;unsignedseed;cout<<"Pleaseenteranunsignedinteger:";cin>>seed;//輸入隨機數種子srand(seed);//將種子傳遞給rand()sum=rolldice();//第一輪投骰子、計算和數6768switch(sum){case7://如果和數為7或11則為勝,狀態為1case11:gamestatus=1;break;case2://和數為2、3或12則為負,狀態為2case3:case12:gamestatus=2;break;default://其它情況,游戲尚無結果,狀態為0,記下點數,為下一輪做準備gamestatus=0;mypoint=sum;cout<<"pointis"<<mypoint<<endl;break;}6869while(gamestatus==0)//只要狀態仍為0,就繼續進行下一輪{sum=rolldice();if(sum==mypoint)//某輪的和數等于點數則取勝,狀態置為1gamestatus=1;elseif(sum==7)//出現和數為7則為負,狀態置為2gamestatus=2;}//當狀態不為0時上面的循環結束,以下程序段輸出游戲結果if(gamestatus==1)cout<<"playerwins\n";elsecout<<"playerloses\n";}6970introlldice(void){//投骰子、計算和數、輸出和數intdie1,die2,worksum;die1=1+rand()%6;die2=1+rand()%6;worksum=die1+die2;cout<<"playerrolled"<<die1<<'+'<<die2<<'='<<worksum<<endl;returnworksum;}7071運行結果2:Pleaseenteranunsignedinteger:23playerrolled6+3=9pointis9playerrolled5+4=9playerwins71嵌套調用在一個函數中調用其它函數叫函數的嵌套。C++中函數的定義是平行的,除了main()以外,都可以互相調用。函數不可以嵌套定義,但可以嵌套調用。比如函數1調用了函數2,函數2再調用函數3,這便形成了函數的嵌套調用。例函數的嵌套調用,求三個數中最大數和最小數的差值#include<iostream>usingnamespacestd;intmax(intx,inty,intz){intt;t=x>y?x:y;return(t>z?t:z);}intmin(intx,inty,intz){intt;t=x<y?x:y;return(t<z?t:z);}intdif(intx,inty,intz){returnmax(x,y,z)-min(x,y,z);}voidmain(){inta,b,c;cin>>a>>b>>c;cout<<"Max-Min="<<dif(a,b,c)<<endl;}函數定義嵌套調用在調用一個函數的過程中又直接或間接地調用該函數本身的這一現象,叫做函數的遞歸調用。

1(n=0)n!=n(n-1)!(n>0)

遞歸可以分為直接遞歸調用和間接遞歸調用。

直接遞歸調用:是在調用函數的過程中又調用該函數本身;

間接遞歸調用:是在調用f1()函數的過程中調用f2()函數,而f2()中又需要調用f1()。遞歸調用遞歸函數設計的一般形式是:函數類型遞歸函數名f(參數x){if(滿足結束條件)結果=初值;else結果=含f(x-1)的表達式;返回結果;}遞歸方法是從結果出發,歸納出后一結果與前一結果直到初值為止存在的關系,要求通過分析得到:初值+遞歸函數,然后設計一個函數(遞歸函數),這個函數不斷使用下一級值調用自身,直到結果已知處。

遞歸調用#include<iostream>usingnamespacestd;intfac(intn){intt;if(n==1)t=1;elset=n*fac(n-1);return(t);}voidmain(){constintmax_n=12;//int類型數能表示的n!的最大的nintn;cout<<"Inputaintegernumber:";cin>>n;if(n>=1&&n<=max_n)cout<<"Factorialof"<<n<<"is:"<<fac(n)<<endl;elsecout<<"Invalidn."<<endl;}遞歸函數定義例使用函數遞歸調用,求n!遞歸函數調用遞歸程序分兩個階段執行:①

調用:欲求fac(n)→先求fac(n-1)→fac(n-2)→…→fac(1)若fac(1)已知,回推結束。②回代:知道fac(1)→可求出fac(2)→fac(3)→…→(n)

函數參數傳遞過程:遞歸調用#include<iostream.h>intsum(intn){ //遞歸函數sumif(n==1)//n等于1時,遞歸出口return1;elsereturnn+sum(n-1);}

voidmain(){intn;cout<<"Inputapositiveinteger:";cin>>n; ints=sum(n);//求出從1累加到n的和放s中cout<<"s=1+...+"<<n<<"="<<s<<endl; }遞歸函數定義例求出1到n之累加和的遞歸函數sum遞歸函數調用例漢諾塔(TowerofHanoi)問題。有三根柱子A、B、C。A柱上有從小到大排列的n個盤,要求把這些盤全部搬到C柱上,可以利用空的B柱;但是每次只能搬動一個盤,且在搬動時每個柱子上必須保持盤從小到大的排列次序。如,當盤數n=3時搬動步驟為:(1,A->C),(2,A->B),(2,C->B),(3,A->C),(1,B->A),(2,B->C),(1,A->C)。

遞歸調用分析:將n個盤子從A柱移到C柱可分解為以下3步:遞歸調用#include<iostream>usingnamespacestd;voidmove(intn,charsource,chartarget){cout<<"("<<n<<","<<source<<"--->"<<target<<")"<<endl;}voidhanoi(intn,charA,charB,charC){if(n==1)move(1,A,C);else{

hanoi(n-1,A,C,B);move(n,A,C);

hanoi(n-1,B,A,C);}}遞歸函數定義遞歸調用voidmain(){intnum;cout<<"Inputthenumberofdiskes";cin>>num;hanoi(num,'A','B','C');}遞歸函數調用運行結果:Inputthenumberofdiskes3↙(1,A--->C)(2,A--->B)(2,C--->B)(3,A--->C)(1,B--->A)(2,B--->C)(1,A--->C)遞歸調用內聯函數的定義形式如下:

inline函數類型函數名(形式參數表){函數體;}內聯函數:是通過在編譯時將函數體代碼插入到函數調用處,將調用函數的方式改為順序執行方式來節省程序執行的時間開銷,這一過程叫做內聯函數的擴展。因此,內聯函數實際上是一種用空間換時間的方案。在內聯函數擴展時也進行了實參與形參結合的過程:先將實參名(而不是實參值),將函數體中的形參處處替換,然后搬到調用處。但從用戶的角度看,調用內聯函數和一般函數沒有任何區別。內聯函數#include<iostream>usingnamespacestd;inlinedoubleCirArea(doubleradius){return3.14*radius*radius;}voidmain(){doubler1(1.0),r2(2);cout<<CirArea(r1)<<endl;cout<<CirArea(r1+r2+4)<<endl;}內聯函數定義內聯函數調用例內聯函數的使用注意:如果僅在聲明函數原型時加上關鍵字inline,并不能達到內聯效果。內聯函數的定義必須出現在對該函數的調用之前,因為編譯器在

對函數調用語句進行替換時,必須事先知道替換該語句的代碼是

什么。這也是僅在聲明函數原型時加上關鍵字inline,并不能達到

內聯效果的原因。

由于計算機的資源總是有限的,使用內聯函數雖然節省了程序運行的時間開銷,但卻增大了代碼占用內存的空間開銷。因此在具體編程時應仔細地權衡時間開銷與空間開銷之間的矛盾,以確定是否采用內聯函數。與處理register變量相似,是否對一個內聯函數進行擴展完全由編譯器自行決定。因此,說明一個內聯函數只是請求而不是命令編譯器對它進行擴展。事實上,如果將一個較復雜的函數定義為內聯函數,大多數編譯器會自動地將其作為普通函數處理。內聯函數C++語言允許在函數說明或函數定義中為形參預賦一個默認的值,這樣的函數就叫做帶有默認形參值的函數。在調用帶有默認參數值的函數時,若為相應形參指定了實參,則形參將使用實參的值;否則,形參相使用其默認值。這就大大地方便了函數的使用。帶缺省形參值的函數

intsub(intx=8,inty=3){returnx-y;}voidmain(void){sub(20,15);//傳遞給形參x,y的值分別為20和15sub(10);//傳遞給形參x,y的值分別為10和3sub();//傳遞給形參x,y的值分別為8和3}帶缺省形參值的函數intf(inta,floatb=5.0,charc='.',intd=10);//正確intf(inta=1,floatb=5.0,charc='.',intd);//錯誤,d未給值intf(inta=1,floatb,charc='.',intd=10);//錯誤,b未給值

(1)若函數具有多個形參,則缺省形參值必須自右向左連續地定義,并且在一個缺省形參值的右邊不能有未指定缺省值的參數。這是由于C++語言在函數調用時參數是自右至左入棧這一約定所決定的。假如有如下聲明:intf(inta,floatb=5.0,charc='.',intd=10);采用如下調用形式是錯誤的:f(8,,,4);//語法錯誤(2)在調用一個函數時,如果省去了某個實參,則直到最右端的實參都要省去(當然,與它們對應的形參都要有缺省值)。帶缺省形參值的函數intsub(intx=8,inty=3);//缺省形參值在函數原型中給出voidmain(void){sub(20,15);//20-15sub(10);//10-3sub();//8-3}intsub(intx,inty)//缺省形參值沒有在函數定義時給出{returnx-y;}(3)缺省形參值的說明必須出現在函數調用之前。這就是說,如果存在函數原型,則形參的缺省值應在函數原型中指定;否則在函數定義中指定。另外,若函數原型中已給出了形參的缺省值,則在函數定義中不得重復指定,即使所指定的缺省值完全相同也不行。帶缺省形參值的函數參數的缺省值是函數調用。intf(inta,floatb=5.0,charc='.',intd=sub(20,15));(4)對形參缺省值的指定可以是初始化表達式,甚至可以包含函數調用。

intf(int,float=5.0,char=’.’,int=sub(20,15));

(5)在函數原型給出了形參的缺省值時,形參名可以省略。帶缺省形參值的函數intmax(int,int);intmax(int,int,int);floatmax(float,float);doublemax(double,double);函數重載:就是兩個以上的函數,取相同的函數名,但是形參的個數和類型不同,編譯器根據實參和形參的類型及個數的最佳匹配,自動決定調用哪一個函數。函數重載#include<iostream>usingnamespacestd;intadd(intx,inty)

{cout<<"(int,int)\t";returnx+y;}doubleadd(doublex,doubley){cout<<"(double,double)\t";returnx+y;}intadd(intx,doubley){cout<<"(int,double)\t";returnint(x+y);}函數重載函數重載函數重載doubleadd(doublex,inty)

{cout<<"(double,int)\t";returnx+y;}voidmain(){cout<<add(9,8)<<endl;cout<<add(9.0,8.0)<<endl;cout<<add(9,8.0)<<endl;cout<<add(9.0,8)<<endl;}函數重載運行結果:(int,int)17(double,double)17(int,double)17(double,int)17重載函數的調用//C++無法區分這兩個函數。因為在沒有確定函數調用是對哪一個重載的函數之前,

//返回類型是不知道的。intadd(inti1,inti2);floatadd(intf1,intf2);注意:(1)各個重載函數的返回類型可以相同,也可以不同。但如果函數名相同、形參表也相同,僅僅是返回類型不同,則是非法的。在編譯時會認為是語法錯誤。//將char型轉換成int型,然后與add(int,int)綁定。add('A','A'+'0');//函數實參向(double,double)轉換,然后與add(double,double)綁定。add(float(8),float(9));//實參類型為(longdouble,int),向低類型轉化。add(longdouble(8),9);

(2)確定對重載函數的哪個函數進行調用的過程稱為綁定(binding),綁定的優先次序為精確匹配、對實參的類型向高類型轉換后的匹配、實參類型向低類型及相容類型轉換后的匹配。函數重載95C++中有四個關鍵字用于描述變量的存儲類別,它們是auto(自動)、static(靜態)、register(寄存器)和extern(外部)。變量的存儲類別用來描述變量在以下三個方面的屬性:(1)變量的存在方式和作用范圍;(2)變量的存在時間;(3)變量的作用域。變量的存儲類型96

使用顯式存儲類別時,變量說明的一般格式變為:

<存儲類別><變量類型><變量名1>,...,<變量名n>;

其中的“<存儲類別>”可以是auto、register、extern、static四個關鍵字之一。

C++程序的數據主要存放在如下兩個數據區之中,一個稱為靜態數據區(也稱全局數據區--“一旦分配,一直擁有”),另一個稱為動態數據區(也稱堆棧數據區--“入時分配并擁有,出時歸還兩手空”)。變量的存儲類型97程序執行時所需要的內存空間一個程序執行時所需的內存空間可分為:程序代碼區,數據區。根據數據存儲的方式,數據區又劃分為靜態存儲區,動態存儲區。因此變量有靜態存儲變量,動態存儲變量之分代碼空間靜態數據空間動態數據空間98

(1)自動(auto)變量與寄存器(register)變量這兩類變量都是局部變量。均被分配在動態數據區之中。它們的“生命期”僅在其作用域之內。即是說,這兩類變量的作用域與“生命期”具有一致性。由于C++編譯器默認所有在函數或塊內說明的局部變量均為自動(auto)變量,所以實用程序中根本不需要使用關鍵字auto。說明寄存器(register)變量時,必須使用存儲類別register。如果沒有足夠多的通用寄存器,則編譯器將它們按自動(auto)變量來處理。變量的存儲類型99

(2)外部(extern)變量外部(extern)變量具有程序級作用域。它們被分配在靜態數據區之中。即是說,它們是作用域最大且“生命期”最長的一種變量,其可見性與存在性是相互一致的。

(3)靜態(static)變量又可分為局部靜態變量和全局靜態變量。局部靜態變量是指在函數或塊的內部說明的靜態變量,它的作用域是局部的;而全局靜態變量指的是在所有函數的外部說明的具有單文件級全局性的靜態變量。兩種靜態變量都被分配在靜態數據區之中,即是說,它們的“生命期”都與整個程序的執行期相同。

變量的存儲類型100變量按其在程序中作用的范圍,分為全局變量和局部變量。

全局變量是指在程序代碼開始執行前分配的變量,它在程序的整個運行過程中都起作用,用靜態數據區存儲。

局部變量是指在程序內部定義的變量,它只在程序內部起作用,用動態數據區存儲。C++規定程序中函數的參數也是局部變量。局部變量的缺省存儲類型是auto。全局變量和局部變量101全局變量在靜態存儲區中分配,到程序執行完畢時才釋放,在程序執行過程中,它們占用固定的存儲單元而不是動態分配和釋放的單元,它的存在時間為整個程序運行時間;動態存儲區中存放的數據在函數調用開始時分配動

溫馨提示

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

評論

0/150

提交評論