C語言學習欄目目錄
目錄
現在,相信大家已經熟悉了帶參數的函數。要掌握函數,還要學習如何編寫自己的函數程序清單中有一個pound()函數,打印指定數量的#號(該符號也叫作編號符號或井號)。該程序還演示了類型轉換的應用。
/************************************************************************
功能:定義一個帶一個參數的函數
************************************************************************/
#include <stdio.h>
void pound(int n); // ANSI函數原型聲明
int main(void)
{
int times = 5;
char ch = '!'; // ASCII碼是33
float f = 6.0f;
pound(times); // int類型的參數
pound(ch); // 和pound((int)ch);相同
pound(f); // 和pound((int)f);相同
system("pause"); // 暫停控制檯
return 0;
}
void pound(int n) // ANSI風格函數頭
{ // 表明該函數接受一個int類型的參數
while (n-- > 0)
printf("#");
printf("\n");
}
運行該程序後,輸出如下:
#####
#################################
######
請按任意鍵繼續. . .
如果函數不接受任何參數,函數頭的圓括號中應該寫上關鍵字 void。由於該函數接受一個 int 類型的參數,所以圓括號中包含一個int類型變量n的聲明。參數名應遵循C語言的命名規則。
聲明參數就創建了被稱爲形式參數(formal argument或formalparameter,簡稱形參)的變量。該例中,形式參數是 int 類型的變量 n。像pound(10)這樣的函數調用會把 10 賦給 n。在該程序中,調用pound(times)就是把 times 的值(5)賦給 n。我們稱函數調用傳遞的值爲實際參數(actualargument或actual parameter),簡稱實參。所以,函數調用pound(10)把實際參數10傳遞給函數,然後該函數把10賦給形式參數(變量n)。也就是說,main()中的變量times的值被拷貝給pound()中的新變量n。
注意 實參和形參
在英文中,argument和parameter經常可以互換使用,但是C99標準規定了:對於actual argument或actual parameter使用術語argument(譯爲實參);對於formal argument或formal parameter使用術語parameter(譯爲形參)。爲遵循這一規定,我們可以說形參是變量,實參是函數調用提供的值,實參被賦給相應的形參。因此,在上程序清單中,times是pound()的實參,n是
pound()的形參。類似地,在函數調用pound(times + 4)中,表達式times + 4的值是該函數的實參。
變量名是函數私有的,即在函數中定義的函數名不會和別處的相同名稱發生衝突。如果在pound()中用times代替n,那麼這個times與main()中的times不同。也就是說,程序中出現了兩個同名的變量,但是程序可以區分它們。
現在,我們來學習函數調用。第1 個函數調用是pound(times),times的值5被賦給n。因此, printf()函數打印了5個井號和1個換行符。第2個函數調用是pound(ch)。這裏,ch是char類型,被初始化爲!字符,在ASCII中ch的數值是33。但是pound()函數的參數類型是int,與char不匹配。程序開頭的函數原型在這裏發揮了作用。原型(prototype)即是函數的聲明,描述了函數的
返回值和參數。pound()函數的原型說明了兩點:
該函數沒有返回值(函數名前面有void關鍵字);
該函數有一個int類型的參數。
該例中,函數原型告訴編譯器pound()需要一個int類型的參數。相應地,當編譯器執行到pound(ch)表達式時,會把參數ch自動轉換成int類型。在我們的系統中,該參數從1字節的33變成4字節的33,所以現在33的類型滿足函數的要求。與此類似,最後一次調用是pound(f),使得float類型的變量被轉換成合適的類型。
在ANSI C之前,C使用的是函數聲明,而不是函數原型。函數聲明只指明瞭函數名和返回類型,沒有指明參數類型。爲了向下兼容,C現在仍然允許這樣的形式:
void pound(); /* ANSI C之前的函數聲明 */
如果用這條函數聲明代替pound.c程序中的函數原型會怎樣?第 1 次函數調用,pound(times)沒問題,因爲times是int類型。第2次函數調用,pound(ch)也沒問題,因爲即使缺少函數原型,C也會把char和short類型自動升級爲int類型。第3次函數調用,pound(f)會失敗,因爲缺少函數原型,float會被自動升級爲 double,這沒什麼用。雖然程序仍然能運行,但是輸出的內容不正確。在函數調用中顯式使用強制類型轉換,可以修復這個問題:
pound ((int)f); // 把f強制類型轉換爲正確的類型
注意,如果f的值太大,超過了int類型表示的範圍,這樣做也不行。
章節程序演示
程序清單演示了本章介紹的幾個概念,這個程序對某些人很有用。程序看起來很長,但是所有的計算都在程序的後面幾行中。我們儘量使用大量的註釋,讓程序看上去清晰明瞭。請通讀該程序,稍後我們會分析幾處要點。
(若程序再VS中無法運行Scanf函數,請參考:VS2015使用scanf報錯解決方案)
/************************************************************************
功能:演示本章介紹的幾個概念
************************************************************************/
#include <stdio.h>
const int S_PER_M = 60; // 1分鐘的秒數
const int S_PER_H = 3600; // 1小時的分鐘數
const double M_PER_K = 0.62137; // 1公里的英里數
int main(void)
{
double distk, distm; // 跑過的距離(分別以公里和英里爲單位)
double rate; // 平均速度(以英里/小時爲單位)
int min, sec; // 跑步用時(以分鐘和秒爲單位)
int time; // 跑步用時(以秒爲單位)
double mtime; // 跑1英里需要的時間,以秒爲單位
int mmin, msec; // 跑1英里需要的時間,以分鐘和秒爲單位
printf("這個程序是對你比賽時間公制轉換\n");
printf("一英里的跑步時間和你的平均成績\n");
printf("速度(英里/小時).\n");
printf("請輸入以公里爲單位的長跑\n");
scanf("%lf", &distk); // %lf表示讀取一個double類型的值
printf("下一步以分鐘和秒爲單位輸入時間\n");
printf("從輸入分鐘開始\n");
scanf("%d", &min);
printf("輸入你的秒數 .\n");
scanf("%d", &sec);
time = S_PER_M * min + sec; // 把時間轉換成秒
distm = M_PER_K * distk; // 把公里轉換成英里
rate = distm / time * S_PER_H; // 英里/秒×秒/小時 = 英里/小時
mtime = (double)time / distm; // 時間/距離 = 跑1英里所用的時間
mmin = (int)mtime / S_PER_M; // 求出分鐘數
msec = (int)mtime % S_PER_M; // 求出剩餘的秒數
printf("你跑 %1.2f km (%1.2f 英里) 用 %d min, %dsec.\n",distk, distm, min, sec);
printf("這個速度相當於跑了一英里 %d min, ",mmin);
printf("%d sec.\n你的平均速度是 %1.2f mph.\n", msec,rate);
system("pause"); //暫停控制檯
return 0;
}
程序清單把時間轉換成分鐘和秒,除此之外還使用了類型轉換。爲什麼要進行類型轉換?因爲程序在秒轉換成分鐘的部分需要型參數,但是在公里轉換成英里的部分需要浮點運算。我們使用強制類型轉換運算符進行了顯式轉換。實際上,我們曾經利用自動類型轉換編寫這個程序,即使用int類型的mtime來強制時間計算轉換成整數形式。但是,在測試的11個系統中,這個版本的程序在1個系統上無法運行,這是由於編譯器(版本比較老)沒有遵循C規則。而使用強制類型轉換就沒有問題。對大家而言,強制類型轉換強調了轉換類型的意圖,對編譯器而言也是如此。
下面是程序清單的輸出示例:
這個程序是對你比賽時間公制轉換
一英里的跑步時間和你的平均成績
速度(英里/小時).
請輸入以公里爲單位的長跑
10
下一步以分鐘和秒爲單位輸入時間
從輸入分鐘開始
36
輸入你的秒數 .
23
你跑 10.00 km (6.21 英里) 用 36 min, 23sec.
這個速度相當於跑了一英里 5 min, 51 sec.
你的平均速度是 10.25 mph.
請按任意鍵繼續. . .