Tải bản đầy đủ (.doc) (8 trang)

Ngôn ngữ Perl-Chương 03-Dữ liệu mảng và danh sách

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (153.81 KB, 8 trang )

Learning Perl - Chương 3: Dữ liệu mảng và Danh sách
1. Mảng
2. Biểu diễn hằng ký hiệu
3. Biến mảng
4. Các hàm và phép toán trên mảng
5. Hoàn cảnh vô hướng và mảng
6. <STDIN> như một mảng
7. Xen lẫn biến mảng
8. Bài tập
3.1 Mảng
Mảng là một danh sách có thứ tự các dữ liệu vô hướng. Mỗi phần tử của mảng đều là một biến
vô hướng tách biệt với một giá trị vô hướng độc lập. Các giá trị này là được sắp thứ tự - tức là
chúng có một trình tự đặc biệt từ phần tử thấp nhất đến cao nhất.
Mảng có thể có bất kì số phần tử nào. Mảng nhỏ nhất không có phần tử nào, trong khi mảng
lớn nhất thì có thể lấp kín toàn bộ bộ nhớ có sẵn.
3.2 Biểu diễn hằng kí hiệu
Một hằng kí hiệu mảng (cách thức bạn biểu diễn giá trị của một mảng bên trong chương trình)
là một danh sách các giá trị tách nhau bằng dấu phẩy và được bao trong dấu ngoặc tròn. Những
giá trị này tạo nên các phần tử của danh sách. Chẳng hạn:
(1,2,3) # mảng gồm ba giá trị 1, 2 và 3
("jerry", 4.5) # hai giá trị, "jerry" và 4.5
Các phần tử của mảng không nhất thiết là hằng - chúng có thể là biểu thức mà sẽ được tính mới
lại mỗi lần mảng được sử dụng. Chẳng hạn:
($a, 17) # hai giá trị: giá trị hiện tại của $a, và 17
($b+$c,$d+$e) # hai giá trị
Mảng rỗng (mảng không có phần tử nào) được biểu diễn bằng một cặp dấu ngoặc rỗng:
() # mảng rỗng (không phần tử)
Một phần tử của mảng có thể bao gồm toán tử cấu thành mảng, được chỉ ra bởi hai giá trị vô
hướng tách nhau bởi hai dấu chấm liên tiếp (..). Toán tử này tạo ra một danh sách các giá trị bắt
đầu tại giá trị vô hướng bên trái kéo cho tới gía trị vô hướng bên phải, mỗi lần tăng lên một.
Chẳng hạn:


(1..5) # giống như (1, 2, ,3 ,4, 5)
(1.2..5.2) # giống như (1.2, 2.2, 3.2, 4.2, 5.2)
(2..6,10,12) # giống như (2,3,4,5,6,10,12)
($a..$b) # phạm vi được xác định bởi giá trị hiện tại của $a và $b
Nếu giá trị vô hướng bên phải bé hơn vô hướng bên trái thì sẽ tạo ra danh sách rỗng - bạn
không thể đếm ngược trật tự của các giá trị. Nếu giá trị cuối cùng không phải là toàn bộ số
bước trên giá trị ban đầu thì danh sách sẽ dừng chỉ ngay trước giá trị tiếp mà sẽ vượt ra ngoài
phạm vi:
(1.3..6.1) # giống như (1.3, 2.3, 3.3, 4.3, 5.3)
Một cách dùng của hằng kí hiệu mảng là như tham số của toán tử print() đã được giới thiệu
trước đây. Các phần tử của danh sách này được in ra mà không có bất kì khoảng trống xen
thêm vào:
print ("Câu trả lời là ", $a, "\n");
Câu lệnh này in ra Câu trả lời là, theo sau bởi một dấu cách, giá trị của $a, và xuống dòng mới.
Ta hãy chuyển sang cách dùng khác cho hằng kí hiệu mảng.
3.3 Biến mảng
Một biến mảng giữ một giá trị mảng riêng. Các tên biến mảng là tương tự với các tên biến vô
hướng, chỉ khác kí tự khởi đầu, là một dấu @ chứ không phải là dấu $. Chẳng hạn:
@jerry # biến mảng @jerry
@A_Very_Long_Array_Variable_Name
@A_Very_Long_Array_Variable_Name_that_is_different
Lưu ý rằng biến mảng @jerry là không có quan hệ gì theo bất kì cách nào với biến vô hướng
$jerry. Perl duy trì không gian tên tách biệt cho các kiểu đối tượng khác nhau.
Giá trị của một biến mảng mà chưa được gán là (), danh sách rỗng.
Một biểu thức có thể tham khảo tới các biến mảng như một tổng thể, hoặc nó có thể xem xét và
thay đổi từng phần tử của mảng đó.
3.4 Các hàm và phép toán trên mảng
Các toán tử mảng hành động trên các mảng như một tổng thể. Một số toán tử mảng có thể cho
lại một giá trị mảng, mà có thể hoặc được dùng như một giá trị cho toán tử mảng khác, hoặc
được gán vào một biến mảng khác.

• 3.4.1 Phép gán
Có lẽ toán tử mảng quan trọng nhất là toán tử gán mảng, cho mảng một giá trị. Nó là dấu bằng,
giống như toán tử gán vô hướng. Perl xác định liệu phép gán có là phép gán vô hướng hay
phép gán mảng bằng việc để ý xem liệu phép gán là cho biến vô hướng hay mảng. Chẳng hạn:
@jerry = (1,2,3); # mảng jerry nhận ba phần tử 1, 2 và 3
@tom = @jerry; # bây giờ được sao sang @tom
Nếu một giá trị vô hướng được gán vào trong một biến mảng thì giá trị vô hướng trở thành
phần tử duy nhất của mảng:
@huh = 1; # 1 được đặt chuyển thành (1) và gán cho @huh
Tên biến mảng có thể xuất hiện trong danh sách hằng kí hiệu mảng. Khi giá trị của danh sách
được tính thì Perl thay thế tên biến mảng bằng giá trị hiện tại của mảng đó, giống vậy:
@jerry = ("một", "hai");
@tom = (4,5,@jerry, 6, 7); # @tom trở thành (4,5,"một","hai",6,7)
@tom = (8, @tom); # đặt 8 vào trước @tom
@tom = (@tom, “cuối”); # và "cuối" vào phía sau @tom
# @tom bây giờ là (8,4,5,"một","hai",6,7,"cuối")
Lưu ý rằng các phần tử mảng được thêm vào đều ở cùng mức như phần còn lại của hằng kí
hiệu - một danh sách không thể chứa một danh sách khác như một phần tử.
Nếu một mảng hằng kí hiệu chỉ chứa các tham khảo biến (không phải là biểu thức) thì mảng
hằng kí hiệu ấy cũng có thể được xử lí như một biến. Nói cách khác, một mảng hằng kí hiệu
như thế có thể được dùng ở vế bên trái của phép gán. Mỗi biến vô hướng trong mảng kí hiệu
nhận một giá trị tương ứng từ danh sách ở vế phải của phép gán. Chẳng hạn:
($a, $b, $c) = (1, 2, 3); # gán 1 cho $a, 2 cho $b, 3 cho $c
($a, $b) = ($b, $a); # tráo đổi $a và $b
($d, @jerry) = ($a, $b, $c); # gán $a cho $d, và ($b,$c) cho @jerry
($e, @jerry) = @jerry; # loại bỏ phần tử thứ nhất của @jerry là $e
# điều này làm cho @jerry = ($c) và $e = $b
Nếu số phần tử được gán không sánh đúng với số các biến để giữ các giá trị thì mọi giá trị vượt
quá (vế phải) đều bị loại bỏ, và bất kì biến vượt quá nào (ở vế trái của dấu bằng) đều được cho
giá trị undef.

Một biến mảng xuất hiện trong danh sách mảng hằng kí hiệu đều phải ở cuối, vì biến mảng nó
tiêu thụ tất cả các giá trị còn lại (bạn có thể đặt các biến khác sau nó, nhưng chúng sẽ chỉ nhận
giá trị undef mà thôi).
Nếu một biến mảng được gán cho một biến vô hướng thì số được gán là chiều dài của mảng,
như trong:
@jerry = (4, 5, 6); # khởi đầu @jerry mang giá trị (4,5,6)
$a = @jerry; # $a = 3, là số lượng các phần tử có trong @jerry
Chiều dài cũng được cho lại nếu một tên biến mảng được dùng trong hầu hết mọi chỗ mà một
giá trị vô hướng đang được cần tới. (Trong mục dưới đây có tên "Hoàn cảnh vô hướng mảng",
chúng ta sẽ thấy rằng điều này quả là được gọi như vậy với việc dùng tên mảng trong hoàn
cảnh vô hướng). Chẳng hạn, để lấy giá trị bé hơn chiều dài mảng một đơn vị, bạn có thể dùng
@jerry-1, vì toán tử trừ vô hướng cần các vô hướng cho cả hai toán hạng của nó. Chú ý điều
sau:
@jerry = (4, 5, 6); # khởi đầu @jerry mang giá trị (1,2,3)
$a = @jerry; # $a nhận chiều dài của @jerry (là 3)
($a) = @jerry; # $a nhận phần tử đầu tiên của @jerry (là 4)
Phép gán $a = đầu tiên là phép gán vô hướng, và do vậy @jerry được xem như một vô hướng,
cho lại chiều dài của nó. Phép gán thứ hai là phép gán mảng (cho dù chỉ một giá trị là cần tới),
và do vậy là phần tử đầu tiên của @jerry, bỏ đi tất cả phần còn lại.
Giá trị của phép gán mảng là chính bản thân giá trị mảng, và có thể được xếp tầng như bạn có
thể làm với các phép gán vô hướng. Chẳng hạn:
@jerry = (@tom = (2,3,4)); # @jerry và @tom mang giá trị (2,3,4)
@jerry = @tom = (2,3,4); # tương tự như trên
• 3.4.2 Truy cập các phần tử của mảng
Cho tới nay, chúng ta vẫn xử lí mảng như một tổng thể, thêm vào và bỏ bớt các giá trị bằng
việc thực hiện gán mảng. Nhiều chương trình có ích đã được xây dựng dùng mảng mà thậm chí
chẳng truy cập vào phần tử mảng nào. Tuy nhiên, Perl cung cấp toán tử chỉ số truyền thống để
tham khảo tới một phần tử mảng theo chỉ số. Với toán tử chỉ số mảng, các phần tử mảng đều
được đánh số bằng việc dùng số nguyên tuần tự, bắt đầu từ không và tăng lên một cho mỗi
phần tử. Phần tử đầu tiên của mảng @jerry mà được truy cập tới là $jerry[0]. Chú ý rằng @

trên tên mảng trở thành $ trên tham khảo phần tử. Đó là vì việc tham khảo tới một phần tử của
mảng xác định ra một biến vô hướng (một phần của mảng), mà có thể hoặc được gán cho, hoặc
có giá trị hiện tại của nó được dùng trong một biểu thức, kiểu như:
@jerry = (7,8,9);
$b = $jerry[0]; # đặt 7 vào $b (phần tử đầu tiên của @jerry)
$jerry[0] = 5; # bây giờ @jerry = (5,8,9)
Cũng có thể truy cập tới các phần tử khác cũng dễ tương tự, như trong:
$c = $jerry[1]; # gán $jerry[1] vào
$s, lúc này $c = 8
$jerry[2]++; # tăng 1 cho phần
tử thứ ba của @jerry
$jerry[1] += 4; # cộng 4 vào phần
tử thứ hai
($jerry[0], $jerry[1]) = ($jerry[1], $jerry[0]); # tráo đổi hai phần
tử đầu của @jerry
Việc truy cập vào một danh sách các phần tử từ cùng mảng (như trong thí dụ cuối) được gọi là
lát cắt, và thường xuất hiện đến mức có một cách biểu diễn đặc biệt cho nó:
@jerry[0,1] # tương tự như ($jerry[0], $jerry[1])
@jerry[0,1] = @jerry[1,0]; # tráo đổi hai phần tử đầu
@jerry[0,1,2] = @jerry[1,1,1]; # làm cho cả 3 phần tử đầu tiên giống phần tử
thứ hai
@jerry[1,2] = (9,10); # đổi hai giá trị cuối thành 9 và 10
Chú ý rằng lát cắt này dùng tiền tố @ chứ không là $. Điều này là vì bạn đang tạo ra một biến
mảng bằng việc chọn một phần của mảng chứ không phải là biến vô hướng chỉ thâm nhập vào
một phần tử.
Lát cắt cũng làm việc trên danh sách hằng kí hiệu, hay bất kì toán tử nào cho lại một giá trị
danh sách:
@who = ("jerry","tom","chip","dale")[2,3]; # @who = ("chip", "dale")
Các giá trị chỉ số trong những thí dụ này là các số nguyên hằng kí hiệu, nhưng chỉ số cũng có
thể là bất kì biểu thức nào cho lại một số, mà rồi được dùng để chọn phần tử thích hợp:

@jerry = (7,8,9);
$a = 2;
$b = $jerry[$a]; # $b = $jerry[2], hay giá trị 9
$c = $jerry[$a-1]; # $c nhận $jerry[1], hay 8
($c) = (7,8,9) [$a-1]; # tương tự như trên, nhưng dùng lát cắt
Vậy chương trình Perl có thể có việc thâm nhập mảng tương tự như các ngôn ngữ lập trình
truyền thống. Ý tưởng này về việc dùng một biểu thức cho chỉ số cũng có tác dụng cho các lát
cắt. Tuy nhiên bạn hãy nhớ rằng chỉ số cho lát cắt là một danh sách các giá trị, cho nên biểu
thức này là một biểu thức mảng, thay vì là một biểu thức vô hướng.
@jerry = (7,8,9); # như trong thí dụ trước
@tom = (2,1,0);
@backfred = @jerry[@tom]; # giống như @jerry[2,1,0], hay ($jerry[2],$jerry[1],
$jerry[0]), hay (9,8,7)
Nếu bạn thâm nhập vào một phần tử mảng bên ngoài hai đầu của mảng hiện tại (tức là một chỉ
số bé hơn không hay lớn hơn chỉ số của phần tử cuối cùng), thì giá trị undef sẽ được trả về mà
không có lời cảnh báo. Chẳng hạn:
@jerry = (1,2,3);
$tom = $jerry[7]; # $tom bây giờ là undef
Việc gán một giá trị bên ngoài đầu của mảng hiện tại sẽ tự động mở rộng mảng (cho một giá trị
undef cho tất cả các giá trị trung gian, nếu có). Chẳng hạn:
@jerry = (1,2,3);
$jerry[3] = "hi"; # @jerry bây giờ là (1,2,3,"h"”)
$jerry[6] = "ho"; # @jerry bây giờ là (1,2,3,"hi",undef,undef,"ho")
Bạn có thể dùng $#jerry để lấy giá trị chỉ số của phần tử cuối của @jerry (tương tự như trong
C-Shell). Bạn thậm chí còn có thể gán vào trong giá trị này để làm thay đổi chiều dài hiển
nhiên của @jerry, làm cho nó to lên hay co lại, nhưng điều đó nói chung là không cần thiết, vì
mảng thường to lên hay co lại một cách tự động.
• 3.4.3 Các toán tử push() và pop()
Một cách dùng thông dụng của mảng là như một chồng thông tin, nơi những giá trị mới được
thêm vào và lấy đi từ phía bên phải của danh sách. Những phép toán này thường xuất hiện đến

mức chúng có các hàm đặc biệt của riêng chúng:
push(@mylist,$newvalue); # giống @mylist = (@mylist, $newvalue)
$oldvalue = pop(@mylist); # lấy ra phần tử cuối của @mylist
Toán tử pop() trả về undef nếu tham số của nó là một danh sách rỗng.
Toán tử push() cũng chấp nhận một danh sách các giá trị cần được đẩy vào danh sách. Các giá
trị được đẩy vào cuối của danh sách. Chẳng hạn:
@mylist = (1,2,3);
push(@mylist,4,5,6); # @mylist = (1,2,3,4,5,6)
Chú ý rằng đối thứ nhất phải là một tên biến mảng - đẩy vào và lấy ra sẽ không có ý nghĩa với
danh sách hằng kí hiệu.
• 3.4.4 Các toán tử shift() và unshift()
Các toán tử push() và pop() làm việc ở bên "phải" của danh sách (phần với chỉ số cao nhất).
Tương tự thế, các toán tử unshift() và shift() thực hiện những hành động tương ứng về bên
"trái" của một danh sách (phần với chỉ số thấp nhất). Sau đây là vài thí dụ:

×