亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

C語言初學者入門講座 第十講 函數(2)

2019-11-17 05:42:04
字體:
來源:轉載
供稿:網友

  一、函數的參數

  前面已經介紹過,函數的參數分為形參和實參兩種。 在本小節中,進一步介紹形參、實參的特點和兩者的關系。 形參出現在函數定義中,在整個函數體內都可以使用, 離開該函數則不能使用。實參出現在主調函數中,進入被調函數后,實參變量也不能使用。 形參和實參的功能是作數據傳送。發生函數調用時, 主調函數把實參的值傳送給被調函數的形參從而實現主調函數向被調函數的數據傳送。

  函數的形參和實參具有以下特點:

  1.形參變量只有在被調用時才分配內存單元,在調用結束時, 即刻釋放所分配的內存單元。因此,形參只有在函數內部有效。 函數調用結束返回主調函數后則不能再使用該形參變量。

  2.實參可以是常量、變量、表達式、函數等, 無論實參是何種類型的量,在進行函數調用時,它們都必須具有確定的值, 以便把這些值傳送給形參。 因此應預先用賦值,輸入等辦法使實參獲得確定值。

  3.實參和形參在數量上,類型上,順序上應嚴格一致, 否則會發生“類型不匹配”的錯誤。

  4.函數調用中發生的數據傳送是單向的。 即只能把實參的值傳送給形參,而不能把形參的值反向地傳送給實參。 因此在函數調用過程中,形參的值發生改變,而實參中的值不會變化。例5.3可以說明這個問題。

void main()
{
int n;
PRintf("input number/n");
scanf("%d",&n);
s(n);
printf("n=%d/n",n);
}
int s(int n)
{
int i;
for(i=n-1;i>=1;i--)
n=n+i;
printf("n=%d/n",n);
}

  本程序中定義了一個函數s,該函數的功能是求∑ni=1i 的值。在主函數中輸入n值,并作為實參,在調用時傳送給s 函數的形參量n( 注重,本例的形參變量和實參變量的標識符都為n, 但這是兩個不同的量,各自的作用域不同)。 在主函數中用printf 語句輸出一次n值,這個n值是實參n的值。在函數s中也用printf 語句輸出了一次n值,這個n值是形參最后取得的n值0。從運行情況看,輸入n值為100。即實參n的值為100。把此值傳給函數s時,形參 n 的初值也為100,在執行函數過程中,形參n的值變為5050。 返回主函數之后,輸出實參n的值仍為100??梢妼崊⒌闹挡浑S形參的變化而變化。

  二、函數的值

  函數的值是指函數被調用之后, 執行函數體中的程序段所取得的并返回給主調函數的值。如調用正弦函數取得正弦值,調用例5.1的max函數取得的最大數等。對函數的值(或稱函數返回值)有以下一些說明:

  1. 函數的值只能通過return語句返回主調函數。return 語句的一般形式為:

  return 表達式;

  或者為:

  return (表達式);

  該語句的功能是計算表達式的值,并返回給主調函數。 在函數中答應有多個return語句,但每次調用只能有一個return 語句被執行, 因此只能返回一個函數值。

  2. 函數值的類型和函數定義中函數的類型應保持一致。 假如兩者不一致,則以函數類型為準,自動進行類型轉換。

  3. 如函數值為整型,在函數定義時可以省去類型說明。

  4. 不返回函數值的函數,可以明確定義為“空類型”, 類型說明符為“void”。如例5.3中函數s并不向主函數返函數值,因此可定義為:

void s(int n)
{ ……
}

  一旦函數被定義為空類型后, 就不能在主調函數中使用被調函數的函數值了。例如,在定義s為空類型后,在主函數中寫下述語句 sum=s(n); 就是錯誤的。為了使程序有良好的可讀性并減少出錯, 凡不要求返回值的函數都應定義為空類型。函數說明在主調函數中調用某函數之前應對該被調函數進行說明, 這與使用變量之前要先進行變量說明是一樣的。 在主調函數中對被調函數作說明的目的是使編譯系統知道被調函數返回值的類型, 以便在主調函數中按此種類型對返回值作相應的處理。 對被調函數的說明也有兩種格式,一種為傳統格式,其一般格式為: 類型說明符 被調函數名(); 這種格式只給出函數返回值的類型,被調函數名及一個空括號。

  這種格式由于在括號中沒有任何參數信息, 因此不便于編譯系統進行錯誤檢查,易于發生錯誤。另一種為現代格式,其一般形式為:

  類型說明符 被調函數名(類型 形參,類型 形參…);

  或為:

  類型說明符 被調函數名(類型,類型…);

  現代格式的括號內給出了形參的類型和形參名, 或只給出形參類型。這便于編譯系統進行檢錯,以防止可能出現的錯誤。例5.1 main函數中對max函數的說明若

  用傳統格式可寫為:

int max();

  用現代格式可寫為:

int max(int a,int b);

  或寫為:

int max(int,int);

  C語言中又規定在以下幾種情況時可以省去主調函數中對被調函數的函數說明。

  1. 假如被調函數的返回值是整型或字符型時, 可以不對被調函數作說明,而直接調用。這時系統將自動對被調函數返回值按整型處理。例5.3的主函數中未對函數s作說明而直接調用即屬此種情形。

  2. 當被調函數的函數定義出現在主調函數之前時, 在主調函數中也可以不對被調函數再作說明而直接調用。例如例5.1中, 函數max的定義放在main 函數之前,因此可在main函數中省去對 max函數的函數說明int max(int a,int b)。

  3. 如在所有函數定義之前, 在函數外預先說明了各個函數的類型,則在以后的各主調函數中,可不再對被調函數作說明。例如:

char str(int a);
float f(float b);
main()
{
……
}
char str(int a)
{
……
}
float f(float b)
{
……
}

  其中第一,二行對str函數和f函數預先作了說明。 因此在以后各函數中無須對str和f函數再作說明就可直接調用。

  4. 對庫函數的調用不需要再作說明, 但必須把該函數的頭文件用include命令包含在源文件前部。數組作為函數參數數組可以作為函數的參數使用,進行數據傳送。 數組用作函數參數有兩種形式,一種是把數組元素(下標變量)作為實參使用; 另一種是把數組名作為函數的形參和實參使用。一、數組元素作函數實參數組元素就是下標變量,它與普通變量并無區別。 因此它作為函數實參使用與普通變量是完全相同的,在發生函數調用時, 把作為實參的數組元素的值傳送給形參,實現單向的值傳送。例5.4說明了這種情況。[例5.4]判別一個整數數組中各元素的值,若大于0 則輸出該值,若小于等于0則輸出0值。編程如下:

void nzp(int v)
{
if(v>0)
printf("%d ",v);
else
printf("%d ",0);
}
main()
{
int a[5],i;
printf("input 5 numbers/n");
for(i=0;i<5;i++)
{
scanf("%d",&a[i]);
nzp(a[i]);
}
}void nzp(int v)
{ ……
}
main()
{
int a[5],i;
printf("input 5 numbers/n");
for(i=0;i<5;i++)
{ scanf("%d",&a[i]);
nzp(a[i]);
}
}  

  本程序中首先定義一個無返回值函數nzp,并說明其形參v 為整型變量。在函數體中根據v值輸出相應的結果。在main函數中用一個for 語句輸入數組各元素, 每輸入一個就以該元素作實參調用一次nzp函數,即把a[i]的值傳送給形參v,供nzp函數使用。

  二、數組名作為函數參數

  用數組名作函數參數與用數組元素作實參有幾點不同:

  1. 用數組元素作實參時,只要數組類型和函數的形參變量的類型一致,那么作為下標變量的數組元素的類型也和函數形參變量的類型是一致的。因此, 并不要求函數的形參也是下標變量。 換句話說,對數組元素的處理是按普通變量對待的。用數組名作函數參數時, 則要求形參和相對應的實參都必須是類型相同的數組,都必須有明確的數組說明。當形參和實參二者不一致時,即會發生錯誤。

  2. 在普通變量或下標變量作函數參數時,形參變量和實參變量是由編譯系統分配的兩個不同的內存單元。在函數調用時發生的值傳送是把實參變量的值賦予形參變量。在用數組名作函數參數時,不是進行值的傳送,即不是把實參數組的每一個元素的值都賦予形參數組的各個元素。因為實際上形參數組并不存在,編譯系統不為形參數組分配內存。那么,數據的傳送是如何實現的呢? 在第四章中我們曾介紹過,數組名就是數組的首地址。因此在數組名作函數參數時所進行的傳送只是地址的傳送, 也就是說把實參數組的首地址賦予形參數組名。形參數組名取得該首地址之后,也就等于有了實在的數組。實際上是形參數組和實參數組為同一數組,共同擁有一段內存空間。圖5.1說明了這種情形。圖中設a為實參數組,類型為整型。a占有以2000 為首地址的一塊內存區。b為形參數組名。當發生函數調用時,進行地址傳送, 把實參數 組a的首地址傳送給形參數組名b,于是b也取得該地址2000。 于是a,b兩數組共同占有以2000 為首地址的一段連續內存單元。從圖中還可以看出a和b下標相同的元素實際上也占相同的兩個內存單元(整型數組每個元素占二字節)。例如a[0]和b[0]都占用2000和2001單元,當然a[0]等于b[0]。類推則有a[i]等于b[i]。

  [例5.5]數組a中存放了一個學生5門課程的成績,求平均成績。float aver(float a[5])

{
int i;
float av,s=a[0];
for(i=1;i<5;i++)
s=s+a[i];
av=s/5;
return av;
}
void main()
{
float sco[5],av;
int i;
printf("/ninput 5 scores:/n");
for(i=0;i<5;i++)
scanf("%f",&sco[i]);
av=aver(sco);
printf("average score is %5.2f",av);
}
float aver(float a[5])
{ ……
}
void main()
{
……
for(i=0;i<5;i++)
scanf("%f",&sco[i]);
av=aver(sco);
……
}  

  本程序首先定義了一個實型函數aver,有一個形參為實型數組a,長度為5。在函數aver中,把各元素值相加求出平均值,返回給主函數。主函數main 中首先完成數組sco的輸入,然后以sco作為實參調用aver函數,函數返回值送av,最后輸出av值。 從運行情況可以看出,程序實現了所要求的功能

  3. 前面已經討論過,在變量作函數參數時,所進行的值傳送是單向的。即只能從實參傳向形參,不能從形參傳回實參。形參的初值和實參相同, 而形參的值發生改變后,實參并不變化, 兩者的終值是不同的。例5.3證實了這個結論。 而當用數組名作函數參數時,情況則不同。 由于實際上形參和實參為同一數組, 因此當形參數組發生變化時,實參數組也隨之變化。 當然這種情況不能理解為發生了“雙向”的值傳遞。但從實際情況來看,調用函數之后實參數組的值將由于形參數組值的變化而變化。為了說明這種情況,把例5.4改為例5.6的形式。[例5.6]題目同5.4例。改用數組名作函數參數。

void nzp(int a[5])
{
int i;
printf("/nvalues of array a are:/n");
for(i=0;i<5;i++)
{
if(a[i]<0) a[i]=0;
printf("%d ",a[i]);
}
}
main()
{
int b[5],i;
printf("/ninput 5 numbers:/n");
for(i=0;i<5;i++)
scanf("%d",&b[i]);
printf("initial values of array b are:/n");
for(i=0;i<5;i++)
printf("%d ",b[i]);
nzp(b);
printf("/nlast values of array b are:/n");
for(i=0;i<5;i++)
printf("%d ",b[i]);
}
void nzp(int a[5])
{ ……
}
main()
{
int b[5],i;
……
nzp(b);
……
}

  本程序中函數nzp的形參為整數組a,長度為 5。 主函數中實參數組b也為整型,長度也為5。在主函數中首先輸入數組b的值,然后輸出數組b的初始值。 然后以數組名b為實參調用nzp函數。在nzp中,按要求把負值單元清0,并輸出形參數組a的值。 返回主函數之后,再次輸出數組b的值。從運行結果可以看出,數組b 的初值和終值是不同的,數組b 的終值和數組a是相同的。這說明實參形參為同一數組,它們的值同時得以改變。 用數組名作為函數參數時還應注重以下幾點:

  a. 形參數組和實參數組的類型必須一致,否則將引起錯誤。

  b. 形參數組和實參數組的長度可以不相同,因為在調用時,只傳送首地址而不檢查形參數組的長度。當形參數組的長度與實參數組不一致時,雖不至于出現語法錯誤(編譯能通過),但程序執行結果將與實際不符,這是應予以注重的。如把例5.6修改如下:

void nzp(int a[8])
{
int i;
printf("/nvalues of array aare:/n");
for(i=0;i<8;i++)
{
if(a[i]<0)a[i]=0;
printf("%d",a[i]);
}
}
main()
{
int b[5],i;
printf("/ninput 5 numbers:/n");
for(i=0;i<5;i++)
scanf("%d",&b[i]);
printf("initial values of array b are:/n");
for(i=0;i<5;i++)
printf("%d",b[i]);
nzp(b);
printf("/nlast values of array b are:/n");
for(i=0;i<5;i++)
printf("%d",b[i]);
}

  本程序與例5.6程序比,nzp函數的形參數組長度改為8,函數體中,for語句的循環條件也改為i<8。因此,形參數組 a和實參數組b的長度不一致。編譯能夠通過,但從結果看,數組a的元素a[5],a[6],a[7]顯然是無意義的。c. 在函數形參表中,答應不給出形參數組的長度,或用一個變量來表示數組元素的個數。

  例如:可以寫為:

void nzp(int a[])

  或寫為

void nzp(int a[],int n)

  其中形參數組a沒有給出長度,而由n值動態地表示數組的長度。n的值由主調函數的實參進行傳送。

  由此,例5.6又可改為例5.7的形式。

  [例5.7]

void nzp(int a[],int n)
{
int i;
printf("/nvalues of array a are:/n");
for(i=0;i<n;i++)
{
if(a[i]<0) a[i]=0;
printf("%d ",a[i]);
}
}
main()
{
int b[5],i;
printf("/ninput 5 numbers:/n");
for(i=0;i<5;i++)
scanf("%d",&b[i]);
printf("initial values of array b are:/n");
for(i=0;i<5;i++)
printf("%d ",b[i]);
nzp(b,5);
printf("/nlast values of array b are:/n");
for(i=0;i<5;i++)
printf("%d ",b[i]);
}
void nzp(int a[],int n)
{ ……
}
main()
{
……
nzp(b,5);
……
}


  本程序nzp函數形參數組a沒有給出長度,由n 動態確定該長度。在main函數中,函數調用語句為nzp(b,5),其中實參5將賦予形參n作為形參數組的長度。

  d. 多維數組也可以作為函數的參數。 在函數定義時對形參數組可以指定每一維的長度,也可省去第一維的長度。因此,以下寫法都是合法的。

int MA(int a[3][10])

  或

int MA(int a[][10])

  函數的嵌套調用

  C語言中不答應作嵌套的函數定義。因此各函數之間是平行的,不存在上一級函數和下一級函數的問題。 但是C語言答應在一個函數的定義中出現對另一個函數的調用。 這樣就出現了函數的嵌套調用。即在被調函數中又調用其它函數。 這與其它語言的子程序嵌套的情形是類似的。其關系可表示如圖5.2。

  圖5.2表示了兩層嵌套的情形。其執行過程是:執行main函數中調用a函數的語句時,即轉去執行a函數,在a函數中調用b 函數時,又轉去執行b函數,b函數執行完畢返回a函數的斷點繼續執行,a 函數執行完畢返回main函數的斷點繼續執行。

  [例5.8]計算s=22!+32!

  本題可編寫兩個函數,一個是用來計算平方值的函數f1, 另一個是用來計算階乘值的函數f2。主函數先調f1計算出平方值, 再在f1中以平方值為實參,調用 f2計算其階乘值,然后返回f1,再返回主函數,在循環程序中計算累加和。

long f1(int p)
{
int k;
long r;
long f2(int);
k=p*p;
r=f2(k);
return r;
}
long f2(int q)
{
long c=1;
int i;
for(i=1;i<=q;i++)
c=c*i;
return c;
}
main()
{
int i;
long s=0;
for (i=2;i<=3;i++)
s=s+f1(i);
printf("/ns=%ld/n",s);
}
long f1(int p)
{
……
long f2(int);
r=f2(k);
……
}
long f2(int q)
{
……
}
main()
{ ……
s=s+f1(i);
……
}

  在程序中,函數f1和f2均為長整型,都在主函數之前定義, 故不必再在主函數中對f1和f2加以說明。在主程序中, 執行循環程序依次把i值作為實參調用函數f1求i2值。在f1中又發生對函數f2的調用,這時是把i2的值作為實參去調f2,在f2 中完成求i2! 的計算。f2執行完畢把C值(即i2!)返回給f1,再由f1 返回主函數實現累加。至此,由函數的嵌套調用實現了題目的要求。 由于數值很大, 所以函數和一些變量的類型都說明為長整型,否則會造成計算錯誤。




發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
一本色道久久88综合日韩精品| 亚洲精品国产精品国自产观看浪潮| 精品久久久久久久久久久| 丝袜美腿精品国产二区| 国产精品视频专区| 日韩视频第一页| 精品久久久久久久大神国产| 亚洲桃花岛网站| 久久视频在线免费观看| 欧美国产视频日韩| 欧美xxxx做受欧美.88| 亚洲欧美成人一区二区在线电影| 亚洲精品成人网| 亚洲图片欧洲图片av| 色综合天天狠天天透天天伊人| 欧美xxxx14xxxxx性爽| 91久久精品日日躁夜夜躁国产| 午夜精品视频在线| 97精品久久久中文字幕免费| 日韩欧美在线字幕| 欧美激情第三页| 久久久久免费精品国产| 国产视频丨精品|在线观看| 青草青草久热精品视频在线观看| 亚洲欧洲在线观看| 欧美一区二区大胆人体摄影专业网站| 久久久久久999| 欧美自拍视频在线| 日韩免费在线观看视频| 亚洲精品中文字幕有码专区| 国产精品爽黄69天堂a| 三级精品视频久久久久| 精品亚洲一区二区三区| 爽爽爽爽爽爽爽成人免费观看| 欧美人在线视频| 日韩欧美黄色动漫| 欧美激情成人在线视频| 久久久之久亚州精品露出| 国产精品av在线播放| 欧美黑人巨大精品一区二区| 亚洲开心激情网| 一个人看的www久久| 欧美亚洲成人精品| 亚洲欧美色婷婷| 欧美电影免费观看电视剧大全| 亚洲男人天堂2023| 国产精品久久久久久网站| 亚洲国产精品中文| 插插插亚洲综合网| 色99之美女主播在线视频| 国产亚洲美女精品久久久| 色综合久久中文字幕综合网小说| 久久亚洲国产精品成人av秋霞| 亚洲国产精品电影| 成人在线中文字幕| 欧美中文在线观看国产| 精品国产91久久久久久老师| 欧美猛交ⅹxxx乱大交视频| 亚洲欧洲免费视频| 国产欧美精品va在线观看| 97精品一区二区三区| 欧美性生交xxxxx久久久| 欧美激情在线播放| 久久久精品欧美| 国产一区二区黑人欧美xxxx| 日韩精品视频在线观看免费| 国产一区二区香蕉| 日韩中文在线中文网在线观看| 日韩欧美在线中文字幕| 国产精品视频yy9099| 国产精品久久久久久久久久ktv| 亚洲高清一二三区| 国产精品第100页| 国产精品久久久久久久av电影| 中文字幕在线精品| 精品一区电影国产| 一本一本久久a久久精品综合小说| 日韩欧美一区二区三区| 国产精品福利在线观看网址| 日韩免费av一区二区| 国产精品久久久久久亚洲调教| 久久久久久久久久久亚洲| 欧美成人精品xxx| 精品亚洲一区二区三区四区五区| 国产精品久久久久久超碰| 亚洲aⅴ男人的天堂在线观看| 亚洲国产精品女人久久久| 一区二区亚洲精品国产| 国产中文欧美精品| 国产成人综合久久| 亚洲精品福利在线观看| 丝袜亚洲欧美日韩综合| 伊人伊成久久人综合网站| 国产精品爱啪在线线免费观看| 欧美日韩国产一区二区三区| 久久福利网址导航| 精品一区二区三区四区在线| 在线观看国产精品淫| 精品国产成人av| 欧洲成人性视频| 久久97精品久久久久久久不卡| 亚洲综合在线小说| 伊人久久久久久久久久| 国内精品国产三级国产在线专| 在线播放日韩专区| 国产一区二区三区在线观看视频| 欧美另类交人妖| 韩国精品美女www爽爽爽视频| 亚洲另类图片色| 欧美午夜激情在线| 91久久在线视频| 亚洲女同精品视频| 欧美裸体xxxx极品少妇软件| 亚洲欧美日韩一区二区在线| 久久免费高清视频| 国产视频亚洲视频| 日韩色av导航| 国产亚洲精品久久久久久牛牛| 91av中文字幕| 亚洲电影免费观看高清完整版在线| 国产亚洲精品久久久优势| 日韩在线一区二区三区免费视频| 久久久久亚洲精品成人网小说| 欧美一级片在线播放| 欧美成人三级视频网站| 欧洲亚洲在线视频| 日韩精品免费在线视频观看| 日韩精品欧美国产精品忘忧草| 国产色婷婷国产综合在线理论片a| 伊是香蕉大人久久| 欧美精品久久一区二区| 国产精品久久久久77777| 久久久久久久久久久人体| 亚洲香蕉成人av网站在线观看| 国产69久久精品成人看| 欧美亚洲成人xxx| 裸体女人亚洲精品一区| 亚洲欧美中文另类| 久久精品久久久久| 亚洲欧美日韩成人| 亚洲人在线观看| 久久久久久久久久久久av| 欧美日韩国产限制| 欧美床上激情在线观看| 亚洲自拍偷拍一区| 九九热精品在线| 久久精品成人欧美大片古装| 亚洲成年网站在线观看| 欧美午夜影院在线视频| 日韩经典中文字幕| 91沈先生作品| 亚洲欧洲一区二区三区久久| 最新的欧美黄色| 在线观看国产成人av片| 91美女福利视频高清| 久久久久国产精品www| 日韩少妇与小伙激情| 欧美精品在线极品| 国产精品精品国产| 国产精品欧美激情| 国产剧情日韩欧美| 91黑丝在线观看| 国产精品久久久久久久久影视| 亚洲精品一区中文字幕乱码|