本文內容來自網道項目,網道/WangDoc.com。
網道是一個文檔網站,提供高質量的、擁有自主版權的、可以自由使用的中文軟件文檔。鄙人無意間瀏覽到后發現網站提供的軟件文檔內容講解十分通俗,並且質量較高,特此收藏與分享。
本文乃至本系列都是謄抄於網道C語言教程,如有各種不當之處,還請速速聯系。
1. 語句
C 語言的代碼由一行行語句(statement)組成。語句就是程序執行的一個操作命令。C 語言規定,語句必須使用分號結尾,除非有明確規定可以不寫分號。
int x = 1;
上面就是一個變量聲明語句,聲明整數變量x
,並且將值設為1
。
多個語句可以寫在一行。
int x; x = 1;
上面示例是兩個語句寫在一行。所以,語句之間的換行符並不是必需的,只是為了方便閱讀代碼。
一個語句也可以寫成多行,這時就要依靠分號判斷語句在哪一行結束。
int x;
x
=
1
;
上面示例中,第二個語句x = 1;
被拆成了四行。編譯器會自動忽略代碼里面的換行。單個分號也是有效語句,稱為“空語句”,雖然毫無作用。
;
2. 表達式
C 語言的各種計算,主要通過表達式完成。表達式(expression)是一個計算式,用來獲取值。
1 + 2
上面代碼就是一個表達式,用來獲取1 + 2
這個算術計算的結果。
表達式加上分號,也可以成為語句,但是沒有實際的作用。
8;
3 + 4;
上面示例是兩個表達式,加上分號以后成為語句。
表達式與語句的區別主要是兩點:
- 語句可以包含表達式,但是表達式本身不構成語句。
- 表達式都有返回值,語句不一定有。因為語句用來執行某個命令,很多時候不需要返回值,比如變量聲明語句(
int x = 1
)就沒有返回值。
3. 語句塊
C 語言允許多個語句使用一對大括號{}
,組成一個塊,也稱為復合語句(compounded statement)。在語法上,語句塊可以視為多個語句組成的一個復合語句。
{
int x;
x = 1;
}
上面示例中,大括號形成了一個語句塊。
大括號的結尾不需要添加分號。
4. 空格
C 語言里面的空格,主要用來幫助編譯器區分語法單位。如果語法單位不用空格就能區分,空格就不是必須的,只是為了增加代碼的可讀性。
int x = 1;
// 等同於
int x=1;
上面示例中,賦值號(=
)前后有沒有空格都可以,因為編譯器這里不借助空格,就能區分語法單位。
語法單位之間的多個空格,等同於單個空格。
int x = 1;
上面示例中,各個語法單位之間的多個空格,跟單個空格的效果是一樣的。
空格還用來表示縮進。多層級的代碼有沒有縮進,其實對於編譯器來說並沒有差別,沒有縮進的代碼也是完全可以運行的。強調代碼縮進,只是為了增強代碼可讀性,便於區分代碼塊。
大多數 C 語言的風格要求是,下一級代碼比上一級縮進4個空格。為了書寫的緊湊,本書采用縮寫兩個空格。
// 縮進四個空格
if(x > 0)
printf("positive\n");
// 縮進兩個空格
if(x > 0)
printf("positive\n");
只包含空格的行被稱為空白行,編譯器會完全忽略該行。
5. 注釋
注釋是對代碼的說明,編譯器會自動忽略注釋,也就是說,注釋對實際代碼沒有影響。
C 語言的注釋有兩種表示方法。第一種方法是將注釋放在/*...*/
之間,內部可以分行
/* 注釋 */
/*
這是一行注釋
*/
這種注釋可以插在行內。
int open(char* s/* file name */, int mode);
上面示例中,/* filename */
用來對函數參數進行說明,跟在它后面的代碼依然會有效執行。
這種注釋一定不能忘記寫結束符號*/
,否則很容易導致錯誤。
printf("a "); /* 注釋一
printf("b ");
printf("c "); /* 注釋二 */
printf("d ");
上面示例的原意是,第一行和第三行代碼的尾部,有兩個注釋。但是,第一行注釋忘記寫結束符號,導致注釋一延續到第三行結束。
第二種寫法是將注釋放在//
后面,從雙斜杠到行尾都屬於注釋。這種注釋只能是單行,可以放在行首,也可以放在一行語句的結尾。這是C99 標准新增的語法。
// 這是一行注釋
int x = 1; // 這也是注釋
不管哪一種注釋,都不能放在雙引號里面。雙引號里面的注釋符號,會成為字符串的一部分,解釋為普通符號,失去注釋作用。
printf("// hello /* world */ ");
上面示例中,雙引號里面的注釋符號,都會被視為普通字符,沒有注釋作用。
編譯時,注釋會被替換成一個空格,所以min/* space */Value
會變成min Value
,而不是minValue
。
6. printf()
6.1 基本語法
本書的示例會大量用到printf()
函數,這里先介紹一下這個函數。
printf()
的作用是將參數文本輸出到屏幕。它名字里面的f
代表format
(格式化),表示可以定制輸出文本的格式。
printf("Hello World");
上面命令會在屏幕上輸出一行文字"Hello World"。
printf()
不會在行尾自動添加換行符,運行結束后,光標就停留在輸出結束的地方,不會自動換行。為了讓光標移到下一行的開頭,可以在輸出文本的結尾,添加一個換行符\n
。
printf("Hello World\n");
如果文本內部有換行,也是通過插入換行符來實現。
printf("Hello\nWorld\n");
上面示例先輸出一個Hello
,然后換行,在下一行開頭輸出World
,然后又是一個換行。
上面示例也可以寫成兩個printf()
,效果完全一樣。
printf("Hello\n");
printf("World\n");
printf()
是在標准庫的頭文件stdio.h
定義的。使用這個函數之前,必須在源碼文件頭部引入這個頭文件。
#include <stdio.h>
int main()
{
printf("Hello World\n");
}
上面示例中,只有在源碼頭部加上#include <stdio.h>
,才能使用printf()
這個函數。
#include
指令的詳細解釋,請看《預處理器》一章。
6.2 占位符
printf()
可以在輸出文本中指定占位符。所謂"占位符",就是在這個位置可以用其他值代入。
// 輸出 There are 3 apples
printf("There are %i apples\n", 3);
上面示例中,There are %i apples\n
是輸出文本,里面的%i
就是占位符,表示這個位置要用其它值來替換。占位符的第一個字符一律為百分號%
,第二個字符表示占位符的類型,%i
表示這里代入的值必須是一個整數。
printf()
的第二個參數就是替換占位符的值,上面的例子是整數3
替換%i
。執行后的輸出結果就是There are 3 apples
。
常用的占位符除了%i
,還有%s
表示代入的是字符串。
printf("%s will come tonight\n", "Jane");
上面示例中,%s
表示代入的是一個字符串,所以printf()
的第二個參數就必須是字符串,這個例子是Jane
。執行后的輸出就是Jane will come tonight
。
輸出文本里面可以使用多個占位符。
printf("%s says it is %i o'clock\n", "Ben", 21);
上面示例中,輸出文本%s says it is %i o'clock
有兩個占位符,第一個是字符串占位符%s
,第二個是整數占位符%i
,分別對應printf()
的第二個參數(Ben
)和第三個參數(21
)。執行后的輸出就是Ben says it is 21 o'clock
。
printf()
參數與占位符是一一對應關系,如果有n
個占位符,printf()
的參數就應該有n + 1
個。如果參數個數少於對應的占位符,printf()
可能會輸出內存中的任意值。
printf()
的占位符有許多種類,與 C 語言的數據類型相對應。下面按照字母順序,列出常用的占位符,方便查找,具體含義在后面章節介紹。
%a
:浮點數。%A
:浮點數。%c
:字符。%d
:十進制整數。%e
:使用科學計數法的浮點數,指數部分的e
為小寫。%E
:是用科學計數法的浮點數,指數部分的E
為大寫。%i
:整數,基本等同於%d
。%f
:小數(包含float
類型和double
類型)。%g
:6個有效數字的浮點數,整數部分一旦超過6位,就會自動轉為科學計數法,指數部分的e
為小寫。%G
:等同於%g
,唯一的區別是指數部分的E
為大寫。%hd
:十進制 short int 類型。%ho
:八進制 short int 類型。%hx
:十六進制 short int 類型。%hu
:unsigned short int 類型。%ld
:十進制 long int 類型。%lo
:八進制 long int 類型。%lx
:十六進制 long int 類型。%lu
:unsigned long int 類型。%lld
:十進制 long long int 類型。%llo
:八進制 long long int 類型。%llx
:十六進制 long long int 類型。%llu
:unsigned long long int 類型。%Le
:科學計數法表示的 long double 類型浮點數。%Lf
:long double 類型浮點數。%n
:已輸出的字符串數量。該占位符本身不輸出,只將值存儲在指定變量之中。%o
:八進制整數。%p
:指針。指針就是地址。%s
:字符串。%u
:無符號整數(unsigned int)。%x
:十六進制整數。%zd
:size_t
類型。%%
:輸出一個百分號。
6.3 輸出格式
printf()
可以定制占位符的輸出格式。
(1)限定寬度
printf()
允許限定占位符的最小寬度。
printf("%5d\n", 123); // 輸出為 " 123"
上面示例中,%5d
表示這個占位符的寬度至少為5位。如果不滿5位,對應的值的前面會添加空格。
輸出的值默認是右對齊,即輸出內容前面會有空格;如果希望改成左對齊,在輸出內容后面添加空格,可以在占位符的%
的后面插入一個-
號。
printf("%d-5d\n", 123); // 輸出為 "123 "
上面示例中,輸出內容123
的后面添加了空格。
對於小數,這個限定符會限制所有數字的最小顯示寬度。
// 輸出 " 123.450000"
printf("%12f\n", 123.45);
上面示例中,%12f
表示輸出的浮點數最少要占據12位。由於小數的默認顯示精度是小數點后6位,所以123.45
輸出結果的頭部會添加2個空格。
(2)總是顯示正負號
默認情況下,printf()
不對正數顯示+
號,只對負數顯示-
號。如果想讓正數也輸出+
號,可以在占位符的%
后面加一個+
。
printf("%+d\n", 12); // 輸出 +12
printf("%+d\n", -12); // 輸出 -12
上面示例中,%+d
可以確保輸出的數值,總是帶有正負號。
(3)限定小數位數
輸出小數時,有時希望限定小數的位數。舉例來說,希望小數點后面只保留兩位,占位符可以寫成%.2f
。
// 輸出 Number is 0.50
printf("Number is %.2f\n", 0.5);
上面示例中,如果希望小數點后面輸出3位(0.500
),占位符就要寫成%.3f
。
這種寫法可以與限定寬度占位符,結合復用。
// 輸出為 " 0.50"
printf("%6.2f\n", 0.5);
上面示例中,%6.2f
表示輸出字符串最小寬度為6,小數位數為2.所以,輸出字符串的頭部有兩個空格。
最小寬度和小數位數這兩個限定值,都可以用*
代替,通過printf()
的參數傳入。
printf("%*.*f\n", 6, 2, 0.5);
// 等同於
printf("%6.2f\n", 0.5);
上面示例中,%*.*f
的兩個星號通過printf()
的兩個參數6
和2
傳入。
(4)輸出部分字符串
%s
占位符用來輸出字符串,默認是全部輸出。如果只想輸出開頭的部分,可以用%.[m]s
指定輸出的長度,其中[m]
代表一個數字,表示所要輸出的長度。
// 輸出 hello
printf("%.5s\n", "hello world");
上面示例中,占位符%.5s
表示只輸出字符串"hello world"的前5個字符,即"hello"。
7. 標准庫,頭文件
程序需要用到的功能,不一定需要自己編寫, C 語言可能已經自帶了。程序員只要去調用這些自帶的功能,就省得自己編寫代碼了。舉例來說,printf()
這個函數就是 C 語言自帶的,只要去調用它,就能實現在屏幕上輸出內容。
C 語言自帶的所有這些功能,統稱為"標准庫"(standard library),因為它們是寫入標准的,到底包括哪些功能,應該怎么使用的,都是規定好的,這樣才能保證代碼的規范和可移植。
不同的功能定義在不同的文件里面,這些文件統稱為"頭文件"(header file)。如果系統自帶某一個功能,就一定還會自帶描述這個功能的頭文件,比如printf()
的頭文件就是系統自帶的stdio.h
。頭文件的后綴通常是.h
。
如果要使用某個功能,就必須先加載對應的頭文件,加載使用的是#include
命令。這就是為什么使用printf()
之前,必須先加載stdio.h
的原因。
#include <stdio.h>
注意,加載頭文件的#include
語句不需要分號結尾,詳見《預處理器》一章。
本系列內容來自網道項目,網道/WangDoc.com。