前言:
前面我們說的都是無參數無返回值的函數,實際程序中,我們經常使用到帶參數有返回值的函數。
void a(int); /*注意函數聲明的形式*/
main()
{
int num;
scanf(%d,&num);
a(num); /*注意調用形式*/
}
void a(int num_back) /*注意定義形式*/
{
printf(%d\n,num_back);
}
在主函數中,先定義一個變量,然後輸入一個值,在a()這個函數中輸出。當程序運行a(num);這一步時,把num的值賦值給num_back,在運行程序過程中,把實際參數的值傳給形式參數,這就是函數參數的傳遞。
void a(int,float);
main()
{
int num1;
float num2;
scanf(%d,&num1);
scanf(%f,&num2);
a(num1,num2);
}
void a(int num1_back,float num2_back)
{
printf(%d,%f\n,num1_back,num2_back);
}
上面的例子中,函數有兩個參數,一個是整型,一個是浮點型,那麼在聲明、調用、定義的時候,不僅個數要一樣,類型也要對應。如果不對應,有可能使的編譯錯誤,即使沒錯誤,也有可能讓數據傳遞過程中出現錯誤。
void a(int);
main()
{
int num;
scanf(%d,&num);
a(num);
}
void a(int num)
{
printf(%d\n,num);
}
看上面的例子,形式參數和實際參數的標識符都是num,程序把實際參數num的值傳遞給形式參數num。有些人可能就不明白了,既然兩個都是num,為什麼還要傳遞呢?干脆這樣不就行了嗎:
void a();
main()
{
int num;
scanf(%d,&num);
a();
}
void a()
{
printf(%d\n,num);
}
其實不然,這就要涉及到標識符作用域的問題。作用域的意思就是說,哪些變量在哪些范圍內有效。一個標識符在一個語句塊中聲明,那麼這個標識符僅在當前和更低的語句塊中可見,在函數外部的其實地方不可見,其他地方同名的標識符不受影響,後面我們會系統講解作用域的問題。在這兒你就要知道兩個同名的變量在不同的函數中是互不干擾的。
void a(int []);
main()
{
int array[5],i;
for(i=0;i<5;i++) scanf(%d,&array[i]);
a(array);
}
void a(int array[])
{
int i;
for(i=0;i<5;i++) printf(%d\t,array[i]);
printf(\n);
}
這就是數組之間的值傳遞。注意他們的聲明和定義形式,和變量參數傳遞有什麼區別?有了後面的[]就表明傳遞的是一個數組。其中在定義的時候,也可以寫成void a(int array[5]);想想,如果我們寫成了int array[4]會有什麼情況發生?
int a(int); /*聲明函數*/
main()
{
int num,area;
scanf(%d,&num);
area=a(num); /*調用時的形式*/
printf(%d,area);
}
int a(int num)
{
int area_back;
area_back=num*num;
return area_back; /*返回一個值*/
}
和前面的程序有幾點不同:
int a(int);
main()
{
int num;
scanf(%d,&num);
printf(%d,a(num)); /*函數調用放在這兒*/
}
int a(int num)
{
int area_back;
area_back=num*num;
return area_back;
}
這樣函數返回的值就可以直接放到輸出緩沖區直接輸出了。
int a(int);
main()
{
int num;
scanf(%d,&num);
printf(%d,a(num));
}
int a(int num)
{
return num*num; /*直接在這兒返回*/
}
對於函數而言,一個函數只能返回一個值,如果想返回一組數值,就要使用數組或者結構或者指針。其實對於這些,還是返回一個值,只是這個值是一個地址而已。但是對於數組的返回有和變量不同,因為數組和地址是聯系在一起的。看一個例子:
void a(int []);
main()
{
int array[5]={1,2,3,4,5},i;
a(array);
for(i=0;i<5;i++) printf(%d,array[i]);
}
void a(int array[])
{
int i;
for(i=0;i<5;i++) array[i]++;
}
看看這個程序,好象函數沒有返回值,但是函數的功能的確實現了,在主函數當中輸出的值的確都各加了1上來。這就是因為數組和變量不同的緣故,在後面講指針的時候再詳細說明。
#include math.h
int judge(int);
main()
{
int num,result;
scanf(%d,&num);
result=judge(num);
if(result==1) printf(yes\n);
else printf(no\n);
}
judge(int num)
{
int i,flag=1;
for(i=2;i<=sqrt(num);i++)
if(num%i==0)
{
flag=0;
break;
}
return flag;
}
可以看出,函數的功能就是為了讓程序看起來有條理,一個函數實現一個特定的功能。如果我們還和以前那樣,把所有代碼都放在main()函數,好象程序就顯的臃腫了。而且函數有一個顯著的好處就是很方便的使用。這裡面的judge()函數判斷一個數是不是素數,如果我們以後還有判斷某個數是不是素數,就可以直接使用這個函數了。我們這樣,把下面的代碼:
judge(int num)
{
int i,flag=1;
for(i=2;i<=sqrt(num);i++)
if(num%i==0)
{
flag=0;
break;
}
return flag;
}
保存為judge.h文件,放到include目錄裡面。
#include math.h /*必須要有它*/
#include judge.h
main()
{
int num,result;
scanf(%d,&num);
result=judge(num);
if(result==1) printf(yes\n);
else printf(no\n);
}
看上面的例子,我們在程序中直接使用了函數judge(),這就是我們自己編寫的第一個所謂的庫函數。但是程序的第一行要包含math.h文件,這是因為在judge.h裡面使用了sqrt()函數,所以為了方便,我們可以把math.h放到judge.h裡面,也就是在judge.h文件的第一行加上include math.h,這樣,我們的主程序中就不需要包含它了,但是這樣做也有副作用,具體有什麼副作用,我們以後接觸到時再介紹。