程序員之程序設計知識點三
3.1 順序結構
順序結構用來描述一個計算或操作序列,表示從序列的第一個計算開始,順序執行序列中的每個計算,直至序列的最后一個計算。通常,一個復雜的計算過程不能用一個簡單的計算來表達,而需把復雜的計算描述成簡單計算的序列。
1.復合語句
在C語言中,將順序執行的語句序列,用花括號括起來,構成C語言的復合語句。在邏輯上視復合語句為單個語句,它也能用作其它結構語句的成分語句。在很多場合,復合語句內還會包含其它結構語句。
2.表達式語句
在順序結構中,最頻繁使用的是表達式之后接上一個分號。例如,在賦值表達式之后接上分號,完成用表達式的值更新某變量,習慣稱這種表達式語句為賦值語句;在函數調用之后接上分號,完成指定的計算功能,習慣稱這種表達式語句為函數調用語句。
3.2 常用輸入輸出庫函數
最基本的輸入輸出庫函數有字符輸入函數、字符輸出函數、格式輸入函數和格式輸出函數。
1.字符輸入函數
字符輸入函數getchar()的功能是從標準輸入設備上(通常是鍵盤終端)讀取一個字符。該函數沒有參數,對它的每次調用,就返回下一個輸入字符的ASCII代碼值。例如,執行語句
ch=getchar();
使變量ch得到輸入字符的ASCII代碼值。一般情況下,這里的變量ch為char型或int型。當程序在輸入字符后,用ch判定輸入文件是否結束時,變量ch必須是int型的。這是因為文件結束標記值是-1,是int型的。程序中常用EOF表示當前讀人字符是文件結束標記,常量名EOF在文件Stdio.h中被定義為-1。
2.字符輸出函數
字符輸出函數ptuchar()有一個字符的ASCII代碼值參數,函數調用putchar (ch)的功能是將以出值為其ASCII代碼的字符輸出到標準輸出設備(通常是終端顯示屏)上。這里ch可以是char型或int型數據。
3.格式輸入函數
格式輸入函數scanf()的作用是從標準設備讀人字符序列,按格式控制字符率所包含的格式解釋輸入字符序列,并將解釋結果存儲到對應的變量中。調用格式輸入函數scanf()的一般形式為
scanf(格式控制字符串,變量地址,變量地址,……)
格式控制字符串是字符串表達式,通常是由一對雙引號括起來的字符串常量,直接用于解釋輸入字符序列。格式控制字符率可以包含:
·空白類字符(空格符或制表符),它們使輸入跳過空白類字符,直到遇到下一個非空白類字符。
·普通字符(不包括%),它們要求輸入字符流中下一個字符與它相同。
·格式轉換說明,以字符’%’開頭至輸入格式符結束的字符序列組成。格式轉換說明引導對下一輸入字符段進行轉換。
格式轉換說明的一般形式為
%[*][w][h/l/L]輸入格式符
輸入格式符共有14個,有12種不同輸入格式,其中大綱要求掌握的7種輸入格式符的意義見表3.1。用方括號括住的內容是輸入格式修飾說明,可以缺省,它們的意義是:
(1)*--星號(賦值抑制符),對應的輸入數據項按格式要求被輸入,但結果不存儲。帶星號的格式轉換說明不對應變量地址。用它來跳過一個輸入數據項。
(2)--整型常數(域寬說明),表示輸入數據項的字符段的有效字符數。若實際輸入字符段的字符數小于W,以實際有效字符為準。
對于數值數據輸入格式來說,輸入域定義為從下一個非空白類字符起(因此可能跳過若干個空格符、制表符、換行符),到一個與數值數據相矛盾的字符,或直到輸入了指定個數的字符數;對于字符率輸入格式來說,輸入域定義為從下一個非空白類字符起,輸入非空白類字符,直至遇到空白類字符,或直到輸入了指定個數的非空白字符。
(3) h/l/L長度修飾符,指明輸入數據項的存儲類型。
h 修飾格式符d,o,X時,表示輸入的整數按短整型存儲。
l 修飾格式符d,O,X時,表示輸入的整數按長整型存儲。
l 修飾格式符e,f時,表示輸入的實數按double型存儲。
缺省時,對于格式符d,o,x,表示輸入的整數按int整型存儲;對于格式符e,f,表示輸入的實數是按float型存儲。
3.3 常用輸入格式符表中格式符的意義
d 輸入十進制形式的整型數據
O 以人進制形式輸入整型數據
X 以十六進制形式輸入整型數據
C 輸入字符數據
S 輸入字符串
e,f 輸入實型數據
說明:
(1)格式控制字符率之后給出的是變量地址,而不是變量名(除非是指針)。如要為整型變量n輸入數據,寫成
scanf(”%d", n)是不正確的,應寫成 scanf(”% d”,&n)
(2)如果在格式控制字符串中除格式轉換說明和空白符之外,還有其它字符,則在輸入數據時應輸入與這些字符相同的字符。例如,
scanf(”%d, %d’’,&i, &j)
則在為i,j輸入數據時,緊接在第一個整型數據之后,需要有一個逗號字符,如輸入
1,2
是正確的;而輸入
1 2
等其它形式都是不正確的。
(3)在用”%c ”格式轉換說明輸入字符時,空白類字符和用轉義字符表示的字符都能作為有效字符輸入。要輸入一串空白類字符之后的第一個非空白類字符,可采用格式”% C”。格式字符率中的空格符使輸入跳過空白類字符到第一個非空白類字符,然后被C格式輸入。
(4)為整型變量輸入整數時,若變量類型為短整型,則必須在格式符之前加長度修飾說明h;若變量類型為長整型,則必須在格式符之前加長度修飾說明1。
(5)輸入數值數據時,輸入字符流中的前導空白類字符會被自動跳過,從空白類字符后的數值數據字符開始輸入。構成數值數據的字符被輸入轉換成計算機的內部表示,并存儲結果。
若第一個非空白類字符不能構成數值字符,則立即結束輸入。
(6)S格式用來輸入字符串,對應的變量地址為字符列表(數組)的首地址,該數組必須大到足以容納可能輸入的最長字符串。在輸入字符流中,跳過前導的空白類字符,以非空白類字符開始,以后隨的第一個空白類字符結束的非空白類字符的字符序列作為一個字符串。scanf()函數在輸入的字符序列之后自動添加字符率結束標記符'\0'(因此,存儲輸入字符序列的字符數組的長度必須比實際最長字符串的字符數多1)。
(7)e,f格式用未輸入實數,對應的數據存儲地址為實型數據存儲地址。如格式轉換說明中含有長度修飾說明1,則為double型變量地址;若無長度修飾說明,則為float型變量地址。輸入數據的字符序列是由正負號(可有可無)、十進制數字串、帶小數點的小數部分(可有可無)。以e或E開頭的指數部分(可有可無)組成。
(8)在跳過前導空白符后,正在輸入數值數據和字符串時,遇以下情況,就認為該數據結束:
·遇空白類字符:空白符、制表符、換行符。
·已讀人由有效字符數所指定的字符數。如”%4d多至4個數字符。
·對于輸入數值數據,下一個字符不能構成正確的數據格式。如
scanf(”%d%C%f,&i,&c,&x)
假定變量i,c,x分別為int型、char型和float型。若輸入字符列為:
123a123x. 26
則變量i為123,變量c為字符a,變量x為123.0。
(9)輸入數據時,將字符流轉換成內部表示后,存儲到對應變量中。例如,
scanf(”%3d%*4d%d”,&i, &j)
如輸入字符行為
123456 78
將使變量i=123,j=78。其中數據456因賦值抑制符*的作用被跳過。一般從鍵盤讀入數據,不指定輸入數據項的有效字符數,數據項與數據項之間用空白符,或制表符,或回車符分隔。
4.格式輸出函數
格式輸出函數printf()的作用是將輸出項接指定的格式排版輸出到標準設備上(通常是終端顯示屏)。調用printf()函數的一般形式為
printf(格式控制字符串,表達式,表達式,……)
其中格式控制字符率是字符串表達式,通常是由用一對雙引號括起來的字符串常量。它包含三類字符:普通字符、轉義字符和格式轉換說明,它們的作用分別如下:
(l)普通字符,要求按原樣輸出。
(2)轉義字符,要求技轉義字符的意義輸出,如’\n’,表示輸出時回車換行,’\b’表示退格等。
(3)格式轉換說明,以字符%開頭至格式符結束的字符列組成,其一般形式為
%[-」「+」「」[#」「W][.p][h/l/L]輸出格式符
其中用方括號括住的內容是格式修飾說明,可以缺省(不出現),如"%d"、"% 7.5f"等。每個格式轉換說明對應一個輸出項,輸出項可以是常量、變量或表達式。格式轉換說明的作用是將對應輸出項的內容按格式符要求產生出字符列,并按格式修飾說明排版輸出。
輸出格式符共有16個,有12種不同的格式,考試大綱只要求掌握表3.2所列的九種。
3.4 常用輸出格式符表中格式符的意義
d或i 整型數據以十進制形式輸出
o 無符號整型數據以八進制形式輸出
X 無符號整型數據以十六進制形式輸出
U 元符號整型數據以十進制形式輸出
C 字符的ASCll碼數據,輸出對應的字符
S 輸出字符串
f 以“整數部分.小數部分”形式輸出實型數據
e 以[-]n.nnnnne±xx輸出實型數據
g 以f或e格式輸出
說明:
(1)x格式符同。格式符一樣,把符號位作為數的一部分輸出。對于x格式,用字符a、b、c、d、e、f(或A、B、C、D、E、F)表示9之后的六個十六進制數字符。
(2)一個整數,只要它的位在0-255范圍內,也可以用字符形式輸出,輸出以該整數為ASCII代碼的字符。反之,一個字符數據也可以用整數形式輸出,輸出該字符的ASCII代碼值。
(3)f、e和g格式符用于輸出實型數據,格式轉換時有四舍五人處理。對于f格式,小數點后的數字個數可由格式修飾說明p指定,若p為0,不顯示小數點。用e格式輸出時,對于非0實數,小數點前有一位非零數字,輸出格式中的有效位數可由格式修飾說明p指定;字符e(或E)之后是指數,指數部分至少包含兩個數字。若輸出值的絕對值不小于 1E+100,則指數部分多于兩位數字。
g格式能根據表示數據所需字符的多少自動選擇f格式或e(或E) 格式輸出實數,選擇是以輸出時所需字符數多少為標準。
格式修飾說明有七種,教材只介紹其中四種,它們的意義分別說明如下:
(1)W域寬說明,W是一個十進制整數,表示輸出字段的字符數。若轉換后需要的字符個數比給出的W多,則以實際需要為準;若轉換后需要的字符數比W少,就在左邊用填充字符補足(若給出左邊對齊標志(-),則在右邊補填充字符人通常用空白符作填充字符,若十進制整數W之前有前導0(此0不表示以八進制數給出字段寬度),則以字符0作填充字符。
(2)- 左對齊標志,當轉換后字符個數少于W時,在W所限定的字段寬度內,轉換所得字符列左對齊,右邊補填充符。缺省時,右對齊,左邊補填充符。
(3).p,其中p也是十進制整數。
對于g或e格式輸出,p指明輸出精度(有效數字位數),可以缺省,缺省值依賴于系統的規定(下面的例子設p的缺省值為6)。
對于f格式輸出,p指明輸出字符列的小數點之后的數字個數,可以缺省。
對于S格式輸出,p指明最多輸出字符率的前p個字符,多余截斷。缺省時,字符串的內容全部輸出。
對于d.i、O、u、x和X,表示至少出現的數字個數。
同域寬說明一樣,p也可以是字符*,而實際值由后面一個輸出項的整數值給出,若該值為負值,相當于沒有給出p。
(4) l指明輸出項的類型。
長度修飾符l用于格式符d、i、o、u、X,表示對應的輸出項是長整型或無符號長整型。
以下是格式輸出的一些例子。例如,
int i=1234; long j=1234567L;
printf(”%d,%+6d,%06d,%-6d, %5ld”,i,i,i,i,j)
將輸出:
1234,+1234,00l234,1234,1234567
注意:對于long型數據輸出,必須在格式符之前有長度修飾符l,表明輸出long型數據。
若 int k=045;long p=-1L;printf(”%#o,%4o,%6lo”,k,k,p)
將輸出:
045, 45, 37777777777
而printf("%#x,%4x,%6lx”,k,k,p)將輸出:
0x25, 25, FFFFFFFF
若 unsigned int u= 65535u;prinif(”%d,%4u,%ln’,u,u,p)
將輸出:
-l, 65535, 4294967295
若 char ch1= 045, ch2=’a’;printf(”%c,%-3c,%2c”,ch1,ch2,ch2)
將輸出:
%,a, a
若 char s[]==”ABCDEF’;printf(”%3s,%4.2s,%-7.4s,%.5s”,s,s,s,s)
將輸出:
ABCDEF, AB, ABCD, ABCDE
若 float f=123.4567f; double d=123.456789;
printf(”%.4f,%8.3f,%-7.2f,%.7f",f,f,f,d)
將輸出:
123.4567, 123.457, 123.46, 123.4567890
而 printf(”%.6e,%10.2e,%-10.2e,%.2e,%.9e”,f,f, f,f,d)
將輸出:
1.23457e+02, 1.2e+02,1.2e+02,l.2e+02, 1.23456789e+02
注意:實型數據的有效位數,不要以為凡是打印(顯示)的數字都是準確的。一般地,float型只有7位有效數字,double型有15位有效數字。實際上,因計算過程中的誤差積累,通常不能達到所說的有效位數。
另外,要注意%g格式的特殊性,當它選擇“整數部分.小數部分”形式時,因格式修飾說明.p在e格式中的意義是指明精度,所以p的值是整數部分位數與小數部分位數之和(不是f
格式中的小數位數)。如有
float g1=12.34f,g2=0.0f;
double d=123.456789, g=123456.789;
printf("%g,%G",g1,g2);
printf("%f,%g,%g,%g,%.8g"’,g1,g1,d,g,g)
將輸出:
12.34,0
12.340000,12.34,123.457,123457,123456.79
3.5 選擇結構
選擇結構有單分支選擇結構、雙分支選擇結構和多分支選擇結構。C語言提供相應的if語句和switCh語句分別用來描述這些選擇結構。
1.單分支選擇語句
單分支選擇語句有以下形式:
if(表達式)
語句
這種形式的語句執行過程是:
(1)計算表達式的值;
(2)測試表達式的值。若表達式的值非0,則執行它的成分語句,并結束單分支選擇的執行;若表達式的值為0,則立即結束單分支選擇的執行。
2.雙分支選擇語句
漢分支選擇語句有以下形式:
if(表達式)
語句1
else
語句2
雙分支選擇語句根據給定的選擇條件表達式值為非0或為0兩種情況,從兩個供選擇的成分語句中自動選取一個成分語句執行。雙分支選擇語句的執行過程是:
(1)計算表達式的值;
(2)測試表達式的值并選擇執行語句。若表達式的值非0,則執行語句1,并結束雙分支選擇語句;否則執行語句2,并結束雙分支選擇語句。
注意;無論條件表達式的值為何值,只能執行語句1或語句2中的一個。當雙分文選擇語句中的else之后的語句2為空語句時,就變成單分支選擇語句。
單分文選擇語句和雙分支選擇語句統稱且語句。在if語句中的語句、語句1和語句2可以是任何語句。當它們中的某一個需用語句序列描述時,必須將這語句序列寫成復合語句。當它們中的某一個又是if語句時,就呈現嵌套的if語句形式。這時應注意else與if的對應關系。C語言約定else總是與它前面最接近的if對應。
為正確書寫if語句,特別說明以下幾點:
(1)若if語句中的語句、語句1、語句2是一個簡單語句,則這些簡單語句之后會有一個分號,這是C語言對這些簡單語句的要求。
(2)若if語句中的語句、語句l、語句2要用語句序列(即為順序結構)來實現,則必須將它們改寫成復合語句,即邏輯上把它們變成一個語句。
(3) 在if語句中,每個else總要與它前面的if對應,不可能出現沒有對應if的else。
多分支選擇語句
多分支選擇結構通常有 n(>2)個不同情況和 n+1個供選擇的分支。多分支選擇結構也可用前敘述的嵌套if語句來描述,但因if語句嵌套深度太多不便于程序編寫,也不便于理解,為此C語言專門提供了一種實現多分支選擇結構的語句,這就是switCh語句。它的一般形式是:
switeh(表達式){
case常量表達式 1:語句序列 1
case常量表達式 1:語句序列 2
case常量表達式 n:語句序列 n
defalt:語句序列 n+1
}
對switeh語句需說明以下幾點:
(1)switch后面括號內的表達式只限于是整型表達式或字符型表達式或枚舉型表達式。
(2)case后的常量表達式稱為情況前綴,要求所有常量表達式的值互不相同,并與switch后面括號內的表達式值的類型相一致。
(3)語句序列由任意條合法的C語句構成,也可以沒有語句。
(4)情況前綴default可以缺省,但至多出現一次,習慣總是將它寫在全部情況前綴之后,如有必要也可寫在某case之前。
switch語句的執行過程解釋如下:
先計算表達式的值,以該值依次與各case之后的常量表達式的值比較,按下列規則,選擇執行的入口:
如果表達式的值等于某個常量表達式的值,switch語句就從該常量表達式之后的語句序列的第一個語句開始執行,然后一直向下執行,或自動依次進入后繼常量表達式之后的語句序列繼續執行(如沒有 break語句),或執行完語句序列 n+1,結束 switch語句的執行;或在執行某個語句序列過程中遇到轉出該switch語句的語句(如break語句),就停止向下執行,結束switch語句的執行。
如果沒有相匹配的常量表達式,就從以default為情況前綴的語句序列開始執行。
如果沒有相匹配的常量表達式,也沒有defaul情況前綴,則該switch語句的這次執行立即結束。
由上述解釋可知,“case常量表達式”只是起語句序列入口的作用。在執行switch語句時,根據switch之后的表達式的值找到與該值匹配的入口,就從此人口處開始執行,只要未遇到轉出該switch語句的break語句或goto語句,就一直向下執行,也不再理會經過的case后的常量表達式。
如果要使各種情況互相排斥,僅執行各case所對應的語句序列,最常用的辦法是使用break語句,各語句序列都以break語句結束。在switch語句中,執行break語句將使控制轉向switch語句的后繼語句。
由于switch語句的表達式不允許是實型的,當應用于實型值選擇情況時,通常需作以下處理:將實表達式乘上一個適當的比例因子,使較大的實表達式值映照到一個較小的范圍上,然后再將它轉換到整型。
循環結構
循環計算用循環結構來描述。C語言提供三種描述不同循環結構的語句,它們是while語句、do-while語句和for語句。
1.while語句
while語句用來描述while型循環結構,它的一般形式為
while(表達式)
語句
while語句的執行過程是:
(1)計算while之后的表達式的值;
(2)測試表達式的值,當值為非 0時,轉步驟 3;如值為 0,則結束while語句;
(3)執行while語句的循環體,并轉步驟1(從而構成循環)。
一般來說,為使while語句的執行能正常結束,如控制循環的條件表達式包含有變量,循環體的執行應能更新這些變量的值,使表達式的值會變為0。有時,很難直接寫出while后的條件,這時可以簡單地寫上 1,而在循環體中含有當某條件滿足時,執行如 break語句那樣的控制轉移語句,使控制跳出while循環,即呈以下結構形式:
while(1){
...
if(表達式)break;
...
}:
2.do-while語句
do-while語句用來描述do-while型循環結構,它的一般形式為;
do
語句
while(表達式);
其中的語句是do-while語句的循環體。do-while語句的執行過程是:
(1)執行do-while語句的循環體;
(2)求 while之后的表達式的值;
(3)測試表達式的值,當值為非0,轉步驟1(從而構成循環);如值為0,則結束do-while語句。
與while語句一樣,當循環體由多個語句組成時,必須把它們書寫成復合語句。有些用while語句描述的循環計算,也能用do-while語句描述。然而,并非總是如此。兩者的重要區別在于:執行循環體時,對作為循環條件的表達式的求值和測試的時間不同。while語句對作為循環條件的表達式求值和測試在執行循環體之前,而do-While語句對作為循環條件的表達式求值和測試在執行循環體之后。對于do-while語句,它的循環體至少被執行一次,而while語句的循環體在作為循環條件的表達式值一開始就為0的情況下,就一次也未被執行。如能保證while語句中的作為循環條件的表達式在第一次被求值后,總是非0,則把該循環條件移至循環體執行之后求值和測試,能起同樣的控制作用。在這種情況下,while語句就能改寫成如while語句。如 while語句中的作為循環條件的表達式值可能初次求值就為 0時,則它不能簡單地改寫成do-while語句。另外要特別指出,分號是do-while語句的結束符,不能省略。
for語句
for語句是C語言中最靈活、使用最廣泛的循環結構語句。如以最一般意義下考慮循環,一個完整的循環應包含對有關變量賦初值部分、控制循環的條件、一個要循環計算的操作、每次循環后對有關變量的修正等四部分組成。拉語句就是從這一般意義下表達循環結構的語
句。for語句的一般形式為
for(表達式1;表達式2;表達式3)
語句
其中的語句是for語句的循環體。輸語句的執行過程是:
(1)計算表達式1;
(2)計算表達式 2的值,并測試其值為 0或非 0。若值為非 0,轉步驟 3;否則結束 for語句;
(3)執行循環體;
(4)計算表達式3;
(5)轉向步驟2。
for語句的一般形式也可等價地用以下形式的while語句來表達:
表達式1;
while(表達式2) {
語句
表達式3;
}
由for語句的執行過程可知,for語句的表達式1的作用是對控制循環的有關變量賦初值;表達式2是控制循環的條件;表達式3用于修正有關變量;語句是循環體。所以for語句按各部分的功能,可以形象地寫成以下形式:
for(賦初值的表達式;控制循環條件的表達式;修正變量的表達式)
完成循環計算的語句
正確使用for語句,需注意以下幾種情況:
(1) for語句的一般形式中,表達式1、表達式2和表達式3都可以省略。如表達式1省略,表示該for語句沒有賦初值部分,或前面的程序段已為有關變量賦了初值,或確實沒有特別的初值;如表達式2省略,表示循環條件永遠為真,可能循環體內有控制轉移語句轉出缺語句;表達式3省略,表示沒有修正部分,對變量的修正已在循環體內一起完成。不管表達式1、表達式2和表達式3省略情況如何,其中兩個分號都不能省略。對于三個表達式都省略情況,for語句呈以下形式:
for(;;)
語句
(2)表達式l、表達式2和表達式3都可包含逗號運算符由多個表達式組成。
4. break語句
break語句除能用于switch語句外,還常用于循環語句中。執行循環結構中的break語句,控制就從包含它的循環結構中退出。break語句通常與if語句結合,構成一個結束循環的條件。
5.continue語句
continue語句只用于循環語句中。通常復雜的循環計算中,循環語句的循環體是一個語句序列,中間會有一個包含continue語句的且語句。當指定的條件成立時,continue語句就被執行,這時continue語句之后的語句就不再執行,控制立即進入下一輪循環。
6. 語句標號和goto語句
C程序的語句之前都可插入標識符和冒號,該標識符即為其后語句的標號。如
strat:X= 0;
標識符Start就是語句“x=0;”的標號。
goto語句(goto標號;)是一種無條件轉移語句,其意義是將程序的控制轉到以所指定的標號命名的語句處。goto語句通常出現在if語句內,實現當某種條件出現時,需要改變正常的順序執行控制流程。由于goto語句過份的隨意使用會給程序的理解帶來很大的困難,所以一般強調不使用goto語句來編程。只有當一個多重循環的最內層,當發現某種特別的情況需要結束整個多重循環,這時可用goto語句讓程序執行從最內層直接轉到外層循環之外。注意,break語句只能跳出包含它的一層循環。
7.用goto語句構成循環
在早先非結構化程序設計中,由于語言提供的控制結構的結構性差,常用goto語句構成循環。但在結構化程序中,不再用goto語句構成循環。考生掌握這個知識是要求考生能將goto語句構成的循環改寫成結構化控制結構描述的循環。
【編輯推薦】