Cấu trúc điều khiển
Khối câu lệnh
Khối câu lệnh là một dẫy các câu lệnh, đợc bao trong cặp dấu ngoặc nhọn. Nó
trông tựa nh thế này:
{
câu lệnh thứ nhất;
câu lệnh thứ hai;
câu lệnh thứ ba;
...
câu lệnh cuối;
}
Perl thực hiện từng câu lệnh theo trình tự, từ đầu đến cuối. (Về sau, tôi sẽ chỉ cho
bạn cách thay đổi trình tự thực hiện này bên trong khối, nhng hiện tại thì thế là đủ.)
Về mặt cú pháp, một khối các câu lệnh đợc chấp nhận ở mọi vị trí của một câu
lệnh.
Câu lệnh if/unless
Độ phức tạp tiếp theo trong các câu lệnh là câu lệnh if. Kết cấu này trông rất
giống kết cấu trong C: một biểu thức điều khiển (đợc tính theo tính đúng đắn của nó),
và hai khối. Nói cách khác, nó trông tựa nh thế này:
if (biểu thức nào đó) {
câu lệnh 1 trong trờng hợp đúng ;
câu lệnh 2 trong trờng hợp đúng ;
câu lệnh 3 trong trờng hợp đúng ;
} else {
câu lệnh 1 trong trờng hợp sai ;
câu lệnh 2 trong trờng hợp sai ;
câu lệnh 3 trong trờng hợp sai ;
}
(Nếu bạn thành thạo về C thì bạn sẽ chú ý rằng các dấu ngoặc nhọn là cần thiết.
Điều này khử bỏ nhu cầu về qui tắc else lòng thòng.)
Trong khi thực hiện, Perl sẽ tính biểu thức điều khiển. Nếu biểu thức này là đúng
thì khối thứ nhất (các câu lệnh trong trờng hợp đúng trên) sẽ đợc thục hiện. Nếu biểu
thức là sai thì khối thứ hai (các câu lệnh trong trờng hợp sai trên) sẽ đợc thực hiện.
Nhng đúng sai là nh thế nào? Trong Perl, các qui tắc có đôi chút hơi huyền ảo,
nhng chúng cho bạn kết quả nh dự kiến. Biểu thức điều khiển đwojc tính cho một giá
trị xâu (nếu nó đã là xâu, thì chẳng có thay đổi gì, nhng nếu nó là số thì nó sẽ đợc
chuyển thành xâu
*
). Nếu xâu này hoặc là xâu rỗng (chiều dài không), hoặc là một
xâu có chứa một kí tự 0 (không), thì giá trị của biểu thức là sai. Mọi thứ khác đều
đợc tự động coi nh là đúng. Tại sao lại có cái qui tắc buồn cời này vậy? Vì điều ấy
làm cho dễ dàng nhẩy theo cái rỗng
*
so với một xâu khác rỗng, cũng nh số không so
với số khác không, không cần phải tạo ra hai cách hiểu về các giá trị đúng và sai. Sau
đây là những thí dụ về cách hiểu đúng và sai:
0 # chuyển thành 0, cho nên là sai
1-1 # chuyển thành 0, rồi chuyển thành 0, cho nên là sai
1 # chuyển thành 1, nên là đúng
# xâu rỗng, cho nên là sai
1 # khong phải là hay 0, cho nên đúng
00 # không phải là hay 0, cho nên là đúng (trờng hợp này có
huyền ảo, xem mà xem)
0.000 # cũng đúng với cùng lí do và cảnh báo
undef # tính thành , cho nên sai
Về mặt thực hành mà nói, cách hiểu các giá trị đúng sai thì khá trực giác. Đừng
để tôi làm bạn sợ.
Sau đây là một thí dụ về câu lệnh if đầy đủ:
print Bạn bao nhiêu tuổi rồi?
$a = <STDIN>;
chop($a);
if ($a < 18) {
print Này, bạn cha đủ tuổi bầu cử đâu nhé, ấy?\n;
} else {
print Đủ tuổi rồi! H y bình thản! Vậy đi bầu cử đi!\n;ã
$voter++; # đếm số cử tri về sau
}
Bạn có thể cắt bỏ khối else, chỉ để lại phần then, nh trong:
print Bạn bao nhiêu tuổi rồi?
$a = <STDIN>;
chop($a);
if ($a < 18) {
print Này, bạn cha đủ tuổi bầu cử đâu nhé, ấy?\n;
}
Đôi khi, bạn muốn bỏ đi phần then mà chỉ có phần else, vì sẽ tự nhiên hơn để nói
*
*
Bên trong, điều này không hoàn toàn đúng. Nhng nó hành động giống nh đây là điều nó thực hiện.
*
*
Này, rỗng là ngoại trừ cho trờng hợp bệnh hoạn của một kí tự không đấy
hãy làm điều đó nếu điều này sai, so với làm điều đó nếu điều không điều này là
đúng. Perl giải quyết điều này với biến thể unless:
print Bạn bao nhiêu tuổi rồi?
$a = <STDIN>;
chop($a);
unless ($a < 18) {
print Đủ tuổi rồi! H y bình thản! Vậy đi bầu cử đi!\n;ã
$voter++;
}
Việc thay thế if bằng unless là có hiệu quả khi nói Nếu biểu thức điều khiển là
không đúng thì hãy làm... (một unless cũng có thể có một else, nh if.)
Nếu bạn có nhiều hơn hai chọn lựa thì bạn có thể thêm một nhánh elsif vào câu
lệnh if , giống nh:
if (biểu thức một nào đó) {
câu lệnh 1 trong trờng hợp đúng một;
câu lệnh 2 trong trờng hợp đúng một;
câu lệnh 3 trong trờng hợp đúng một;
} elsif (biểu thức hai nào đó ) {
câu lệnh 1 trong trờng hợp đúng hai;
câu lệnh 2 trong trờng hợp đúng hai;
câu lệnh 3 trong trờng hợp đúng hai;
} elsif (biểu thức ba nào đó ){
câu lệnh 1 trong trờng hợp đúng ba;
câu lệnh 2 trong trờng hợp đúng ba;
câu lệnh 3 trong trờng hợp đúng ba;
} else {
câu lệnh 1 trong trờng hợp sai tất cả ;
câu lệnh 2 trong trờng hợp sai tất cả;
câu lệnh 3 trong trờng hợp sai tất cả;
}
Mỗi biểu thức (ở đây, biểu thức một nào đó, biểu thức hai nào đó, và biểu thức ba nào
đó) đều đợc tính lần lợt. Nếu một biểu thức là đúng thì nhánh tơng ứng sẽ đợc thực
hiện, và tất cả phần còn lại của biểu thức điều khiển cũng các nhánh câu lệnh sẽ bị bỏ
qua. Nếu tất cả các biểu thức này đều sai thì nhánh else sẽ đợc thực hiện (nếu có).
Bạn có thể có nhiều nhánh elsif tuỳ ý.
Câu lệnh while/until
Không một ngôn ngữ thuật toán nào lại hoàn chỉnh mà không có một dạng lặp
nào đó (thực hiện lặp lại một khối các câu lệnh). Perl có thể lặp bằng việc dùng câu
lệnh while:
while (biểu thức nào đó) {
câu lệnh 1;
câu lệnh 2;
câu lệnh 3;
}
Để thựuc hiện câu lệnh while này, Perl tính biểu thức điều khiển (biểu thức nào đó
trong thí dụ này). Nếu giá trị này là đúng (bằng việc dùng ý tởng về cái đúng của câu
lệnh if), thì thân của câu lệnh while sẽ đợc tính một lần. Điều này đợc lặp lại cho tới
khi biểu thức điều khiển trở thành sai, tại điểm đó Perl chuyển sang câu lệnh tiếp sau
while. Chẳng hạn:
print Bạn bao nhiêu tuổi rồi?
$a = <STDIN>;
chop($a);
while ($a > 0) {
print Vào lúc này bạn mới $a tuổi.\n;
$a--;
}
Đôi khi nói hãy làm việc đó trong khi điều này sai lại dễ hơn là nói hãy làm
việc đó trong khi không điều này là đúng. Một lần nữa, Perl lại có câu trả lời. Thay
cho while là until, cũng cho kết quả mong muốn:
until (biểu thức nào đó) {
câu lệnh 1;
câu lệnh 2;
câu lệnh 3;
}
Chú ý rằng trong cả hai dạng while và until, các câu lệnh thân sẽ bị bỏ qua hoàn
toàn nếu biểu thức điều khiển là giá trị kết thúc nagy từ lúc bắt đầu. Chẳng hạn, nếu
ngời dùng đa vào một độ tuổi bé hơn không cho đoạn chơng trình trên thì Perl sẽ bỏ
qua thân chu trình.
Có thể là biểu thức điều khiển sẽ chẳng bao giờ để cho chu trình ra đợc. Điều này
hoàn toàn hợp pháp, và đôi khi cũng là mong muốn nữa, và do vậy không bị coi nh
một lỗi. Chẳng hạn, bạn có thể muốn một chu trình cứ lặp lại mãi chừng nào bạn còn
cha phạm phải lỗi, và rồi có một đoạn trình giải quyết lỗi đi theo sau chu trình. Bạn
có thể dùng điều này cho một việc quái quỉ cứ thế chạy hoài cho tới khi hệ thống sập.
Câu lệnh for
Một kết cấu lặp khác của Perl là câu lệnh for, mà trong giống nh câu lệnh for của
C, và làm việc thì đại thể cũng giống thế. Sau đây là nó:
for (biểu thức khởi đầu; biểu thức kiểm tra; biểu thức tăng) {
câu lệnh 1;
câu lệnh 2;
câu lệnh 3;
}
Gỡ ra theo dạng ta đã thấy trớc đây, điều này trở thành
biểu thức khởi đầu
while (biểu thức kiểm tra) {
câu lệnh 1;
câu lệnh 2;
câu lệnh 3;
biểu thức tăng
}
Trong cả hai trờng hợp, biểu thức khởi đầu đều đợc tính trớc. Biểu thức này về điển
hình chỉ gán giá trị ban đầu cho một biến lặp, nhng cũng chẳng có hạn chế nào về
việc nó có thể chứa cái gì - trong thực tế nó có thể rỗng (chẳng làm gì cả). Rồi biểu
thức kiểm tra sẽ đợc tính để xác định đúng sai. Nếu giá trị tính đợc là đúng thì thân
chu trình sẽ đợc tính, tiếp theo đó là tính biểu thức tăng (mà điển hình là đợc dùng để
tăng bộ lặp). Perl tiếp đó sẽ tính lại biểu thức kiểm tra, lặp lại khi còn cần.
Thí dụ này in ra các số từ 1 đến 10, mỗi số đều có sau nó một dấu cách:
for ($i = 1; $i <= 10; $i++)
print $i ;
}
Ban đầu, biến $i đợc đặt là 1. Rồi, biến này đợc so sánh với 10, mà thực sự nó
đang bé hơn hay bằng. Thân của chu trình (mỗi câu lệnh print) đợc thực hiện, và rồi
biểu thức tăng (biểu thức tự tăng $i++) sẽ đợc thực hiện, thay đổi giá trị trong $i
thành 2. Vì điều này vẫn còn bé hơn 10 nên ta lặp lại tiến trình, cho tới khi lần lặp
cuối mà giá trị 10 của $i đổi thành 11. Rồi điều này không còn bé hơn hay bằng 10
nữa, cho nên chu trình đi ra (với $i có giá trị 11).
Câu lệnh foreach
Vẫn còn một kết cấu lặp khác là câu lệnh foreach. Câu lệnh này rất giống nh câu
lệnh foreach của vỏ C: nó nhận một danh sách các giá trị và mỗi lần lại gán chúng cho
một biến vô hớng, rồi thực hiện một khối mã cùng với việc gán đó. Nó trông tựa nh
thế này:
foreach $i (@danh sách nào đó) {
câu lệnh 1;
câu lệnh 2;
câu lệnh 3;
}