---
# System prepended metadata

title: 4.C Program Control
tags: [學校門口大樹石頭下, 程設好難, 他的課就很好睡阿]

---

4.C Program Control
==
# 4.1-4.2 Iteration Essentials
* 迴圈（looping）是指當一個迴圈繼續條件式（looping-continuation condition）持續為真時，電腦重複執行的一指令。
* 兩種循環方式
 1. 計數器控制循環（conter-  control iteration)
 --迴圈執行前就明確知道循環次數，所以又稱為明確的循環（definite iteration)
 --使用控制變數（control variable)來計算循環次數
2. 警示值控制循環（sential value)
 --事先不知道迴圈需循環多少次，又稱為非明確循環（indefinite iteration）
 --若不能事先知道循環次數或迴圈內含有一個每次迴圈執行都會取得的資料的敘述式，就要使用警示值。
 --警示值表示資料結束。警示值會在所有正是資料向都輸入後，才會輸入到程式當中。警示值必須與其他正式資料項不同。
 
# 4.3 Counter-Controll Iteration
* 計數器控制循環所需東東
1. name(名稱)
2. initial value（初始值）
3. increment（遞增量）or decrement（遞減量）(白話點就是每圈迴圈結束後會做什麼)
4. final value(終止值)的條件


# 4.4 for Iteration
* for的一般格式組成
```c=
for(initalization; condition; increment){
    statement  
｝
```
1. initialization為迴圈的初始值，condition是迴圈進行的條件，increment則會在最後遞增或遞減control variable，statement則是程式本人。
2. ㄧ定要用分號（；）來隔開其他都不行呦！且標頭檔的兩個分號都是不能省略的喔!
3. 其實for標頭式裡的運算式是可有可無的。
 -如果省略條件運算式，將會建立成一個無窮迴圈。
 -若事先設定好初始值，便可以省略初始化的運算式。(把宣告放外面)
 -若遞增減動作在for迴圈內執行或是不需遞增減動作，遞增減運算式便可省略。
4. 你在迴圈標頭式裡才定義control varible的話，control variable僅在迴圈結束前存在。
* Example
```c=
for( int yyds = 1; yyds <= 10; yyds++){ 
    printf("%d\n",yyds);
}
```
 -因為控制變數yyds在標頭式內才定義，所以只存在迴圈結束前。
 -程式一開始會先從初始值yyds=1開始，接下來判斷是否符合條件運算式yyds<=10，符合條件便執行程式印出1。程式執行完畢後，控制變數yyds的值便會+1，然後迴圈會再度測試迴圈執行條件，程序將一直持續下去，直到yyds遞增到終止值11，不符合條件運算式為止。
# 4.5 for Statement:Note and Observations
* for 注意事項&提示
1. 定義初始值、條件運算式&遞增減的部分都是可以包含算數運算式的。
2. 如果迴圈一開始的繼續條件為偽，則迴圈本體將不會執行。
3. 控制變數可以只用來控制循環的次數，在迴圈內本體不一定要使用它。
(如果只是單純跑次數的話就不要亂改，因為會影響條件)
# 4.6 Examples Using the for Statement
* 這一張主要在舉例一些使用for迴圈的範例，課本上都有，我這邊就總結一些事項、小蜜蜂以及數值輸出格式化。
* 數值輸出格式化
-- 浮點數:%[+(向右靠)][-(向左靠)][寬度][.小數位數][f|e|g]

:::spoiler 注意!
課本中的第二個範例:計算複利中使用到的類似pow((x,y)會計算出x的y次方)這樣的數學函式時，應寫上標頭檔<math.h>。若沒有連結器可能沒有辦法找到pow函式。關於函式的詳細資訊第五章有介紹。
:::
:::spoiler 🐝
double型別是和float型別，但通常double可以儲存比float更精確度更高的值。但同樣的double所需的記憶體也比float多。
:::
:::spoiler 🐝
最好不要使用float和double變數形別來執行金額運算。浮點數的不確定性，可能會導致不正確的金額。範例中使用double型別來處理複利計算是為簡單化，因為在處理金額時可能帶有小數。
:::


# 4.7 switch Mutiple-Selection Statement~(~~這不重要。但是佐任愛考qq~~)~
* swicth 定義&大概長什麼鳥樣
1. 有時候我們可能執行一連串的判斷來針對不同的情況採取不同的動作，這就稱為多重選擇。而switch就是C語言裡提供的一個多重敘述式。
2. switch 包含了一連串的case標籤和對每個case所要執行的敘述式，以及一個可有可無的default case。
* Example
```c=
switch(id){
    case a: A=1; break;
    case b: B=2; break;
    case c: C=3; break;
            .
            .
            .
    case z: Z=n; break;
    
    default:
        printf("%s",is not correct)
        break;      
}

```
-switch後括號內的id便是控制運算式（controlling expression），他將會一一比較case label直到找到符合的就執行case的敘述式，最後因break而結束。若沒有符合的便會執行default case的敘述式，最後再因break而結束。（沒有break的話case會接著執行）
-記住每一個case只能檢驗一個常數整數運算式(constant integral expression)。 字元必須被放在單引號中，如'A'，才會被視為字元常數
:::spoiler EOF小補充
* EOF=end of file
* 通常值會是-1(會因為作業系統不同而影響)
* 在windows系統裡面等於ctrl+z
* 定義於<stdio.h>裡面
:::

# 4.8 do...while Iteriation Statement
* do...while與while差別
1. while是在一開始便會檢驗迴圈地繼續條件，所以迴圈本體的執行次數最小次數為0。
2. do...while則是會在本體執行一次後才開始檢驗迴圈執行條件。因此迴圈本體的執行最小次數為1。
* do...while 格式
```c=
do {
    statements
}while(condition);
```
-大括號{}內的statement要執行的敘述式本人，而while小括號()內的contdition便是檢驗迴圈繼續的條件。
* Example
```c=
int yyds=0;
do{
    printf("%d\n",yyds);
    yyds++;
}while(yyds<=10);

```
-一開始會先執行do後大括號{}裡的敘述式一次並印出0，接著yyds的值+1。接下來才會開始檢驗yyds是否符合while後小括號()裡yyds<=10的條件。若符合便會持續這個動作，直到不符合條件便結束。
* do...while流程圖
![](https://i.imgur.com/8Am41yb.jpg)


# 4.9 break & continue
* break與continue的差別
 -可以想成break是"跳出"、continue是"跳過"。在迴圈裡使用break的話，則是直接跳出迴圈並執行迴圈後的第一個敘述式。continue則是會跳過迴圈內尚未執行的敘述式，並直接執行下一次迴圈的動作。
* Example(break)
```c=
    for(int yyds=1; yyds<=10; yyds++){
        
        if(yyds==5){
            break;
        }
        printf("%d\n",yyds);
    }
```
-for迴圈一開始會先執行初始值1並印出1，接下來yyds的值變+1，繼續執行迴圈。直到yyds=5，符合if的條件的時候，執行內部敘述式break，並跳出迴圈直接執行迴圈後的下一個敘述式
* Excample(continue)
```c=
for(int yyds=1; yyds<=10; yyds++){
    if(yyds==5){
        continue;
    }
    printf("%d\n",yyds);
}
```
-for迴圈一開始會先執行初始值1並印出1，接下來yyds的值+1，繼續執行迴圈。直到yyds=5，符合if的條件的時候，執行內部敘述式continue，跳過迴圈後的敘述式繼續執行下一輪的迴圈yyds=6，並印出6。接著繼續for迴圈，直到yyds的值不符合for的迴圈執行條件。
# 4.10 Logical Operators
* 邏輯運算子包括了(&&)AND、(||)OR和(!)NOT。
1. 邏輯運算子AND(&&)
 -邏輯運算子&&只會在兩種條件都為真的情況下才執行。
![](https://i.imgur.com/7QjZ0ik.jpg) 

 -以上圖AND(&&)真值表來看，當expression1和expression2同時為非0時，expression1&&expression2才會變換成1。若expression1為0、expression2為非零，兩者不同時為真，expression1&&expression2就會為0。
2. 邏輯運算子OR(||)
 -邏輯運算子||只要兩者中有其中一者為真，就會執行
 ![](https://i.imgur.com/sGEmoKV.jpg)
 -以上圖OR(||)真值表來看，只要expression1和expression2其中一者為非零或兩者為非零，expression1||expression2就會為1。相對的，要是兩者同時為0，條件都不為真時，expression1||expression2就會為1。
 
3. 邏輯否定運算子NOT(!)
 -NOT（!）就是將條件反過來解釋
 ![](https://i.imgur.com/SMpXGfW.jpg)
 -以上圖NOT(!)真值表來看，若expression為0，！expression為非零。同樣的expression為非零，！expression就會為0。
 
*  而**邏輯運算子**是有優先順序和結合性的。下圖表格優先順序是由上到下。(**學長說這是考古題)**
![](https://i.imgur.com/1iwBDyd.jpg)

* 布林（boolean）資料型態
 -C語言用零值和非零值來表示真偽。而 bool (#include <stdbool.h>) 則是用true和false取代了1和0來表示真偽。
# 4.11 Confusing Equality(==)&Assignment(=)Operators
* 相等運算子(==)是判斷第一個運算元是否等於第二個運算元，而指定運算原則是簡單的指定動作而已。基本上這兩個東東會經常搞混，我們用Example來說明。
* Example1 (將(==)打成(=)) 
```c=
if(yyds == 4){
  printf("%s","you are god");
  
}
```
-這個程式內使用相等運算子，所以在yyds的值等於四的時候，便會執行if內的敘述式，而印出"you are god"。
```c=
if(yyds = 4){
    printf("%s","you are god");
}
```
-若我們不小心打成如上圖指定運算子的話，此運算子是一個簡單的指定動作。任何非零的數值都會被解釋為真。而4一個大於零的常數，所以條件式將永遠被判斷為真。因此不管yyds實際的值是多少，都會執行if內的敘述式。
* Example2 (將(=)打成(==))
```c=
yyds = 1;
```
-此運算式只是將一個值設定給變數而已。
```c=
yyds == 1;
```
-而若不小心打成==，編譯氣會將此判斷承當 yyds的值為1的時候條件為真，並執行敘述式。反之，若值不等於1，條件為偽，將不會執行敘述式。
:::spoiler 🐝
當你們在寫相等運算子(==)可以將習慣從原本的變數名稱放左邊常數寫右邊，改成變數寫右邊常數寫左邊(如yyds == 7 改成 7 == yyds)。若不小心打成=的話，編譯器會自動把此錯誤找出來，因為指定運算子(=)的左邊只能放變數名稱而已。
:::


# 4.12 Structured Programming Summary
* 任意的連接個別的流程符號可能會導致非結構化的程式。僅使用單一入口及單一出口的控制敘述式，能夠循序的連接控制敘述式以形成結構化程式。
* 形成結構化程式的規則
1. 從最簡單的流程圖開始
 ![](https://i.imgur.com/EGeCOdD.jpg)

2. (堆疊規則)任何地矩形(動作)都可以被兩個矩形(動作)依順序替換。
![](https://i.imgur.com/kjchk4x.jpg)

3. (巢狀規則)任何矩形(動作)都可以被任何控制敘述式所取代。
![](https://i.imgur.com/HX7I0GE.jpg)
-將最簡單流程圖的矩形換成一個雙重選擇敘述式。而虛線包起來的雙重選擇敘述式代表被矩形換掉的部分。
4. 規則2和3可以按照你的喜好以任何順序經常使用。若按照規則使用會產生如下圖一樣非結構化的流程圖。
![](https://i.imgur.com/1BZAXtm.jpg)

* 任何程式只需下列三種控制格式
1.  循序
2.  選擇
-- if 
-- if...else
-- switch
  **if...else & switch都可用最簡單的 if 取代。
3.  循環
-- while
-- do...while
-- for
  **do...while & for都可用while來取代。
*   Conclusion
-我們只需要以下三種控制格式就可以完成C程式所需要的任何控制形式。而這些控制形式只能以堆疊跟巢狀兩種方式組合。
-- 循序
-- if (選擇)
-- while (循環)
# 4.13 Secure C Programming
* 檢查scanf函式回傳值
-倘若輸入有錯，scanf會回傳EOF，或會回傳她讀到項目的個數，若與你的期望不符，表示scanf沒有完成輸入操作。
:::spoiler 🐝
記得檢查scanf回傳值，以確保讀取的輸入數量與預期的輸入數量符合。
:::
* 範圍檢查
-scanf即使執行完成，讀入的值可能是無用的。你必須在完成程式候用範圍檢查(range checking)來驗證，並可以在該值超出範圍時要求使用者重新輸入。
# Chapter4 結束
###### tags: `程設好難` `學校門口大樹石頭下` `他的課就很好睡阿`
<style>
.navbar-brand::after { content: " × 老葉的程式設計"; }
</style>