詳解C語言中的符號常量、變量與算術(shù)表達(dá)式
C語言中的符號常量
在結(jié)束討論溫度轉(zhuǎn)換程序前,我們再來看一下符號常量。在程序中使用 300、20 等類似的“幻數(shù)”并不是一個好習(xí)慣,它們幾乎無法向以后閱讀該程序的人提供什么信息,而且使程序的修改變得更加困難。處理這種幻數(shù)的一種方法是賦予它們有意義的名字。#define 指令可以把符號名(或稱為符號常量)定義為一個特定的字符串:
#define 名字 替換文本
在該定義之后,程序中出現(xiàn)的所有在 #define 中定義的名字(既沒有用引號引起來,也不是其它名字的一部分)都將用相應(yīng)的替換文本替換。其中,名字與普通變量名的形式相同:它們都是以字母打頭的字母和數(shù)字序列;替換文本可以是任何字符序列,而不僅限于數(shù)字。
在該定義之后,程序中出現(xiàn)的所有在 #define 中定義的名字(既沒有用引號引起來,也不是其它名字的一部分)都將用相應(yīng)的替換文本替換。其中,名字與普通變量名的形式相同:它們都是以字母打頭的字母和數(shù)字序列;替換文本可以是任何字符序列,而不僅限于數(shù)字。
#include <stdio.h> #define LOWER 0 /* lower limit of table */ #define UPPER 300 /* upper limit */ #define STEP 20 /* step size */ /* print Fahrenheit-Celsius table */ main() { int fahr; for (fahr = LOWER; fahr <= UPPER; fahr = fahr + STEP) printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32)); }
其中,LOWER、UPPER 與 STEP 都是符號常量,而非變量,因此不需要出現(xiàn)在聲明中。符號常量名通常用大寫字母拼寫,這樣可以很容易與用小寫字母拼寫的變量名相區(qū)別。注意,#define 指令行的末尾沒有分號。
變量與算術(shù)表達(dá)式
我們來看下一個程序,使用公式℃=(5/9)(℉-32)打印下列華氏溫度與攝氏溫度對照表:
0 -17 20 -6 40 4 60 15 80 26 100 37 120 48 140 60 160 71 180 82 200 93 220 104 240 115 260 126 280 137 300 148
此程序中仍然只包括一個名為 main 的函數(shù)定義。它比前面打印“hello, world”的程序長一些,但并不復(fù)雜。這個程序中引入了一些新的概念,包括注釋、聲明、變量、算術(shù)表達(dá)式、循環(huán)以及格式化輸出。該程序如下所示:
#include <stdio.h> /* 當(dāng) fahr=0,20,… ,300 時,分別打印華氏溫度與攝氏溫度對照表 */ main() { int i; int fahr, celsius; int lower, upper, step; lower = 0; /* 溫度表的下限 */ upper = 300; /* 溫度表的上限 */ step = 20; /* 步長 */ fahr = lower; while (fahr <= upper) { celsius = 5 * (fahr-32) / 9; printf("%d\t%d\n", fahr, celsius); fahr = fahr + step; } scanf("%s", &i); }
其中的一行:
/*當(dāng) fahr=0,20,… ,300 時,分別打印華氏溫度與攝氏溫度對照表 */
稱為注釋,此處,它簡單地解釋,該程序是做什么用的。包含在/*與*/之間的字符序列將被編譯器忽略。注釋可以自由地運用在程序中,使得程序更易于理解。程序中允許出現(xiàn)空格、制表符或換行符之處,都可以使用注釋。
在 C 語言中,所有變量都必須先聲明后使用。聲明通常放在函數(shù)起始處,在任何可執(zhí)行語句之前。聲明用于說明變量的屬性,它由一個類型名和一個變量表組成,例如:
int fahr, celsius; int lower, upper, step;
其中,類型 int 表示其后所列變量為整數(shù),與之相對應(yīng)的,float 表示所列變量為浮點數(shù)(即可以帶有小數(shù)部分的數(shù))。int 與 float 類型的取值范圍取決于具體的機器。對于 int 類型,通常為 16 位,其取值范圍在-32768~32767 之間,也有用 32 位表示的 int 類型。float 類型通常是 32 位,它至少有 6 位有效數(shù)字,取值范圍一般在 10-38~1038 之間。
除 int 與 float 類型之外,C 語高還提供了其它一些基本數(shù)據(jù)類型,例如:
- char:字符,一個字節(jié)
- short:短整型
- long:長整型
- double:雙精度浮點型
這些數(shù)據(jù)類型對象的大小也取決于具體的機器。另外,還存在這些基本數(shù)據(jù)類型的數(shù)組、結(jié)構(gòu)、聯(lián)合,指向這些類型的指針以及返回這些類型值的函教。
在上面的溫度轉(zhuǎn)換程序中,最開始執(zhí)行的計算是下列 4 個賦值語句:
lower = 0; upper = 300; step = 20; fahr = lower;
它們?yōu)樽兞吭O(shè)置初值。各條語句均以分號結(jié)束。
溫度轉(zhuǎn)換表中的各行計算方式相同,因此可以用循環(huán)語句重復(fù)輸出各行。這是 while 循環(huán)語句的用途:
while (fahr <= upper) { ... }
while循環(huán)語句的執(zhí)行方式是這樣的:首先測試圓括號中的條件;如果條件為真(fahr<=upper),則執(zhí)行循環(huán)體(括在花括號中的 3 條語句);然后再重新測試圓括號中的條件,如果為真,則再次執(zhí)行循環(huán)體;當(dāng)圓括號中的條件測試結(jié)果為假(fahr>upper)時,循環(huán)結(jié)束,并繼續(xù)執(zhí)行跟在 while 循環(huán)語句之后的下一條語句。在本程序中,循環(huán)語句后沒有其它語句,因此整個程序的執(zhí)行終止。
while 語句的循環(huán)體可以是用花括號括起來的一條或多條語句(如上面的溫度轉(zhuǎn)換程序),也可以是不用花括號包括的單條語句,例如:
while (i < j) i = 2 * i;
在這兩種情況下,我們總是把由 while 控制的語句縮進(jìn)一個制表位,這樣就可以很容易地看出循環(huán)語句中包含哪些語句。這種縮進(jìn)方式突出了程序的邏輯結(jié)構(gòu)。盡管 C 編譯器并不關(guān)心程序的外觀形式,但正確的縮進(jìn)以及保留適當(dāng)空格的程序設(shè)計風(fēng)格對程序的易讀性非常重要。我們建議每行只書寫一條語句,并在運算符兩邊各加上一個空格字符,這樣可以使得運算的結(jié)合關(guān)系更清楚明了。相比而言,花括號的位置就不那么重要了。我們從比較流行的一些風(fēng)格中選擇了一種,讀者可以選擇適合自己的一種風(fēng)格,并養(yǎng)成一直使用這種風(fēng)格的好習(xí)慣。
在該程序中,絕大部分工作都是在循環(huán)體中完成的。循環(huán)體中的賦值語句:
printf(" %d\t%d\n", fahr, celsius);
用于打印兩個整數(shù) fahr 與 celsius 的值,并在兩者之間留一個制表符的空間(\t)。
printf 函數(shù)的第一個參數(shù)中的各個%分別對應(yīng)于第二個、第三個、……參數(shù),它們在數(shù)目和類型上都必須匹配,否則將出現(xiàn)錯誤的結(jié)果。
順便指出,printf 函數(shù)并不是 C 語言本身的一部分,C 語言本身并沒有定義輸入/輸出功能。printf 僅僅是標(biāo)準(zhǔn)庫函數(shù)中一個有用的函數(shù)而已,這些標(biāo)準(zhǔn)序函數(shù)在 C 語言程序中通常都可以使用。但是,ANSI 標(biāo)準(zhǔn)定義了 printf 函數(shù)的行為,因此,對每個符合該標(biāo)準(zhǔn)的編譯器和庫來說,該函數(shù)的屬性都是相同的。
上述的溫度轉(zhuǎn)換程序存在兩個問題。比較簡單的問題是,由于輸出的數(shù)不是右對齊的,所以輸出的結(jié)果不是很美觀。這個問題比較容易解決:如果在 printf 語句的第一個參數(shù)的%d 中指明打印寬度,則打印的數(shù)字會在打印區(qū)域內(nèi)右對齊。例如,可以用語句
printf(" %3d %6d\n", fahr, celsius);
打印 fahr 與 celsius 的值,這樣,fahr 的值占 3 個數(shù)字寬,celsius 的值占 6 個數(shù)字寬,輸出的結(jié)果如下所示:
0 -17 20 -6 40 4 60 15 80 26 100 37 ...
另一個較為嚴(yán)重的問題是,由于我們使用的是整型算術(shù)運算,因此經(jīng)計算得到的攝氏溫度值不太精確,例如,與 0℉對應(yīng)的精確的攝氏溫度應(yīng)該為-17.8℃,而不是-17℃。為了得到更精確的結(jié)果,應(yīng)該用浮點算術(shù)運算代替上面的整型算術(shù)運算。這就需要對程序做適當(dāng)修改。下面是該程序的又一種版本
#include <stdio.h> /* print Fahrenheit-Celsius table for fahr = 0, 20, ..., 300; floating-point version */ main() { float fahr, celsius; float lower, upper, step; lower = 0; upper = 300; step = 20; /* lower limit of temperatuire scale */ /* upper limit */ /* step size */ fahr = lower; while (fahr <= upper) { celsius = (5.0/9.0) * (fahr-32.0); printf("%3.0f %6.1f\n", fahr, celsius); fahr = fahr + step; } }
這個程序與前一個程序基本相同,不同的是,它把 fahr 與 celsius 聲明為 float 類型,轉(zhuǎn)換公式的表述方式也更自然一些。在前一個程序中,之所以不能使用 5 / 9 的形式,是因為按整型除法的計算規(guī)則,它們相除并舍位后得到的結(jié)果為 0。但是,常數(shù)中的小數(shù)點表明該常數(shù)是一個浮點數(shù),因此,5.0 / 9.0 是兩個浮點數(shù)相除,結(jié)果將不被舍位。
如果某個算術(shù)運算符的所有操作數(shù)均為整型,則執(zhí)行整型運算。但是,如果某個算術(shù)運算符有一個浮點型操作數(shù)和一個整型操作數(shù),則在開始運算之前整型操作數(shù)將會被轉(zhuǎn)換為浮點型。例如,在表達(dá)式 fahr – 32 中,32 在運算過程中將被自動轉(zhuǎn)換為浮點數(shù)再參與運算。不過,即使浮點常量取的是整型值,在書寫時最好還是為它加上一個顯式的小數(shù)點,這樣可以強調(diào)其浮點性質(zhì),便于閱讀。
在這里需要注意,賦值語句 fahr = lower; 與條件測試語句 while (fahr <= upper) 也都是按照這種方式執(zhí)行的,即在運算之前先把 int 類型的操作數(shù)轉(zhuǎn)換為 float 類型的操作數(shù)。
printf 中的轉(zhuǎn)換說明%3.0f 表明待打印的浮點數(shù)(即 fahr)至少占 3 個字符寬,且不帶小數(shù)點和小數(shù)部分;%6.1f 表明另一個待打印的數(shù)(celsius)至少占 6 個字符寬,且小數(shù)點后面有 1 位數(shù)字。其輸出如下所示:
0 -17.8 20 -6.7 40 4.4 ...
格式說明可以省略寬度與精度,例如,%6f 表示待打印的浮點數(shù)至少有 6 個字符寬;%.2f指定待打印的浮點數(shù)的小數(shù)點后有兩位小數(shù),但寬度沒有限制;%f 則僅僅要求按照浮點數(shù)打印該數(shù)。
- %d, 按照十進(jìn)制整型數(shù)打印
- %6d, 按照十進(jìn)制整型數(shù)打印,至少 6 個字符寬
- %f, 按照浮點數(shù)打印
- %6f, 按照浮點數(shù)打印,至少 6 個字符寬
- %.2f, 按照浮點數(shù)打印,至少 6 個字符寬
- %6.2f, 按照浮點數(shù)打印,至少 6 個字符寬,小數(shù)點后有兩位小數(shù)
此外,printf 函數(shù)還支持下列格式說明:%o 表示八進(jìn)制數(shù);%x 表示十六進(jìn)制數(shù);%c表示字符;%s 表示字符串;%%表示百分號(%)本身。
相關(guān)文章
C++實現(xiàn)學(xué)生管理系統(tǒng)示例解析
這篇文章主要介紹了C++實現(xiàn)學(xué)生管理系統(tǒng)示例解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08C++數(shù)據(jù)結(jié)構(gòu)與算法之哈夫曼樹的實現(xiàn)方法
這篇文章主要介紹了C++數(shù)據(jù)結(jié)構(gòu)與算法之哈夫曼樹的實現(xiàn)方法,簡單說明了哈夫曼樹的原理,并結(jié)合具體實例形式分析了C++實現(xiàn)哈夫曼樹的相關(guān)操作技巧,需要的朋友可以參考下2017-11-11

C++實現(xiàn)LeetCode(114.將二叉樹展開成鏈表)