Chương 3: Cấu trúc ñiều khiển

Giảng viên: Ph.D Nguyễn Văn Hòa Khoa KT-CN-MT – ðH An Giang

1

Giới thiệu

ñiều khiển

(cid:1) Dữ liệu và tác vụ là 2 yếu tố cơ bản của CT (cid:1) Mỗi sự kết hợp của chúng gắn liền với cấu trúc

ñịnh thứ tự thực hiện chương trình (cid:1) Xét về cấu trúc thì có 3 loại ñiều khiển

(cid:2) ðiều khiển trong biểu thức (cid:2) ðiều khiển giữa các lệnh (phát biểu): như cấu trúc ñiều

kiện hay cấu trúc lặp

(cid:2) ðiều khiển trong chương trình con: gọi trả về hay ñệ

qui

2

(cid:1) Cấu trúc ñiều khiển là tập hợp các qui tắc xác

Giới thiệu (tt)

VD qui tắc ưu tiên của các toán tử

(cid:2) ðiều khiển tường minh: ñược xác ñịnh bởi programmer

(cid:1) Xét về thiết kế ngôn ngữ thì có 2 loại ñiều khiển (cid:2) ðiều khiển ngầm: ñược thiết kế trong ngôn ngữ LT,

(cid:2) ðiều khiển tuần tự (cid:2) ðiều khiển cạnh tranh (concurrency) : 2 hoặc nhiều hơn ñoạn chương trình ñược thực thi song song

(cid:1) Hai cấu trúc ñiều khiển

(cid:2) Dễ viết (cid:2) Dễ ñọc

3

(cid:1) Cấu trúc ñiều khiển tốt

Nội dung chính của chương

4

(cid:1) ðiều khiển trong biểu thức (cid:1) Lệnh lựa chọn hay ñiều kiện (cid:1) Lệnh lặp (cid:1) Rẽ nhánh không ñiều kiện (cid:1) Luồng ñiều khiển không tuần tự

ðiều khiển trong biểu thức

chất hàm (functional composition) (cid:2) Tác vụ hay phép toán (cid:2) Các ñối số hay toán hạng

(cid:1) Cơ chế ñiều khiển trong biểu thức là sự chồng

*

-

+

(cid:1) Toán hạng: hằng, các kết quả của các phép tham khảo dữ liệu (biến) hoặc kết quả của các phép toán khác

A

B C

A

(A+B)*(C-A)

5

(cid:1) Cơ chế chồng ñược biểu diễn bởi một cấu trúc cây

ðiều khiển trong biểu thức (tt)

(cid:2) Hiệu ứng lề

(cid:1) Thứ tự ưu tiên của các toán tử (cid:1) Các toán tử cùng ñộ ưu tiên (cid:1) Thứ tự các toán hạng

6

(cid:1) Tính ña năng của toán tử

Thứ tự ưu tiên các toán tử

thứ tự thực hiện các toán tử

(cid:1) Kết quả của biểu thức 3 + 5 * 2 ?? → phụ thuộc

(cid:1) Thứ tự thực hiện các toán tử trong NNLT

FORTRAN 95

C Ada **, abs ** postfix ++,-- *, / prefix ++, *, /, mod

-âm, +dương rem -âm, +dương *, /, % -âm, +dương +,-

+,-

+,-

7

Các toán tử cùng ưu tiên (associativity)

qui luật ñể xác ñịnh thứ tự thực hiện

(cid:1) Các phép toán có cùng ưu tiên, + và -, cần có 1

(cid:2) Từ trái sang phải (cid:2) Trừ Fortran (từ phải sang trái)

(cid:1) VD a-b+c-d (cid:1) Các NNLT qui ñịnh thứ tự thực hiện

tử bị mất ñi và thực hiện theo dấu ngoặc

8

(cid:1) Ada bắt buộc phải có dấu ngoặc ((a-b)+c)-d (cid:1) Nếu có ngấu ngoặc thì thứ tự ưu tiên của các toán

Biểu thức ñiều kiện

if (count == 0) average = 0;

else

average = sum /count;

9

(cid:1) Toán tử «?» là toán tử tam phân (ternary) (cid:1) Biểu thức ñiều kiện chỉ có trong ngôn ngữ C (cid:1) VD average = (count == 0)? 0 : sum / count (cid:1) Có thể dùng câu lệnh if-then-else thay thế

Biểu thức quan hệ

hạng có nhiều kiểu khác nhau

(cid:1) Biểu thức quan hệ: 1 toán tử quan hệ và 2 toán

(cid:1) Trị của biểu thức quan hệ: ñúng hoặc sai (cid:1) VD toán tử quan hệ

FORTRAN 95

C Ada = /= > < >= <=

Bằng .EQ. = = = = Không Bằng .NE. <> != Lớn hơn .GT. > > Nhỏ hơn .LT. < < Lớn hơn or bằng .GN. >= >= Nhỏ hơn or bằng .LN. <= <=

10

Biểu thức logic

kiểu logic

(cid:1) Biểu thức logic: 1 toán tử logic và 2 toán hạng có

C Ada FORTRAN 77 FORTRAN 90 .AND. and && and .OR. or || or .NOT. not ! not xor

11

(cid:1) Trị của biểu thức logic: ñúng hoặc sai (cid:1) VD các toán tử logic

Thứ tự thực hiện các toán tử : C

12

(cid:1) Hậu tố (++, --) (cid:1) Tiền tố (++, --, !) âm dương (+, -) (cid:1) *, /, % (cid:1) +, - (cid:1) <,>,<=,>= (cid:1) ==, != (cid:1) && (cid:1) ||

Hiệu ứng lề

bộ hoặc có truyền quy chiếu

int a= 5; int fun1(){a = 17; return 3;} void fun2(){a = a + fun1();} void main(){

fun2();

}

(cid:1) Kết quả của a là 8 hay 20

13

(cid:1) Hiệu ứng lề là 1 phép toán trả về kết quả ẩn (cid:1) Hàm hiệu ứng lề là hàm thay ñổi biến không cục

Hiệu ứng lề

(cid:2) NNLT không cho phép hàm tham chiếu các biến không

cục bộ và truyền quy chiếu (cid:1) Ưu ñiểm : dễ thực hiện (cid:1) Khuyết ñiểm : không linh hoạt

(cid:2) NNLT phải qui ñịnh thứ tự ưu tiên của các toán hạng (cid:1) Khuyết ñiểm : giảm khả năng tối ưu code của trình biên dịch

(cid:2) Ngôn ngữ C trả về giá trị của a là 20

14

(cid:1) Giải pháp ñể giải quyết hiệu ứng lề

Cú pháp của biểu thức

(cid:2) Phổ biến và tự nhiên nhất: kí hiệu phép toán ñược viết

giữa 2 toán hạng

(cid:2) VD (A + B) * (C - A) (cid:1) Dạng tiền tố (prefix)

(cid:2) Kí hiệu phép toán ñược viết trước các toán hạng (cid:2) VD * (+ (A B)) – (C A))

(cid:1) Dạng trung tố (infex)

(cid:2) Kí hiệu phép toán ñược viết sau các toán hạng (cid:2) VD ((A B) +) (C A) -)*

15

(cid:1) Dạng hậu tố (posfix)

Toán tử ña năng hóa (overloaded)

tử ña năng hóa

(cid:1) Một toán tử có thực hiện nhiều phép toán → toán

(cid:2) int x, y, z ; (cid:2) x = &y // trả về ñịa chỉ ô nhớ của y cho x (cid:2) x = y&z // trả về giá trị của phép toán And trên y,z

(cid:1) Phép toán + với kiểu số nguyên và kiểu số thực (cid:1) Phép toán &: lấy ñịa chỉ và phép toán And (bit)

(cid:2) Trả về trị của ô nhớ mà pointer trỏ ñến hoặc phép toán

nhân

16

(cid:1) Phép toán *

Lệnh ñiều khiển

(cid:2) Lệnh tuần tự

(cid:1) Lệnh gán, lệnh gọi chương trình con (cid:1) Lệnh xuất / nhập

(cid:2) Lệnh lựa chọn hay ñiều kiện (cid:2) Lệnh lặp

(cid:1) Ba loại cấu trúc ñiều khiển cơ bản

17

(cid:1) Lệnh rẽ nhánh không ñiều kiện

Lệnh lựa chọn hay ñiều kiện

của hai hoặc ña nhánh ñể thực hiện

(cid:1) Lệnh ñiều kiện là một lệnh biểu thị sự lựa chọn

(cid:2) Chỉ có 2 lựa chọn (lệnh IF) (cid:2) Nhiều lựa chọn (lệnh CASE)

18

(cid:1) Chia làm 2 loại

Lệnh lựa chọn : 2 lựa chọn

if control_expression then clause else clause

(cid:1) Dạng phổ biến :

(cid:2) Dạng và kiểu của biểu thức lựa chọn như thế nào : quan

hệ, toán và logic?

(cid:2) Các câu lệnh gì sau then và sau else? (cid:2) Lệnh lựa chọn có lòng nhau hay không?

19

(cid:1) Các yếu tố trong lệnh 2 lựa chọn

Biểu thức lựa chọn (2 lựa chọn)

if (boolean_expr) then stmt else stmt

(cid:1) ALGOL 60 : chỉ dùng biểu thức logic

(cid:2) VD if(5-3) printf(«A») else printf(«B»); (cid:2) C/C++/Java: if (expr) stmt else stmt

(cid:1) C (89 trở về trước) : chỉ dùng biểu thức logic (cid:1) C (99) và C++ : biểu thức toán và logic

logic

20

(cid:1) Ada, Java và C# chỉ cho phép dùng biểu thức

Sự lựa chọn lòng nhau

if (count == 0) result = 0;

else result = 1;

(cid:2) Lệnh if nào sẽ ñi cùng với lệnh else? (cid:2) NN Java qui ñịnh lệnh if và lệnh else gần nhau nhất

sẽ ñi cùng nhau

(cid:1) Thí dụ trong Java if (sum == 0)

21

(cid:1) C, C++, C# yêu cầu dùng {} ñể phân ñịnh (cid:1) Perl yêu cầu câu lệnh ghép (if else ñầy ñủ)

Sự lựa chọn lòng nhau

(cid:1) C, C++, C#

if (sum == 0){

if (count == 0) result = 0;

(cid:1) Ada

}else result = 1;

if (sum == 0) then if (sum == 0) then

if (count == 0)then if (count == 0)then

result = 0; result = 0;

else end if

result = 1; else

end if result = 1;

22

end if end if

Lệnh lựa chọn ña nhánh

nhánh lệnh ñể thực hiện

(cid:1) Cho phép lựa chọn 1 nhánh trong số nhiều

nó thực hiện lệnh gì?

23

(cid:1) Các yếu tố trong lệnh lựa chọn ña nhánh (cid:2) Kiểu và dạng của biểu thức ñiều khiển là gì? (cid:2) Công việc của từng nhánh lệnh là gì? (cid:2) Có nhánh lệnh không thỏa ñiều kiện không? Nếu có

Mô hình switch-case

switch (expr){

case const_expr_1 : stmt_1; … case const_expr_n : stmt_n; [default: stmt_n+1;]

}

(cid:1) Switch-case trong C, C++, Java

(cid:2) Biểu thức ñiều khiển phải là kiểu nguyên (cid:2) Câu lệnh ñược chọn có thể 1 câu lệnh ñơn hoặc lệnh hợp

thành

(cid:2) Default : ñược chọn nếu không có giá trị nào thỏa expr

24

Mô hình switch-case

(cid:1) Switch-case trong Ada case expression is

when choice list => stmt_sequence; … when choice list => stmt_sequence; when others => stmt_sequence;]

end case;

trường hợp ñược chọn

25

(cid:1) Dễ ñọc hơn switch-case của C (cid:1) C# chỉ cho phép thực hiện 1 lệnh ñơn trong

Chọn ña nhánh với lệnh if

chọn 2 nhánh với else-if if (expr == const_expr_1 ) stmt_1; else if (expr == const_expr_2) stmt_2 … Else if (expr == const_expr_n) stmt_n; else stmt_n+1; (cid:2) Phải kết với hợp với lệnh nhảy (goto) (cid:2) Code rất nghèo nàng

26

(cid:1) Lệnh chọn ña nhánh có thể chuyển thành lệnh

Lệnh lặp

lệnh hợp thành

(cid:1) Lệnh lặp là ñể thực hiện một số lần lệnh ñơn hay

(cid:2) Làm thể nào ñể kiểm soát lặp? (cid:2) Kiểm soát lặp xuất hiện ở ñâu trong vòng lặp?

27

(cid:1) Các yếu tố trong lệnh lặp

Lệnh lặp với bộ ñếm

(cid:1) Lệnh có 1 biến ñếm, giá trị của biến này từ giá trị bắt ñầu (initial) ñến giá trị kết thúc (terminal) và giá trị của bước nhảy (stepsize)

(cid:2) Biến lặp có kiểu gì và phạm vi nào? (cid:2) Giá trị của biến lặp khi vòng lặp kết thúc là bao nhiêu? (cid:2) Giá trị của biến lặp có ñược thay ñổi trong thân vòng lặp không? Nếu có thì có ảnh hưởng ñến vòng lặp không?

28

(cid:1) Các yếu tố trong lệnh lặp :

VD - lệnh lặp với bộ ñếm

(cid:2) do bien_lap = trị_bat_dau, trị_ket_thuc [, buoc_nhay] (cid:2) Trị của bước nhảy là bất kỳ (trừ 0), mặc ñịnh 1 (cid:2) trị_bat_dau, trị_ket_thuc có thể là biểu thức (cid:2) Kiểu của biến lặp phải là kiểu số nguyên (cid:2) Biến lặp không ñược thay ñổi trong thân vòng lặp

(cid:1) Cú pháp của Fortran 90

(cid:2) do bien_lap = trị_bat_dau, trị_ket_thuc [, buoc_nhay]

(cid:1) Fortran 95

… end do

29

VD - lệnh lặp với bộ ñếm (tt)

(cid:1) Cú pháp lệnh for của Pascal

for bien_lap := bat_dau (to|downto)

ket_thuc do …

(cid:2) bien_lap có kiểu số nguyên (cid:2) Sau khi kết thúc vòng lặp, giá trị của bien_lap là không

xác ñịnh

(cid:2) Giá trị của bien_lap không thể thay ñổi trong thân vòng

lập;

(cid:2) bat_dau, ket_thuc có thể là biểu thức, nhưng các tham số có thể thay ñổi trong vòng lặp và không ảnh hưởng ñến vòng lặp

30

VD - lệnh lặp với bộ ñếm (tt)

(cid:2) for bien_lap in [reverse] day_roi_rac loop

(cid:1) Cú pháp lệnh for trong Ada

… end loop

(cid:2) day_roi_rac : miền con số nguyên, 1..10, hoặc kiểu

liệt kê monday..friday

(cid:2) Phạm vi của biến có bao gồm vòng lặp (cid:2) Giá trị của biến lặp là không xác ñinh sau khi vòng lặp

kết thúc

31

VD - lệnh lặp với bộ ñếm (tt)

(cid:1) Cú pháp của for trong C

for ([expr_1] ; [expr_2] ; [expr_3])

statement

(cid:2) Mọi thứ có thể thay ñổi trong thân vòng lặp (cid:2) Biểu thức expr_1 ñược ñịnh lượng 1 lần (trước khi thực hiện vòng lặp), expr_2 và expr_3 ñược ñịnh lượng ở mọi lần lặp

(cid:2) C++ : cho phép khai báo kiểu trong expr_1

(cid:1) For(int count =0; count

32

(cid:1) C++ vs C

Lệnh lặp có ñiều kiện

(cid:2) Kiểm tra ñiều kiện trước hay sau (cid:2) Có phải lệnh lặp có ñiều kiện là trường hợp ñặc biệt

của lệnh lặp với bộ ñếm

(cid:1) Lệnh lặp chỉ ñược thực hiện khi ñiều kiện ñúng (cid:1) Các yếu tố trong lệnh lặp có ñiều kiện

(cid:2) While (ctrl_expr) do

loop body loop body

while (ctrl_expr)

33

(cid:1) Cú pháp

Lệnh lặp có ñiều kiện (tt)

và sau : while-do và repeat-until (cid:1) C và C++ dùng cả (while-do and do-while); kiểm tra trước là lặp nếu ñiều kiện ñúng nhưng kiểm tra ñiều kiện sau là lặp ñến khi ñiều kiện sai (cid:1) Cũng giống như C, nhưng biểu thức ñiều kiện của

Java có kiểu boolean (cid:1) Ada chỉ có lặp kiểm tra trước

34

(cid:1) Pascal phân chia rõ ràng kiểm tra ñiều kiện trước

Rẽ nhánh không ñiều kiện

(cid:1) Lệnh rẽ nhánh không ñiều kiền ñược ñưa ra 1960s (cid:1) Cho phép thay ñổi thứ tự thực hiện chương trình (cid:1) Cơ chế phổ biến nhất là lệnh: goto

case

(cid:1) Một số NNLT không hỗ trợ lệnh goto (cid:1) C# cung cấp lệnh goto, có thể dùng trong switch-

bảo trì

35

(cid:1) Lệnh goto làm cho CT trở nên khó ñọc và khó

Luồng ñiều khiển không từng tự (Nonlocal control flow)

(cid:1) Cho phép thoát khỏi luồng ñiều khiển thông thường (cid:1) Ứng dụng

(cid:2) Thoát sớm trong các cấu trúc lặp (cid:2) Trả về (return) sớm trong các hàm (cid:2) Bắt các ngoại lệ

(cid:1) VD

(cid:2) Continue & break (cid:2) Return (cid:2) Try/catch

36

Lệnh continue & break

chuyển ñến vòng lặp tiếp theo

(cid:1) Lệnh continue sẽ kết thúc vòng lặp hiện hành và

của vòng lặp sẽ ñược bỏ qua

(cid:1) Khi gặp lệnh này, các câu lệnh còn lại trong thân

37

(cid:1) VD

Lệnh continue & break (tt)

(cid:1) Lệnh break ñể thoát khỏi các cấu trúc lặp hoặc switch

38

Lệnh return

39

Lệnh continue và break (Java)

block1: while (XXX) {

... while (XXX) {

... if (XXX) break block1;

}

} loop1: while (XXX) {

... while (XXX) {

... if (XXX) continue loop1;

}

40

}

Try/catch

(cid:1) Cú pháp try{

// ñoạn mã có khả năng gây ra ngoại lệ

} catch(Exception e1){

// Nếu các lệnh trong khối ‘try’ tạo ra ngoại lệ có loại e1

} … catch(Exception eN){

} Finally {

// khối lệnh nay luôn ñược thực hiện cho dù ngoại lệ có xảy ra hay không

}

41

Try/catch

try {

x = f(x,y);

} catch (ArithmeticException) {

System.out.println(”An arithmetic error

occurred!”);

System.exit(0);

} (cid:2) Nếu hàm f(x,y) không có lỗi, tiến trình vẫn tiếp tục (cid:2) Nếu hàm f(x,y) lỗi, ArithmeticException ñược

chuyển tới JVM

42

(cid:1) VD