文章程式碼顯示

2017年11月11日 星期六

《筆記》C語言 - 03:條件運算子、while 重複敘述式、強制轉型、算數指定運算子、遞增遞減運算子


條件運算子

  前一章有提到使用 if ... else 的結構來進行判斷數值的大小,很多時候這樣的判斷都會在程式中不斷出現,所以在C語言中有一個更簡潔的寫法,稱為條件運算子(conditional operator ?: ) 。條件運算子是 C 中唯一的三元運算子,用法如下

#include "stdio.h"

int main(void) {
setvbuf(stdout,NULL,_IONBF,0);

 int grade;

 printf("Enter your grade : \n");
 scanf("%d", &grade);
 printf( "%s\n", grade >= 60? "Passed" : "Failed" );
}






此意思為,成績是否大於 60 分? 是的話顯示 Passed , 否的話顯示 Failed


while 重複敘述式

  重複敘述式可以讓條件為"成立"(或稱條件為"真(True)") 時,重複執行同一項動作

#include "stdio.h"

int main(void) {
//setvbuf(stdout,NULL,_IONBF,0);

 int counter = 0;

 while( counter < 5){
  printf("%d\n", counter);
  counter = counter +1 ;
 }

 return 0;
}



首先我們定義了一個整數型態的變數,名稱為 counter 並且令其初始值為 0,然後使用了 while 重複敘述式(我比較習慣稱其為 while 迴圈),由於我們的判斷條件為 counter < 5 ,所以一開始時條件是成立的,會進入 while 迴圈內的區塊。

在列印顯示出 counter 的值後,我們將 counter 的值加 1 並且把它丟回到 counter 裡面。

在第 10 行的敘述句,此處我們要有的概念是電腦會先完成等號右邊的算術,在將值丟到右邊的變數內。

學會了 while 函數後我們來實作一個計算全班平均分數的問題

#include "stdio.h"

int main(void) {
setvbuf(stdout,NULL,_IONBF,0);

 int grade = 0;
 int counter = 0;
 int grade_total = 0;
 float average = 0;

 while( grade != -1 ){
  printf( "Enter grade (-1 means end) : " );
  scanf( "%d", &grade );
  if(grade != -1){
   counter = counter +1;
   grade_total = grade_total + grade;
  }
 }

 average = (float)grade_total / counter ;
 printf( "Average grade is : %.2f\n", average );

 return 0;
}



程式中:

第 4 行:編譯器缺陷,忽略。

第 6-9 行:在這四行中我們宣告了四個不同名稱的變數,其初始值都為零。但其中有一個變數的型別(type) 我們宣告成 float 而不是 int ,因我們之前說過 int 是整數型態,僅能存取整數值,而當我們宣告成 float 時才能存取小數點的數值,帶小數點的數字在 C 中我們稱它為"浮點數"。

注意 : 這不代表為了方便我們就將所有不需要存取小數點的變數也都宣告成 float ,這有可能會造成莫名且難以察覺的錯誤結果,正確的為變數賦予它該有的型別(type) 才是比較好的設計習慣。

第 11 行:在這行中我們使用了 while 迴圈,且其判斷式為 grade 不等於 -1 。此處的 -1 我們用來當作結束迴圈的條件。

可能有人已經發現到這樣設計的目的了,在前面的例子中我們可以直接確定 while 的迴圈執行次數,此種稱為「明確重複」;但在這個新的例子中我們並沒有辦法在程式撰寫的時候就知道迴圈執行次數,因為我們想要讓使用者可以輸入很多筆成積,並且最後將其取平均,此種則稱為「非明確重複」。

第 15 行:變數 counter 記錄了總共有幾筆成積被輸入。

第 16 行:將每次輸入的成積進行加總,並且丟到變數 grade_total 裡面。

第 20 行:因為我們不知道加總過後的總成績與成績個數相除後會不會出現小數點,所以我們在宣告 average 變數時就先宣告為具有小數點的"浮點數資料形態"

grade_total 及 counter 本身是整數型態(int),在C語言中,兩個整數型態的數值相除,其結果若有小數點則會被"捨棄"。因此當這個相除的運算執行後,小數點的部分將會被捨去,此時我們將值丟給 average 後就只會剩下整數的部分。為了能夠正確的保留計算結果的小數,我們必須製造一個"暫時"的浮點數

C 語言中提供了強制型別轉換運算子( cast operator) 功能,當我們使用如 (float) 這樣的敘述時,C 在內部會為後方的變數 grade_total 產生一個 "暫時" 的浮點數型態拷貝,但原本存放在 grade_total 的值仍然是整數型態。

這是一個神奇的地方,大多數的電腦只能執行運算元型別相同的運算式,為了確保型別相同,編譯器會自動對某些運算元執行一種稱為提升(promotion)的動作。例如在 int 和 float 型別的運算式中, ANSI標準規定對 int 的運算元複製並提升為 float,然後進行兩個浮點數的相除。

簡而言之,以此例來說當我們使用 "強制型別轉換運算子" 的功能時,若兩個値都是整數型態則會將兩個値都進行複製變成浮點數,其中一個値是由強制轉換得來的,另一個値是由編譯器 promotion 得來的。

第 21 行:%.2f 代表將有浮點數會被顯示列印,且顯示到小數點第二位。


最後補充一下算數指定運算子以及遞增遞減運算子

算數指定運算子

c+=7  等效於   c = c+7
c-=7  等效於   c = c-7
c*=7  等效於   c = c*7
c/=7  等效於   c = c/7
c%=7  等效於   c = c%7

遞增遞減運算子

a++  先將 a 遞增1,再以 a 的新值進行運算。等效於 a = a+1 及 a+=1
++a  以 a 目前的值進行運算,再將 a 遞增1
b--  先將 b 遞減1,再以 b 的新值進行運算
--b  以 b 目前的值進行運算,再將 b 遞減1

↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引