流程控制 鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所 綱要 1. 2. 3. 4. 5. 6. 7. 巢狀if 與if-else if敘述 switch 敘述 列舉型別 for 迴圈 while 迴圈 do-while 迴圈 continue與break 綱要 8. 9. 10. 11. 變數生命週期與有效範圍 無窮迴圈應用 結構化程式設計 應用虛擬碼設計結構化程式 綱要 1. 2. 3. 4. 5. 6. 7. 巢狀if 與if-else if敘述 switch 敘述 列舉型別 for 迴圈 while 迴圈 do-while 迴圈 continue與break.
Download
Report
Transcript 流程控制 鄭士康 國立台灣大學 電機工程學系/電信工程研究所/ 資訊網路與多媒體研究所 綱要 1. 2. 3. 4. 5. 6. 7. 巢狀if 與if-else if敘述 switch 敘述 列舉型別 for 迴圈 while 迴圈 do-while 迴圈 continue與break 綱要 8. 9. 10. 11. 變數生命週期與有效範圍 無窮迴圈應用 結構化程式設計 應用虛擬碼設計結構化程式 綱要 1. 2. 3. 4. 5. 6. 7. 巢狀if 與if-else if敘述 switch 敘述 列舉型別 for 迴圈 while 迴圈 do-while 迴圈 continue與break.
流程控制
鄭士康
國立台灣大學
電機工程學系/電信工程研究所/
資訊網路與多媒體研究所
1
綱要
1.
2.
3.
4.
5.
6.
7.
巢狀if 與if-else if敘述
switch 敘述
列舉型別
for 迴圈
while 迴圈
do-while 迴圈
continue與break
2
綱要
8.
9.
10.
11.
變數生命週期與有效範圍
無窮迴圈應用
結構化程式設計
應用虛擬碼設計結構化程式
3
綱要
1.
2.
3.
4.
5.
6.
7.
巢狀if 與if-else if敘述
switch 敘述
列舉型別
for 迴圈
while 迴圈
do-while 迴圈
continue與break
4
巢狀if流程
false
false
輸出”成績優良”
score < 80
score < 60
true
true
輸出”不及格”
輸出”成績中等”
5
UsingNestedIf.Program片段
if (score < FAIL_THRESHOLD)
{
Console.WriteLine("請注意, 成績不及格");
}
else
{
if (score < GOOD_GRADE_THRESHOLD)
{
Console.WriteLine("成績中等");
}
else
{
Console.WriteLine("成績優良");
}
}
6
懸置else
if ( score >= 60 )
if( score >= 80 )
Console.WriteLine(“成績優良”);
else
Console.WriteLine(“請注意, 成績不及格”);
============================================
if ( score >= 60 )
if( score >= 80 )
Console.WriteLine(“成績優良”);
else
Console.WriteLine(“請注意, 成績不及格”);
7
避免懸置else
if ( score >= 60 )
{
if( score >= 80 )
{
Console.WriteLine(“成績優良”);
}
}
else
{
Console.WriteLine(“請注意, 成績不及格”);
}
8
if-else if 敘述
false
false
false
false
score
>= 60
score
>= 70
score
>= 80
score
>= 90
true
true
true
true
grade =
‘F’
grade =
‘D’
grade =
‘C’
grade =
‘B’
grade =
‘A’
9
UsingIfElseIf.Program片段
if (score >= 90)
{
grade = ‘A’;
}
. . . . . .
else if (grade >= 60)
{
grade = ‘D’;
}
else
{
grade = ‘F’;
}
10
練習
• 西元年份被4整除, 但不被100整除,就是閏
年;能被400整除的話, 也算閏年
• 寫一個程式,輸入西元年份,輸出該年是
否閏年
• 可以先畫流程圖澄清概念
11
綱要
1.
2.
3.
4.
5.
6.
7.
巢狀if 與if-else if敘述
switch 敘述
列舉型別
for 迴圈
while 迴圈
do-while 迴圈
continue與break
12
同一變數之有限多個值作為條件之
連續判斷 false grade
== ‘A’
false
false
false
false
grade
== ‘F’
grade
== ‘D’
grade
== ‘C’
grade
== ‘B’
true
true
true
true
true
輸出
輸出
輸出
輸出
輸出
輸出
“成績錯誤” “不及格” “成績尚可” “成績中等” “成績良好” “成績優異”
13
Switch 流程
grade
default
‘F’
‘D’
‘C’
‘B’
‘A’
輸出
輸出
輸出
輸出
輸出
輸出
“成績錯誤” “不及格” “成績尚可” “成績中等” “成績良好” “成績優異”
14
UsingSwitch.Program 片段(1/2)
Console.Write("請輸入成績:A, B, C, D, F: ");
char grade =
Console.ReadLine().ToCharArray()[0];
switch (grade)
{
case 'A':
Console.WriteLine("成績優異");
break;
case 'B':
Console.WriteLine("成績良好");
break;
15
UsingSwitch.Program 片段(2/2)
case 'C':
Console.WriteLine("成績中等");
break;
case 'D':
Console.WriteLine("成績尚可");
break;
case 'F':
Console.WriteLine("不及格");
break;
default:
Console.WriteLine("成績錯誤");
break;
}
16
switch 流程
true
grade==‘A’
false
grade==‘B’
false
break
輸出”成績優異”
break
true
輸出”成績良好”
true
grade==‘C’
break
輸出”成績中等”
false
grade==‘D’
true
break
輸出”成績尚可”
false
輸出”成績錯誤”
grade==‘F’
break
true
輸出”不及格”
false
17
switch 敘述
• 省略break的場合
• 使用字元與其他整數型別的switch敘述
18
綱要
1.
2.
3.
4.
5.
6.
7.
巢狀if 與if-else if敘述
switch 敘述
列舉型別
for 迴圈
while 迴圈
do-while 迴圈
continue與break
19
示範程式UsingEnum重要片段(1/2)
enum WeekDay
{
SUN = 1,
MON = 2,
TUE = 3,
WED = 4,
THU = 5,
FRI = 6,
SAT = 7
}
20
示範程式UsingEnum重要片段(2/2)
WeekDay day = WeekDay.TUE;
switch (day)
{
case WeekDay.SUN:
Console.WriteLine("星期日為一週的第{0}天!!",
(int)WeekDay.SUN);
break;
case WeekDay.TUE:
Console.WriteLine("星期二為一週的第{0}天!!",
(int)WeekDay.TUE);
break;
default:
Console.WriteLine("一週的第{0}天!!",
(int)day);
break;
}
21
列舉型別 (Enumeration)
• 組織整數常數與程式維護
• 省略數值指定
• 應用列舉型別
22
練習
• 宣告並測試列舉型別Season,其中包括常
數Spring、Summer、Fall、Winter
23
練習
• 宣告列舉型別Grade,其可能值包括A、B、
C、D、F
• 成績變數grade宣告為Grade型別,其值
由Grade.A到Grade.F
• 以列舉型別改寫程式UsingSwitch.Program
24
綱要
1.
2.
3.
4.
5.
6.
7.
巢狀if 與if-else if敘述
switch 敘述
列舉型別
for 迴圈
while 迴圈
do-while 迴圈
continue與break
25
1加到10
• int sum = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
• int sum = 0;
sum += 1;
sum += 2;
sum += 3;
sum += 4;
sum += 5;
sum += 6;
sum += 7;
sum += 8;
sum += 9;
sum += 10;
26
1加到100
• int sum = 1 + 2 + 3 + 4 + . . . + 100;
• int sum = 0;
sum += 1;
sum += 2;
sum += 3;
sum += 4;
.
.
.
sum += 100;
27
1加到100的流程
sum = 0
i> 100
i = 1
i <= 100
++i
i <= 100
sum += i
輸出 sum
28
UsingFor.Program 片段
int sum = 0;
for (i = 1; i <= 100; i++)
{
sum += i;
}
Console.WriteLine(
"1 ~ 100 的加總等於 " + sum);
29
練習
• 修改範例程式UsingFor,計算1到100的偶
數和
30
關於迴圈(Loops)
• 迴圈之基本要素
– 控制變數初值設定
– 檢驗條件
– 控制變數改變
• 常見錯誤
– 邊界值錯誤, Off-by-one
– 無窮迴圈
31
MTable.Program片段
for (i = 1; i < 10; ++i)
{
for (j = 1; j < 10; ++j)
{
Console.Write("{0}*{1}={2} ",
i, j, i * j);
}
// 印完一組便換行
Console.WriteLine();
}
32
迴圈執行效率
• 迴圈中不改變的敘述
• 編譯建置過程的最佳化
• 兩種版本的CIL檔
– Release
– Debug
33
綱要
1.
2.
3.
4.
5.
6.
7.
巢狀if 與if-else if敘述
switch 敘述
列舉型別
for 迴圈
while 迴圈
do-while 迴圈
continue與break
34
1加到100的流程
sum = 0
i = 1
false
i <= 100
true
sum += i
++i
輸出 sum
35
UsingWhile.Program 片段
int sum = 0;
int i = 0;
while (i <= 100)
{
sum += i;
++i;
}
Console.WriteLine(
"1 ~ 100 的加總等於 “ +
sum);
36
常見錯誤
• 控制變數未設初值
• 迴圈內控制變數未改變
• 無窮迴圈
37
使用時機
• 迴圈繼續執行之條件比較複雜
• 很不容易以一個控制變數表現迴圈繼續執
行之條件
– 例如,檔案讀取未結束
38
綱要
1.
2.
3.
4.
5.
6.
7.
巢狀if 與if-else if敘述
switch 敘述
列舉型別
for 迴圈
while 迴圈
do-while 迴圈
continue與break
39
1加到100的流程
sum = 0
i = 1
sum += i
++i
false
i <= 100
true
輸出 sum
40
UsingDoWhile.Program 片段
int sum = 0;
int i = 1;
do
{
sum += i;
++i;
} while (i <= 100);
Console.WriteLine(
"1 ~ 100 的加總等於 “+sum);
41
for, while, do-while的主要差別
• for迴圈與while迴圈可能完全不被執行
• do-while迴圈至少會被執行一次
42
綱要
1.
2.
3.
4.
5.
6.
7.
巢狀if 與if-else if敘述
switch 敘述
列舉型別
for 迴圈
while 迴圈
do-while 迴圈
continue與break
43
畢氏數
• x 2 + y 2 = z2
• 前10組畢氏數
– (3, 4, 5)、(5, 12, 13)、(6, 8, 10)、(7, 24, 25)、(8, 15,
17)、(9, 12, 15)、(9, 40, 41)、(10, 24, 26)、(11, 60,
61)、(12, 16, 20)
44
Pythagoras.Program重要片段
for (x = 1; x <= 100; ++x) {
for (y = x; y <= 100; ++y) {
for (z = 1; z <= 150; ++z) {
if (x * x + y * y == z * z) {
++n;
if (n <= 10) {
Console.WriteLine(
"{0}: {1}*{1} + {2}*{2} = {3}*{3}",
n, x, y, z);
}
}
}
}
}
45
UsingBreak.Program重要片段
for (x = 1; x <= 100; ++x) {
for (y = x; y <= 100; ++y) {
for (z = 1; z <= 150; ++z) {
if (x * x + y * y == z * z) {
++n;
Console.WriteLine(
"{0}: {1}*{1} + {2}*{2} = {3}*{3}",
n, x, y, z);
break;
}
}
if (n == 10) break;
}
if (n == 10) break;
}
46
UsingContinueAndBreak.Program片段
for (x = 1; x <= 100; ++x){
for (y = x; y <= 100; ++y){
for (z = 1; z <= 150; ++z){
if (x * x + y * y != z * z) continue;
++n;
Console.WriteLine(
"{0}: {1}*{1} + {2}*{2} = {3}*{3}",
n, x, y, z);
break;
}
if (n == 10) break;
}
if (n == 10) break;
}
47
綱要
9.
10.
11.
12.
變數生命週期與有效範圍
無窮迴圈應用
結構化程式設計
演算法虛擬碼
48
VarScope片段
Console.Write("請輸入一個字元: ");
string s = Console.ReadLine();
if (s == "A") {
string s1 = s;
Console.WriteLine(s1 + "為第一個英文字母!!");
} else {
string s1 = s;
Console.WriteLine(s1 + "不是第一個英文字
母!!");
}
for (int i = 0; i < 10; i++) {
string s1 = s;
Console.WriteLine(s1);
}
49
綱要
9.
10.
11.
12.
變數生命週期與有效範圍
無窮迴圈應用
結構化程式設計
演算法虛擬碼
50
CheckingInput.Program 片段
Console.Write("輸入成績: ");
grade = Convert.ToInt16(Console.ReadLine());
while (grade <0 || grade > 100)
{
Console.Write("成績須在0到100之間, 請重新輸入: ");
grade = Convert.ToInt16(Console.ReadLine());
}
Console.WriteLine("成績為: " + grade);
51
特設之無窮迴圈
for ( ; ; ) {
/*
. . . . . .
*/
}
或
while (true) {
/*
. . . . . .
*/
}
52
UsingInfiniteLoop.Program 片段
int grade = 0;
Console.Write("輸入成績: ");
while (true)
{
grade =
Convert.ToInt16( Console.ReadLine() );
if (grade >= 0 && grade <= 100) break;
// 數值合理則跳出無窮迴圈
Console.Write(
"成績須在0到100之間, 請重新輸入: ");
}
Console.WriteLine("成績為: " + grade);
53
練習
• 寫一程式,要求使用者不斷輸入及Echo學
生成績,直到輸入為負時為止。印出學生
總人數及平均成績
54
綱要
9.
10.
11.
12.
變數生命週期與有效範圍
無窮迴圈應用
結構化程式設計
演算法虛擬碼
55
FORTRAN-IV程式片段
100
200
300
SUM = 0
I = 1
IF( I > 100 ) GOTO 200
SUM = SUM + I
I = I + 1
GOTO 100
WRITE(6, 300) SUM
FORMAT(1X, I6)
56
goto敘述
• 允許使用者由程式某處任意跳到另一處
• 容易產生通心麵狀程式碼(spaghetti code)
• 極少數情況下仍需使用
57
通心麵狀程式碼(Spaghetti Code)
流程
58
結構化程式
59
綱要
9.
10.
11.
12.
變數生命週期與有效範圍
無窮迴圈應用
結構化程式設計
演算法虛擬碼
60
虛擬碼(Pseudo Code)
• 幫助思考程式流程
• 沒有程式語言正式,省略細節,易寫易懂
• 限定使用結構化程式流程控制,容易以程
式語言改寫
• 較流程圖方便
• 紙筆追蹤測試(Tracing an algorithm)
61
Euclid 輾轉相除法尋找最大公因數
在正整數x與y都不是0的情況下,持續以較
大的數除以較小的數,並將除數與餘數分
別設給x與y。最後的x便是原先兩數的最大
公因數。
62
Euclid 輾轉相除法虛擬碼
1. x = 較大的輸入值;
2. y = 較小的輸入值;
3. while( y不等於0)
{
3.1 remainder = x 除以y的餘數;
3.2 x = y;
3.3 y = remainder;
}
4. 最大公因數 = x;
63
紙筆測試
• GCD(1, 5)=1
• GCD(12, 18)=3
• GCD(17, 13)=1
64
Euclid.Program 程式片段
if (x < y) // x 較小時, 需交換x 與 y
{
int temp = x;
x = y;
y = temp;
}
while (y != 0)
{
remainder = x % y;
x = y;
y = remainder;
}
65
練習
• 用下一頁的演算法, 撰寫虛擬碼, 進行紙筆測
試, 並完成C#程式
66
判斷是否質數的篩檢法
• 要判斷x是否質數,可用2開始到x開根號的
奇數,逐一檢查是否能整除x
•如果都不能整除,x便是質數,否則x就不
是質數
67