if else 語句的通用形式爲:git
if (expression)express
statement1編程
else函數
statement2性能
若是expression爲真(非零),就執行statement1;若是expression爲假或零,則執行跟在else後的那一條語句(statement2)。測試
若是但願在if和else之間有多條語句,必須使用花括號建立一個代碼塊。ui
if語句使您可以選擇是否執行某個動做。if else語句使您能夠在兩個動做之間進行選擇。spa
7.2.1 另外一個例子:介紹getchar()和putchar()設計
如今咱們將接觸專門 爲面向字符I/O而設計的一對C函數:getchar()和putchar()。code
getchar()函數沒有參數,它返回來自輸入設備的下一個字符。
ch=getchar();與scanf("%c",&ch);有一樣的效果。
putchar()函數打印它的參數。例如,下面的語句將先前賦值給ch的值做爲字符打印出來:
putchar(ch);
該語句與printf("%c",ch);有一樣的效果。
由於這些函數僅僅處理字符,因此它們比更通用的scanf()和printf()函數更快並且更簡潔。一樣,注意到它們不須要格式說明符,由於它們只對字符 起做用。
這兩個函數一般都是在stdio.h文件中定義的。
下面的示例將說明這些函數是如何工做的,「若是字符 是空格,打印之;不然,打印它們在ASCII序列中的下一個字符」。
程序清單7.2 cypher1.c 程序
/*cypher1.c --改變輸入,只保留其中的空格*/ #include #define SPACE ' ' /*SPACE至關於「引號-空格-引號」*/ int main(void) { char ch; ch=getchar(); /*讀入一個字符*/ while(ch!='\n') /*當一行未結束時*/ { if(ch==SPACE) putchar(ch); else putchar(ch+1); ch=getchar(); } putchar(ch); /*換行打印字符*/ return 0; } /*下面是一個運行示例: CALL ME HAL. DBMM NF IBM/ */
C靈活的語法使您能夠經過將讀取和判斷合併爲單個表達來仿效程序清單7.1。就是說,您能夠把這種形式的循環:
ch=getchar();
while(ch!='\n')
{
...
ch=getchar();
}
替換爲下面的形式:
while((ch=getchar())!='\n')
{
....
}
關鍵的一行是while( (ch=getchar()) != '\n' )
這體現了c的編程風格:將兩個動做合併爲一個表達式。
圓括號是必須的,由於!=的優先級要比=的高。
putchar(ch+1)再次證實了字符其實是做爲整數存儲的。
7.2.2 ctype.h系列字符函數
ctype.h頭文件包含了一些能夠用來分析字符的函數的原型。這些函數接受一個字符做爲參數,若是該字符 屬於某特定的種類則返回非零值(真),不然返回零(假)。
例如,若是isalpha()函數的參數是一個字母,則它返回一個非零值。程序清單7.3經過使用該函數擴展了程序清單7.2。
程序清單7.3 cypher2.c
#include #include int main (void) { char ch; while((ch=getchar())!='\n') { if(isalpha(ch)) //若是是一個字母 putchar(ch+1); //則改變它 else //不然 putchar(ch); //原樣打印它 } putchar(ch); //打印換行符 return 0; }
表7.1 ctype.h的字符判斷函數
函數名 | 爲以下參數時,返回值爲真 |
isalnum() | 字母或數字 |
isalpha() | 字母 |
isblank() | 一個標準的空白字符(空格、水平製表符、或換行) |
iscntrl() | 控制符,例如ctrl+B |
isdigit() | 阿拉伯數字 |
isgraph() | 除空格外的全部可打印字符 |
islower() | 小寫字母 |
isprint() | 可打印字符 |
ispunct() | 標點符號(除空格和字母數字外的可打印字符) |
isspace() | 空白字符 |
isupper() | 大寫字母 |
isxdigit() | 十六進制數字字符 |
表7.2 ctype.h的字符映射函數
函數名 | 動做 |
tolower() | 返回參數的小寫字符 |
toupper() | 返回參數的大寫字符 |
7.2.3 多重選擇else if
平常生活中,常常會給咱們提供兩個以上的選擇。
程序清單7.4 electric.c
/*electric.c --計算用電賬目*/ #include #define RATE1 0.12589 /*第1 個360KWH的費率*/ #define RATE2 0.17901 /*下一個320KWH的費率*/ #define RATE3 0.20971 /*超過680KWH的費率*/ #define BREAK1 360.0 /*費率的第一個分界點*/ #define BREAK2 680.0 /*費率的第二個分界點*/ #define BASE1 (RATE1*BREAK1) /*用電360KWH的費用*/ #define BASE2 (BASE1+(RATE2*(BREAK2-BREAK1))) /*用電680KWH的費用*/ int main (void) { double kwh; /*用電的千瓦小時數*/ double bill; /*費用*/ printf("Please enter the kwh used.\n"); scanf("%lf",&kwh); /*%lf是double類型的說明符*/ if(kwh<=BREAK1) bill = RATE1 * kwh; else if (kwh <= BREAK2) /*用電量在360-680kwh之間*/ bill = BASE1 + (RATE2 * (kwh-BREAK1)); else /*用電超出680kwh時*/ bill = BASE2 + (RATE3 * (kwh-BREAK2)); printf("The charge for %.1f kwh is $1.2f.\n",kwh,bill); return 0; }
程序清單7.4用符號常量表示費率,以便這些常量能夠很方便的被放置在一塊兒。該清單也用 符號表示了費率的分界點。BASE1和BASE2根據費率和分界點來表示。這樣,若是費率或分界點改變了,它們也會自動的更新。您可能回想起預處理器是不作計算的,程序中BASE1出現的地方將使用0.12589*360.0代替。不用擔憂,編譯器會求得該表達式的數值(45.3204)以便最終的程序代碼使用45.3204而不是一個計算表達式。
程序的流程簡單明瞭。應該特別注意的是僅當KWH大於360時程序纔到達第一個else。因此,像程序註釋的那樣,else if 行實際上至關於要求kwh在360和680之間。一樣僅當kwh超過680才能到達最後一個else。
說到編譯器的嵌套限制,C99標準要求編譯器最少支持127層嵌套。
7.2.4 把else 與 if 配對
當有衆多的if和else的時候 ,計算機是怎樣判斷哪一個if對應哪一個else的?
規則是若是沒有花括號指明,else與和它最接近的一個if相匹配。
7.2.5 多層嵌套的if
前面所看到的if...else if...else序列是嵌套if的一種形式,這是從一系列的二選一中進行選擇的。當進行了特定的選擇後又致使了額外的選擇時將使用另外一種嵌套if。
咱們試着用這種形式的嵌套if來解決下面的問題:給定一個整數,顯示全部能整除它的約數;若是沒有約數,則報告該數是個素數。
首先,對程序進行總體設計,爲了方便,程序須要用一個循環來使您能輸入被測試的數。
下一步,須要 計劃怎麼來找到除數。或許最顯而易見的方法是這樣的:
for(dir=2;div
if(num%div==0)
printf("%d is divisible by %d\n",num,div);
該循環檢查界於2到num之間的全部數,看它們是否能夠整除num。不幸的是這樣浪費了計算機的時間。咱們能夠作的更好。例如,考慮搜索144的約數。能夠發現144%2爲0,這意味着144能被2整除。若是明確的拿144除以2,能夠獲得72,這也是一個約數,所以一次成功的num%div測試能夠獲得兩個約數而不是一個。然而,真正的性能指標在於循環測試界限的改變。
爲了弄清這是怎麼工做的,看一下循環中所獲得的成對的約數:2和7二、3和4八、4和3六、6和2四、8和1八、9和1六、12和十二、16和九、18和8等。哦,在獲得12和12這對約數後,又開始獲得與已找到的相同的約數(以相反的次序)。無須循環到143,在達到12後就能夠中止。這就節省 了大量的循環週期。
概括之後,能夠肯定必須測試的數只要到num的平方根就能夠了,而沒必要到num。對於像9這樣的數,這並不會節省不少時間,但對於像10000這樣的數,差異就很大了。然而,咱們沒必要在程序中計算平方根,而是像下面這樣描述判斷條件:
for (div=2;(div*div)<=num;div++)
if(num%div==0)
printf("%d is divisible by %d and %d.\n",num,div,num / div);
若是num爲144,循環運行到div=12終止。若是Num爲145,循環運行到div=13終止。
咱們還須要提出兩個問題,而後才能準備開始編程。第一,若是測試的數是一個徹底平方數怎麼辦?報告144可被12和12整除顯然有些愚蠢,但能夠用嵌套if語句來判斷div是否等於num / div。若是是,程序將只打印一個約數,而不是兩個。
for (div = 2;(div*div)<=num;div++)
{
if(num % div == 0)
{
if(div*div!=num)
printf( "%d is divisible by %d\n",num,div);
else
printf("%d is divisible by %d.\n",num,div);
}
}
第二,怎麼知道一個數是素數呢?若是一個數是素數,程序永遠也進不了if語句。爲了解決這個問題,能夠在循環外設置一個變量爲某一值,比方說1,在if語句中將這個變動重設爲0.那麼循環完成後,檢查該變量是否仍然是1.若是是,則歷來沒有進入過if語句,這個數是素數。
這樣的變量一般稱爲標誌(flag)。
傳統上,C習慣了用Into類型做爲標誌,可是新型的_Bool型變量極佳地符合了這種需求。並且經過使用stdbool.h頭文件,能夠用bool代替_Bool表示這種類型,並用標識符true和false代替1和0.
程序清單 7.5 divisors.c
//divisors.c --使用嵌套if顯示一個數的約數 #include <stdio.h> #include <stdbool.h> int main(void) { unsigned long num; //要檢查的數 unsigned long div; //可能的約數 bool isprime; //素數的標誌 printf("Please enter an integer for analysis:"); printf("Enter q to quit.\n"); while(scanf("%lu",&num)==1) { for(div=2,isprime=true;(div*div)<=num;div++) { if(num % div == 0) { if((div*div)!=num) printf("%lu is divisible by %lu and %lu.\n",num,div,num / div ); else printf("%lu is divisible by %lu.\n",num,div); isprime=false; //不是一個素數 } } if(isprime) printf("%lu is prime.\n",num); printf("Please enter another integer for analysis;"); printf("Enter q to quit.\n"); } printf("Bye.\n"); return 0; }
這個程序將會把1判斷爲素數,而實際上1不是素數。下一部分將要介紹的邏輯運算符將使你可以把1排除在外。