C語言程式設計本課介紹C語言程式設計的基本方法和基本的程式語句。從程式流程的角度來看,程式可以分為三種基本結構, 即順序結構、分支結構、迴圈結構。 這三種基本結構可以組成所有的各種複雜程式。C語言提供了多種語句來實現這些程式結構。 本章介紹這些基本語句及其應用,使讀者對C程式有一個初步的認識, 為後面各章的學習打下基礎。
工具/原料
記憶+理解
方法/步驟
C程式的語句C程式的執行部分是由語句組成的。 程式的功能也是由執行語句實現的。C語句可分為以下五類:1.表示式語句2.函式呼叫語句3.控制語句4.複合語句5.空語句
1.表示式語句表示式語句由表示式加上分號“;”組成。其一般形式為: 表示式; 執行表示式語句就是計算表示式的值。例如: x=y+z; 賦值語句y+z; 加法運算語句,但計算結果不能保留,無實際意義i++; 自增1語句,i值增1
2.函式呼叫語句由函式名、實際引數加上分號“;”組成。其一般形式為: 函式名(實際引數表); 執行函式語句就是呼叫函式體並把實際引數賦予函式定義中的形式引數,然後執行被調函式體中的語句,求取函式值。(在第五章函式中再詳細介紹)例如printf("C Program");呼叫庫函式,輸出字串。
3.控制語句控制語句用於控制程式的流程, 以實現程式的各種結構方式。它們由特定的語句定義符組成。C語言有九種控制語句。 可分成以下三類:(1) 條件判斷語句 if語句,switch語句(2) 迴圈執行語句 do while語句,while語句,for語句(3) 轉向語句 break語句,goto語句,continue語句,return語句
4.複合語句把多個語句用括號{}括起來組成的一個語句稱複合語句。 在程式中應把複合語句看成是單條語句,而不是多條語句,例如 {x=y+z;a=b+c;printf(“%d%d”,x,a);}是一條複合語句。複合語句內的各條語句都必須以分號“;”結尾,在括號“}”外不能加分號。
5.空語句只有分號“;”組成的語句稱為空語句。 空語句是什麼也不執行的語句。在程式中空語句可用來作空迴圈體。例如 while(getchar()!='\n'); 本語句的功能是,只要從鍵盤輸入的字元不是回車則重新輸入。這裡的迴圈體為空語句。
賦值語句賦值語句是由賦值表示式再加上分號構成的表示式語句。 其一般形式為: 變數=表示式; 賦值語句的功能和特點都與賦值表示式相同。 它是程式中使用最多的語句之一。 在賦值語句的使用中需要注意以下幾點:1.由於在賦值符“=”右邊的表示式也可以又是一個賦值表示式,因此,下述形式 變數=(變數=表示式); 是成立的,從而形成巢狀的情形。其展開之後的一般形式為: 變數=變數=…=表示式; 例如:a=b=c=d=e=5;按照賦值運算子的右接合性,因此實際上等效於: e=5;d=e;c=d;b=c;a=b;2.注意在變數說明中給變數賦初值和賦值語句的區別。給變數賦初值是變數說明的一部分,賦初值後的變數與其後的其它同類變數之間仍必須用逗號間隔,而賦值語句則必須用分號結尾。 3.在變數說明中,不允許連續給多個變數賦初值。 如下述說明是錯誤的: int a=b=c=5 必須寫為 int a=5,b=5,c=5; 而賦值語句允許連續賦值4.注意賦值表示式和賦值語句的區別。賦值表示式是一種表示式,它可以出現在任何允許表示式出現的地方,而賦值語句則不能。下述語句是合法的: if((x=y+5)>0) z=x; 語句的功能是,若表示式x=y+5大於0則z=x。下述語句是非法的: if((x=y+5;)>0) z=x; 因為=y+5;是語句,不能出現在表示式中。
資料輸出語句本小節介紹的是向標準輸出裝置顯示器輸出資料的語句。在C語言中,所有的資料輸入/輸出都是由庫函式完成的。 因此都是函式語句。本小節先介紹printf函式和putchar函式。printf函式printf函式稱為格式輸出函式,其關鍵字最末一個字母f即為“格式”(format)之意。其功能是按使用者指定的格式, 把指定的資料顯示到顯示器螢幕上。在前面的例題中我們已多次使用過這個函式。
一、printf函式呼叫的一般形式printf函式是一個標準庫函式,它的函式原型在標頭檔案“stdio.h”中。但作為一個特例,不要求在使用 printf 函式之前必須包含stdio.h檔案。printf函式呼叫的一般形式為: printf(“格式控制字串”,輸出表列)其中格式控制字串用於指定輸出格式。 格式控制串可由格式字串和非格式字串兩種組成。格式字串是以%開頭的字串,在%後面跟有各種格式字元,以說明輸出資料的型別、形式、長度、小數位數等。如“%d”表示按十進位制整型輸出,“%ld”表示按十進位制長整型輸出,“%c”表示按字元型輸出等。後面將專門給予討論。非格式字串在輸出時原樣照印,在顯示中起提示作用。 輸出表列中給出了各個輸出項, 要求格式字串和各輸出項在數量和型別上應該一一對應。void main(){int a=88,b=89;printf("%d %d\n",a,b);printf("%d,%d\n",a,b);printf("%c,%c\n",a,b);printf("a=%d,b=%d",a,b);}a<--8,b<--89
printf("%d %d\n",a,b);printf("%d,%d\n",a,b);printf("%c,%c\n",a,b);printf("a=%d,b=%d",a,b);本例中四次輸出了a,b的值,但由於格式控制串不同,輸出的結果也不相同。第四行的輸出語句格式控制串中,兩格式串%d 之間加了一個空格(非格式字元),所以輸出的a,b值之間有一個空格。第五行的printf語句格式控制串中加入的是非格式字元逗號, 因此輸出的a,b值之間加了一個逗號。第六行的格式串要求按字元型輸出 a,b值。第七行中為了提示輸出結果又增加了非格式字串。
二、格式字串在Turbo C中格式字串的一般形式為: [標誌][輸出最小寬度][.精度][長度]型別 其中方括號[]中的項為可選項。各項的意義介紹如下:1.型別型別字元用以表示輸出資料的型別,其格式符和意義下表所示:表示輸出型別的格式字元 格式字元意義d 以十進位制形式輸出帶符號整數(正數不輸出符號)o 以八進位制形式輸出無符號整數(不輸出字首O)x 以十六進位制形式輸出無符號整數(不輸出字首OX)u 以十進位制形式輸出無符號整數f 以小數形式輸出單、雙精度實數e 以指數形式輸出單、雙精度實數g 以%f%e中較短的輸出寬度輸出單、雙精度實數c 輸出單個字元s 輸出字串2.標誌標誌字元為-、+、#、空格四種,其意義下表所示: 標誌格式字元 標 志 意 義- 結果左對齊,右邊填空格+ 輸出符號(正號或負號)空格輸出值為正時冠以空格,為負時冠以負號# 對c,s,d,u類無影響;對o類, 在輸出時加字首o 對x類,在輸出時加字首0x;對e,g,f 類當結果有小數時才給出小數點3.輸出最小寬度用十進位制整數來表示輸出的最少位數。 若實際位數多於定義的寬度,則按實際位數輸出, 若實際位數少於定義的寬度則補以空格或0。4.精度精度格式符以“.”開頭,後跟十進位制整數。本項的意義是:如果輸出數字,則表示小數的位數;如果輸出的是字元, 則表示輸出字元的個數;若實際位數大於所定義的精度數,則截去超過的部分。5.長度長度格式符為h,l兩種,h表示按短整型量輸出,l表示按長整型量輸出。void main(){int a=15;float b=138.3576278;double c=35648256.3645687;char d='p';printf("a=%d,%5d,%o,%x\n",a,a,a,a);printf("b=%f,%lf,%5.4lf,%e\n",b,b,b,b);printf("c=%lf,%f,%8.4lf\n",c,c,c);printf("d=%c,%8c\n",d,d);} a<--15b<--138.3576278c<--35648256.3645687d<--'p'main(){int a=29;float b=1243.2341;double c=24212345.24232;char d='h';printf("a=%d,%5d,%o,%x\n",a,a,a,a);printf("b=%f,%lf,%5.4lf,%e\n",b,b,b,b);printf("c=%lf,%f,%8.4lf\n",c,c,c);printf("d=%c,%8c\n",d,d);} 本例第七行中以四種格式輸出整型變數a的值,其中“%5d ”要求輸出寬度為5,而a值為15只有兩位故補三個空格。 第八行中以四種格式輸出實型量b的值。其中“%f”和“%lf ”格式的輸出相同,說明“l”符對“f”型別無影響。“%5.4lf”指定輸出寬度為5,精度為4,由於實際長度超過5故應該按實際位數輸出,小數位數超過4位部分被截去。第九行輸出雙精度實數,“%8.4lf ”由於指定精度為4位故截去了超過4位的部分。第十行輸出字元量d,其中“%bc ”指定輸出寬度為8故在輸出字元p之前補加7個空格。使用printf函式時還要注意一個問題, 那就是輸出表列中的求值順序。不同的編譯系統不一定相同,可以從左到右, 也可從右到左。Turbo C是按從右到左進行的。如把例2.13改寫如下述形式:void main(){int i=8;printf("%d\n%d\n%d\n%d\n%d\n%d\n",++i,--i,i--,i++,-i--);} i<--8這個程式與例2.13相比只是把多個printf語句改一個printf 語句輸出。但從結果可以看出是不同的。為什麼結果會不同呢?就是因為printf函式對輸出表中各量求值的順序是自右至左進行 的。在式中,先對最後一項“-i--”求值,結果為-8,然後i自減1後為7。 再對“-i++”項求值得-7,然後i自增1後為8。再對“i--”項求值得8,然後i再自減1後為7。再求“i++”項得7,然後I再自增1後為8。 再求“--i”項,i先自減1後輸出,輸出值為7。 最後才求輸出表列中的第一項“++i”,此時i自增1後輸出8。但是必須注意, 求值順序雖是自右至左,但是輸出順序還是從左至右, 因此得到的結果是上述輸出結果。字元輸出函式putchar 函式putchar 函式是字元輸出函式, 其功能是在顯示器上輸出單個字元。其一般形式為: putchar(字元變數) 例如:putchar('A'); 輸出大寫字母Aputchar(x); 輸出字元變數x的值putchar('\n'); 換行 對控制字元則執行控制功能,不在螢幕上顯示。 使用本函式前必須要用檔案包含命令:#include
分支結構程式 關係運算符和表示式在程式中經常需要比較兩個量的大小關係, 以決定程式下一步的工作。比較兩個量的運算子稱為關係運算符。 在C語言中有以下關係運算符:< 小於<= 小於或等於 > 大於>= 大於或等於== 等於!= 不等於 關係運算符都是雙目運算子,其結合性均為左結合。 關係運算符的優先順序低於算術運算子,高於賦值運算子。 在六個關係運算符中,<,<=,>,>=的優先順序相同,高於==和!=,==和!=的優先順序相同。關係表示式關係表示式的一般形式為: 表示式 關係運算符 表示式 例如:a+b>c-d,x>3/2,'a'+1
if語句用if語句可以構成分支結構。它根據給定的條件進行判斷, 以決定執行某個分支程式段。C語言的if語句有三種基本形式。
1.第一種形式為基本形式 if(表示式) 語句; 其語義是:如果表示式的值為真,則執行其後的語句, 否則不執行該語句。其過程可表示為下圖void main(){int a,b,max;printf("\n input two numbers: ");scanf("%d%d",&a,&b);max=a;if (max
本例程式中,輸入兩個數a,b。把a先賦予變數max,再用if語句判別max和b的大小,如max小於b,則把b賦予max。因此max中總是大數,最後輸出max的值。2.第二種形式為if-else形式 if(表示式) 語句1; else 語句2;其語義是:如果表示式的值為真,則執行語句1,否則執行語句2 。void main(){int a, b;printf("input two numbers: ");scanf("%d%d",&a,&b);if(a>b)printf("max=%d\n",a);elseprintf("max=%d\n",b);}輸入兩個整數,輸出其中的大數。改用if-else語句判別a,b的大小,若a大,則輸出a,否則輸出b。3.第三種形式為if-else-if形式前二種形式的if語句一般都用於兩個分支的情況。 當有多個分支選擇時,可採用if-else-if語句,其一般形式為: if(表示式1) 語句1; else if(表示式2) 語句2; else if(表示式3) 語句3; … else if(表示式m) 語句m; else 語句n; 其語義是:依次判斷表示式的值,當出現某個值為真時, 則執行其對應的語句。然後跳到整個if語句之外繼續執行程式。 如果所有的表示式均為假,則執行語句n 。 然後繼續執行後續程式。 if-else-if語句的執行過程如圖3—3所示。#include"stdio.h"void main(){char c;printf("input a character: ");c=getchar();if(c<32)printf("This is a control character\n");else if(c>='0'&&c<='9')printf("This is a digit\n");else if(c>='A'&&c<='Z')printf("This is a capital letter\n");else if(c>='a'&&c<='z')printf("This is a small letter\n");elseprintf("This is an other character\n");}本例要求判別鍵盤輸入字元的類別。可以根據輸入字元的ASCII碼來判別型別。由ASCII碼錶可知ASCII值小於32的為控制字元。 在“0”和“9”之間的為數字,在“A”和“Z”之間為大寫字母, 在“a”和“z”之間為小寫字母,其餘則為其它字元。 這是一個多分支選擇的問題,用if-else-if語句程式設計,判斷輸入字元ASCII碼所在的範圍,分別給出不同的輸出。例如輸入為“g”,輸出顯示它為小寫字元。4.在使用if語句中還應注意以下問題(1) 在三種形式的if語句中,在if關鍵字之後均為表示式。 該表示式通常是邏輯表示式或關係表示式, 但也可以是其它表示式,如賦值表示式等,甚至也可以是一個變數。例如: if(a=5) 語句;if(b) 語句; 都是允許的。只要表示式的值為非0,即為“真”。如在if(a=5)…;中表達式的值永遠為非0,所以其後的語句總是要執行的,當然這種情況在程式中不一定會出現,但在語法上是合法的。又如,有程式段: if(a=b)printf("%d",a);elseprintf("a=0"); 本語句的語義是,把b值賦予a,如為非0則輸出該值,否則輸出“a=0”字串。這種用法在程式中是經常出現的。(2) 在if語句中,條件判斷表示式必須用括號括起來, 在語句之後必須加分號。(3) 在if語句的三種形式中,所有的語句應為單個語句,如果要想在滿足條件時執行一組(多個)語句,則必須把這一組語句用{} 括起來組成一個複合語句。但要注意的是在}之後不能再加分號。例如:if(a>b){a++;b++;}else{a=0;b=10;}if語句的巢狀當if語句中的執行語句又是if語句時,則構成了if 語句巢狀的情形。其一般形式可表示如下: if(表示式) if語句; 或者為if(表示式) if語句; else if語句; 在巢狀內的if語句可能又是if-else型的,這將會出現多個if和多個else重疊的情況,這時要特別注意if和else的配對問題。例如:if(表示式1)if(表示式2)語句1;else語句2;其中的else究竟是與哪一個if配對呢?應該理解為: 還是應理解為: if(表示式1) if(表示式1) if(表示式2) if(表示式2) 語句1; 語句1;else else 語句2; 語句2; 為了避免這種二義性,C語言規定,else 總是與它前面最近的if配對,因此對上述例子應按前一種情況理解。比較兩個數的大小關係。void main(){int a,b;printf("please input A,B: ");scanf("%d%d",&a,&b);if(a!=b)if(a>b) printf("A>B\n");else printf("A B、A b) printf("A>B\n");else printf("A
條件運算子和條件表示式如果在條件語句中,只執行單個的賦值語句時, 常可使用條件表示式來實現。不但使程式簡潔,也提高了執行效率。條件運算子為?和:,它是一個三目運算子,即有三個參與運算的量。由條件運算子組成條件表示式的一般形式為:表示式1? 表示式2: 表示式3 其求值規則為:如果表示式1的值為真,則以表示式2 的值作為條件表示式的值,否則以表示式2的值作為整個條件表示式的值。 條件表示式通常用於賦值語句之中。例如條件語句: if(a>b) max=a;else max=b;可用條件表示式寫為 max=(a>b)?a:b; 執行該語句的語義是:如a>b為真,則把a賦予max,否則把b 賦予max。使用條件表示式時,還應注意以下幾點:1. 條件運算子的運算優先順序低於關係運算符和算術運算子,但高於賦值符。因此 max=(a>b)?a:b可以去掉括號而寫為 max=a>b?a:b2. 條件運算子?和:是一對運算子,不能分開單獨使用。3. 條件運算子的結合方向是自右至左。例如:a>b?a:c>d?c:d應理解為a>b?a:(c>d?c:d) 這也就是條件表示式巢狀的情形,即其中的表示式3又是一個條件表示式。void main(){int a,b,max;printf("\n input two numbers: ");scanf("%d%d",&a,&b);printf("max=%d",a>b?a:b);}用條件表示式對上例重新程式設計,輸出兩個數中的大數。switch語句C語言還提供了另一種用於多分支選擇的switch語句, 其一般形式為: switch(表示式){ case常量表達式1: 語句1; case常量表達式2: 語句2; … case常量表達式n: 語句n; default : 語句n+1; } 其語義是:計算表示式的值。 並逐個與其後的常量表達式值相比較,當表示式的值與某個常量表達式的值相等時, 即執行其後的語句,然後不再進行判斷,繼續執行後面所有case後的語句。 如表示式的值與所有case後的常量表達式均不相同時,則執行default後的語句。void main(){int a;printf("input integer number: ");scanf("%d",&a);switch (a){ case 1:printf("Monday\n");case 2:printf("Tuesday\n");case 3:printf("Wednesday\n");case 4:printf("Thursday\n");case 5:printf("Friday\n");case 6:printf("Saturday\n");case 7:printf("Sunday\n");default:printf("error\n");}}
本程式是要求輸入一個數字,輸出一個英文單詞。但是當輸入3之後,卻執行了case3以及以後的所有語句,輸出了Wednesday 及以後的所有單詞。這當然是不希望的。為什麼會出現這種情況呢?這恰恰反應了switch語句的一個特點。在switch語句中,“case 常量表達式”只相當於一個語句標號, 表示式的值和某標號相等則轉向該標號執行,但不能在執行完該標號的語句後自動跳出整個switch 語句,所以出現了繼續執行所有後面case語句的情況。 這是與前面介紹的if語句完全不同的,應特別注意。為了避免上述情況, C語言還提供了一種break語句,專用於跳出switch語句,break 語句只有關鍵字break,沒有引數。在後面還將詳細介紹。修改例題的程式,在每一case語句之後增加break 語句, 使每一次執行之後均可跳出switch語句,從而避免輸出不應有的結果。void main(){int a;printf("input integer number: ");scanf("%d",&a);switch (a){case 1:printf("Monday\n");break;case 2:printf("Tuesday\n"); break;case 3:printf("Wednesday\n");break;case 4:printf("Thursday\n");break;case 5:printf("Friday\n");break;case 6:printf("Saturday\n");break;case 7:printf("Sunday\n");break;default:printf("error\n");}}在使用switch語句時還應注意以下幾點:1.在case後的各常量表達式的值不能相同,否則會出現錯誤。2.在case後,允許有多個語句,可以不用{}括起來。3.各case和default子句的先後順序可以變動,而不會影響程式執行結果。4.default子句可以省略不用。程式舉例輸入三個整數,輸出最大數和最小數。void main(){int a,b,c,max,min;printf("input three numbers: ");scanf("%d%d%d",&a,&b,&c);if(a>b){max=a;min=b;}else{max=b;min=a;}if(max
本程式中,首先比較輸入的a,b的大小,並把大數裝入max, 小數裝入min中,然後再與c比較,若max小於c,則把c賦予max;如果c小於min,則把c賦予min。因此max內總是最大數,而min內總是最小數。最後輸出max和min的值即可。 計算器程式。使用者輸入運算數和四則運算子, 輸出計算結果。void main(){float a,b,s;char c;printf("input expression: a+(-,*,/)b \n");scanf("%f%c%f",&a,&c,&b);switch(c){case '+': printf("%f\n",a+b);break;case '-': printf("%f\n",a-b);break;case '*': printf("%f\n",a*b);break;case '/': printf("%f\n",a/b);break;default: printf("input error\n");}}本例可用於四則運算求值。switch語句用於判斷運算子, 然後輸出運算值。當輸入運算子不是+,-,*,/時給出錯誤提示。
迴圈結構程式迴圈結構是程式中一種很重要的結構。其特點是, 在給定條件成立時,反覆執行某程式段,直到條件不成立為止。 給定的條件稱為迴圈條件,反覆執行的程式段稱為迴圈體。 C語言提供了多種迴圈語句,可以組成各種不同形式的迴圈結構。
while語句while語句的一般形式為: while(表示式)語句; 其中表達式是迴圈條件,語句為迴圈體。while語句的語義是:計算表示式的值,當值為真(非0)時, 執行迴圈體語句。其執行過程可用圖3—4表示。 統計從鍵盤輸入一行字元的個數。#include
do-while語句do-while語句的一般形式為: do語句; while(表示式); 其中語句是迴圈體,表示式是迴圈條件。do-while語句的語義是:先執行迴圈體語句一次, 再判別表示式的值,若為真(非0)則繼續迴圈,否則終止迴圈。do-while語句和while語句的區別在於do-while是先執行後判斷,因此do-while至少要執行一次迴圈體。而while是先判斷後執行,如果條件不滿足,則一次迴圈體語句也不執行。while語句和do-while語句一般都可以相互改寫。void main(){int a=0,n;printf("\n input n: ");scanf("%d",&n);do printf("%d ",a++*2);while (--n);} 在本例中,迴圈條件改為--n,否則將多執行一次迴圈。這是由於先執行後判斷而造成的。對於do-while語句還應注意以下幾點:1.在if語句,while語句中, 表示式後面都不能加分號, 而在 do-while語句的表示式後面則必須加分號。2.do-while語句也可以組成多重迴圈,而且也可以和while語句相互巢狀。3.在do和while之間的迴圈體由多個語句組成時,也必須用{}括起來組成一個複合語句。4.do-while和while語句相互替換時,要注意修改迴圈控制條件。
注意事項
理論比較多,要經常看看,也可收藏