3.Structure Program Development in C
===
## 3.2 Algorithms
要執行的動作,以及執行這些操作的順序稱為演算法
## 3.3 Pseudocode
假碼是一種人工和非正式的語言(電腦不會執行),可幫助您開發演算法,它僅由行動和決策的敘述組成
* example as following
```c=
int i;
```
換句話說這個定義不會引起任何動作
## 3.4 Control Structures ( go to語法 )
建議不要使用這語法!!
取而待之的是三種控制結構
1. 序列結構 (sequence structure)
2. 選擇結構 (selection structure)
3. 迭代結構 (iteration structure)
## Flowcharts
圓角長方形代表"開始"
小圓圈代表"連接器"
菱形代表"決策"


## Selection statement
1. if (單一選擇)
2. if...else (雙重選擇)
3. switch (多重選擇)
## Iteration statement
1. while
2. do...while
3. for
## 3.5 If..else Statement
```c=
#include <stdio.h>
#include <stdlib.h>
int main()
{
int grade;
printf("grade is ");
scanf("%d", &grade);
if ( grade >= 60 ) {
puts("Passed\n");
}
else {
puts("Failed\n");
}
return 0;
}
```
* 我們可以從範例中知道
if選擇語句僅在條件為真時執行指定的操作
## 3.6 比較下列兩個if...else Statement
1. else後面是先接括號,在接if的敘述
```c=
#include <stdio.h>
#include <stdlib.h>
int main()
{
int grade;
scanf("%d", &grade);
printf("Your scores level: ");
if ( grade >= 90) {
puts("A");
}
else {
if ( grade >= 80 ) {
puts("B");
}
else {
if ( grade >= 70) {
puts("C");
}
else {
if ( grade >= 60) {
puts("D");
}
else {
puts("F");
}
}
}
}
return 0;
}
```
2. else後面接if,然後接括號
```c=
#include <stdio.h>
#include <stdlib.h>
int main()
{
int grade;
scanf("%d", &grade);
printf("Your scores level: ");
if ( grade >= 90) {
puts("A");
}
else if ( grade >= 80 ) {
puts("B");
}
else if ( grade >= 70) {
puts("C");
}
else if ( grade >= 60) {
puts("D");
}
else {
puts("F");
}
return 0;
}
```
* 對於C的編譯器而言,兩種形式是相同的。然而後者因為**避免了代碼向右的深度縮排**。這種縮排經常在一行裡留下很小的空間,迫使行被拆開並降低程式的可讀性!
## 3.7 The while Iteration ( Counter-controlled iteration )
```c=
#include <stdio.h>
#include <stdlib.h>
int main()
{
unsigned int counter;// number of grade to be entered
int grade; // grade value
int total;// sum of grades entered by user
int average;// average of grades
// initial phase
total = 0;// initialize total
counter = 1;// initialize loop counter
// processing phase
while ( counter <= 10 ) {// loop 10 times
printf("%s","Enter grade: ");// prompt for input
scanf("%d", &grade);// read grade from user
total = total + grade;// add grade to total
counter = counter + 1;// increment counter
}// end while
// termination phase
average = total / 10;// integer division
printf("Class average is %d\n", average);// display result
}// end function main
```
1. 變數被儲存在總計而且在被程式使用前應該設初始值為零,**否則總和會包括存儲在總計內存位置的先前值**
2. 計數器變數是通常初始化為0或1,這取決於它們的用途。一個未初始化的變數包含一個**垃圾值**,最後存儲在為該變數保留的內存位置。
## 3.9 Sentinel-controlled iteration
* synonym ( 同義詞 )
( signal / dummy / flag ) value
* e.g. ( 舉例 )
Develop a class-averaging program that will process an arbitrary number of grades each time the program is run.
翻譯:開發一個班級平均程式,該程式將會在每次程式運行時處理任意數字的成績。
* 處理方式可利用一種稱為**sentinel value**來表示**數據輸入結束**。使用者輸入成績直到輸入完所有合法的成績,然後輸入sentinel value來表示最後的成績已經輸入完成。**Sentinel-Controlled Iteration**通常稱為無限迭代( **Indefinite iteration** ),原因是由於在循環開始執行前,不知道迭代的次數。
##### *Top-Down, Stepwise Refinement*
* 我們使用一種稱為**自上而下逐步細化**的技術來處理類平均程式,一種對程式至關重要的技術。
我們開始一個假碼(pseudocode)來表示頂部(top):
*Determine the class average for the quiz*
* 頂部是完整地傳達程式的整體功能。然而,卻未能傳達足夠的細節來編寫C程式。因此第一次細化過程如下:
*Determine the class average for the quiz
Initialize variables
Input, sum, and count the quiz grades
Calculate and print the class average*
* 使用了**序列結構** ( sequence structure )
##### *Second Refinement*
* 第二次細化**致力於特定的變數**,需要對數字進行匯總,計算有多少個數字已處理。一個變數用於接收每項成績的值作為輸入和一個變數來保持計算的平均值。假碼的語句可以細化如下:
*Initialize variables
Initialize total to zero
Initialize counter to zero*
* 只需要**初始化總數和計數器**。
變數平均值和成績 ( 對於分別計算出的平均值和使用者輸入 ) 不需要初始化,因為它們的值將分別從使用者計算和輸入。
*Input, sum, and count the quiz grades*
* 假碼 ( pseudocode )需要一個迭代結構 ( iteration structure ) ,依次輸入每項成績。因為我們不知道預先處理多少個成績,我們將**使用哨兵控制的迭代 ( sentinel-controlled iteration )** 。當使用者輸入到最後一個合法成績後,使用者將輸入標記值 ( sentinel value ) 。程式測試每項成績然後當**輸入 ( sentinel ) 時終止循環**。
*Input the first grade (possibly the sentinel)
While the user has not as yet entered the sentinel
Add this grade into the running total
Add one to the grade counter
Input the next grade (possibly the sentinel)*
## 3.8 Class-average program with sentinel-controlled iteration.
```c=
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
unsigned int counter;
int grade;
int total;
float average;
total = 0;
counter = 0;
printf("%s", "Enter grade, -1 to end: ");
scanf("%d", &grade);
while ( grade !=-1 ) {
total = total + grade;
counter = counter + 1;
printf("%s", "Enter grade, -1 to end: ");
scanf("%d", &grade);
}
if ( counter != 0 ) {
average = (float) total / counter;
printf( "Class average is %.2f\n", average );
}
else {
puts( "No grades were entered" );
}
}
```
1. while循環複合語句**大括號是必要的**,以確保所有語句都在循環內執行。
2. total / counter 的計算結果是一個整數,因為 total 和 counter 都是整數變數。**因為先進行計算**,在將結果分配給平均值之前,小數部分會丟失。
##### *Converting Between Types Explicitly(明確地)and Implicitly(含蓄地)*
```c=
average = ( float ) / counter;
```
1. 轉換運算符 (float),它創建其操作數的臨時浮點副本,total。total存儲的值仍然是一個整數,以這種方式**使用強制轉換**運算符稱為**顯式**轉換。
2. 為確保操作數的類型相同,編譯器執行**對選定操作數**稱為**隱式**轉換的操作。
##### *Formatting Floating-Point Number*
```c=
printf("%.2f\n", 3.446);// prints 3.45
printf("%.1f\n", 3.446);// prints 3.4
```
* f 確認將印出浮點值
* (.2) 是顯示值的精確度,而小數點右側有 2 位數字
* 如果使用 %f 轉換說明符(不指定精確度),不履行精確度的 6 被使用了,就像使用了轉換說明符 %.6f 一樣。當浮點數值被精確地輸入,輸入值被四捨五入到指定的數量小數位,**其中內存中的值不變**。
##### *Notes on Floating-Point Numbers*
* 儘管浮點數並不總是100%精確,但有許多應用
* 浮點數發展的另一種方式是透過除法。
* 電腦**只分配固定量的空間**來保存這樣的值,因此存儲的浮點值**只能是一個近似值**。
## 3.10 Nested Control Statements
* 假碼自上向下,逐步細化,編寫相應的C程式,而控制語句可能會彼此按順序堆疊在一起就像孩子堆砌積木一樣。舉例如下:

* 舉例如下:
```c=
#include <stdio.h>
int main( void ) {
unsigned int passes = 0;
unsigned int failures = 0;
unsigned int student = 1;
int result;
while ( student <= 10 ) {
printf( "%s", "Enter result ( 1=pass,2=fail ): " );
scanf( "%d", &result );
if ( result == 1 ) {
passes = passes + 1;
}
else {
failures = failures + 1;
}
student = student + 1;
}
printf( "Passed %u\n", passes );
printf( "Failed %u\n", failures );
if ( passes > 8 ) {
puts( "Bonus to instructor!" );
}
}
```
## 3.11 Assignment Operators
先假設: int c = 3, d = 5, e = 4, f = 6, g = 12;
| Assignment operator | Sample expression | Explanation |
| -------- | -------- | -------- |
| += | c += 7 | c = c + 7|
| -= | d -= 4 | d = d - 4|
| *= | e *= 5 | e = e * 5|
| /= | f /= 3 | f = f / 3|
| %= | g %= 9 | g = g % 9|
## 3.12 Increment and Decrement Operators

判斷方式:
* **前置**遞增運算子是**先遞增**之後才指定
* **後置**遞增運算子是先指定之**後**才**遞增**
* 單字解釋(increment增加)(post在後)(pre在前)
```c =
#include <stdio.h>
#include <stdlib.h>
int main()
{
int c;
c = 5;
printf("%d\n", c);// print 5
printf("%d\n", c++);// print 5 then postincrement
printf("%d\n\n", c);// print 6
c = 5;
printf("%d\n", c);// print 5
printf("%d\n", ++c);// preincrement then print 6
printf("%d\n", c);// print 6
}
```
* 一元運算符應該直接放在它們的操作數旁邊,**中間沒有空格**。有個簡單的表示法如下方:
a □ = b;
a = a □ b;
***其中 □ 可以是 + - / 任何一個符號***
* 當在一個變數增加或減少**其自身時**,語句本身前增量和後增量形式**具有相同效果**。只有當一個變數出現在一個更大的表達的上下文中時,後遞增具有不同的效果(對於前遞減和後遞減類似)。因此,**只有一個簡單**的變數名可以**用作遞增或遞減運算符**的操作數。
下方的表格參考看看吧

單字解釋:
(multiplicative 乘法的;倍數詞的)
(postfix 字尾;詞尾)
## 3.13 Secure C programming
```c =
sum = integer1 + interger2;
```
##### Arithmetic Overflow ( 算術溢出 )
將整數相加可能會**導致太大而無法存儲**在int變數中的值。這稱為算術溢出而且可能導致未定義的行為、使系統容易受到攻擊。可以存儲在int中的特定於平台的最大值和最小值變數分別由常量**INT_MAX和INT_MIN**表示,它們是在標題 <limits.h> 中定義。
##### Unsigned Integers
一般來說,應該**存儲非負數**的計數器值應該在整數類型之前用無符號聲明。無符號變數類型可以表示**從0到相應的正範圍的大約兩倍的值**有符號整數類型。
###### tags: `程設好難` `學校門口大樹石頭下` `他的課就很好睡阿`
<style>
.navbar-brand::after { content: " × 老葉的程式設計"; }
</style>