24
2011
Bài 8 – Vòng lặp FOR, phức tạp nhưng đầy sức mạnh
(Bài học lên mạng ngày 24/03/2011) Có nhiều cách để tạo ra một cấu trúc lặp trong PHP, nhưng (theo cảm nhận cá nhân của tôi thì) FOR được sử dụng nhiều hơn cả. Điều này khá dễ hiểu vì FOR trong PHP rất mềm dẻo và có thể giúp bạn giải quyết được mọi bài toán cần sự hỗ trợ của vòng lặp.
Vòng lặp là gì?
Trong đời sống thường ngày, có những công việc lặp đi lặp lại như (ngay trước mặt tôi là) cái quạt bàn với tuýp lăng quay đang mở. Đầu tiên nó quay qua trái, đến “kịch đường biên” thì nó ngưng một chút rồi quay qua phải, “kịch đường biên” lại quay qua trái. Việc quay qua trái rồi quay qua phải như vậy sẽ được lặp đi lặp lại không ngừng nghỉ chừng nào nó… chưa bị hỏng và điện còn cung cấp!
Trái đất tự quay quanh trục của nó hết 24 tiếng đồng hồ, hay vòng tuần hoàn sáng – trưa – chiều – tối cũng là một định nghĩa về lòng vặp.
Vòng lặp là những công việc mà sau những khoảng thời gian nhất định sẽ thiết lập lại trạng thái / tính chất ban đầu.
Nhưng trong ngôn ngữ lập trình, vòng lặp đôi khi được hiểu theo những cách có thể khiến bạn thấy hơi xa lạ. Ví dụ, việc yêu cầu một đứa bé đếm từ 1 đến 10 cũng được coi là vòng lặp. Trong đó, hành động “đếm” được lặp đi lặp lại, có điều “số đếm” hay “âm thanh phát ra từ đứa bé” thì thay đổi sau mỗi lần lặp.
Giả sử có một bài tập, tôi cho các bạn một số n và yêu cầu bạn viết ra màn hình n dấu hoa thị (*) cho các trường hợp n=1/3/6 và 9. Khi này, bạn có thể dễ dàng thực hiện bằng các câu lệnh tương tự dưới đây:
Nhưng sẽ thế nào nếu tôi thay đổi đề bài đi một chút? Hãy viết ra màn hình n dấu hoa thị (*) tương ứng với số tự nhiên n được người dùng nhập vào từ bàn phím?
Đừng nghĩ đến việc dùng vòng lặp (vì chúng ta đã được học đâu). Thật may mắn vì PHP vẫn có cách giúp bạn xử lý việc này, đó là dùng hàm str_repeat (đây là nội hàm của PHP, cứ gọi là chạy thôi):
Tuy vậy, công việc sẽ trở nên “đầy thách thức” nếu đề bài được sửa cho “lắt léo” thêm một chút: Hãy nhập vào một số nguyên dương n và viết ra màn hình các câu đếm “Số thứ 1 / Số thứ 2 / Số thứ 3 …” cho đến “Số thứ n”.
Mặc dù đề bài không dùng chữ “lặp” nhưng chúng ta vẫn dễ dàng hình dung ra được đây là một công việc lặp đi lặp lại, và (cho dù có nhiều thủ thuật để xử lý việc này) cách đơn giản nhất vẫn là dùng… vòng lặp!
Cấu trúc lặp FOR trong ngôn ngữ PHP
Một cấu trúc lặp FOR tổng quát sẽ có dạng:
for(biểu thức 1 – BT1; biểu thức 2 – BT2; biểu thức 3 – BT3)
…….câu lệnh – CL;
Trong đó:
- BT1, BT2, BT3 và CL có thể… rỗng
- Nhưng dấu ; thì phải có
- BT1, BT2, BT3 có thể là các biểu thức kép, bằng cách viết nhiều biểu thức đơn và ngăn bằng dấu phẩy ,
- CL có thể là một khối câu lệnh bao bằng cặp dấu đóng mở ngoặc nhọn là { và }
Nếu các bạn chạy thử ví dụ này thì cửa sổ thông dịch sẽ bị “treo”, khi này bạn cần nhấn tổ hợp phím Ctrl+C để thoát. Vì, PHP đã rơi vào một vòng lặp vô tận, không có điểm dừng (tôi sẽ giải thích kỹ hơn ở phía dưới). Ví dụ này chỉ muốn minh hoạ cho ý “BT1, BT2, BT3 và CL có thể… rỗng nhưng dấu ; thì phải có”.
Bạn khoan quan tâm đến kết quả chạy chương trình, chỉ cần biết rằng chương trình chạy được và không có lỗi về cú pháp! Tôi đã dùng paint vẽ thêm các “đường bao” để các bạn phân biệt rõ BT1, BT2 và BT3. Các bạn sẽ dễ dàng nhận thấy trong các biểu thức này gồm có nhiều biểu thức con phân cách nhau bằng dấu phẩy , và các biểu thức con này rất “lung tung”, “hồn nhiên” hoàn toàn không cần phải tuân theo quy tắc hay ràng buộc gì với nhau hết cả (miễn nó đừng vi phạm các quy tắc về biến, hàm, biểu thức do PHP quy định).
Phía dưới là một khối lệnh gồm có 4 lệnh con: 2 câu lệnh echo và 2 câu lệnh gán. Các câu lệnh này cũng… linh tinh lang tang nốt, chẳng liên hệ gì với nhau và cũng chẳng liên hệ gì tới các câu lệnh trong phần biểu thức.
Ví dụ vd4.php giúp minh hoạ cho ý “BT1, BT2, BT3 có thể là các biểu thức kép, bằng cách viết nhiều biểu thức đơn và ngăn bằng dấu phẩy , CL có thể là một khối câu lệnh bao bằng cặp dấu đóng mở ngoặc nhọn là { và }”.
FOR hoạt động thế nào?
for(BT1; BT2; BT3)
…….CL;
- Đầu tiên, BT1 được thực thi một lần duy nhất;
- Sau đó BT2 được thực thi, nếu BT2 có giá trị true thì CL được thực thi, còn nếu BT2 có giá trị false thì kết thúc vòng lặp
- Sau đó BT3 được thực thi; và lặp lại bước 2
Hoạt động của vòng lặp for có thể hình dung đơn giản thế này:
Như vậy, vòng lặp sẽ là BT2 – CL – BT3 – BT2 – CL… Vòng lặp này sẽ kết thúc (ngưng lặp) khi BT2 có giá trị false. Ví dụ, để viết ra màn hình số đếm từ 1 đến 5, ta có thể dùng vòng lặp như sau:
Với lưu ý rằng $i=$i+1 có thể viết gọn thành $i++, các bạn cũng có thể dùng FOR để “vẽ hình” bằng ký tự như thế này:
Có 2 chú ý mà các bạn nên ghi nhớ:
- Do BT2 có thể gồm nhiều biểu thức đơn ngăn cách bởi dấu phẩy , nên PHP chỉ tính giá trị của biểu thức này là TRUE hay FALSE dựa vào biểu thức đơn cuối cùng.
- Bên trong khối câu lệnh CL, các bạn có thể dùng câu lệnh break; để “nhảy ra khỏi” vòng lặp bất chấp giá trị kế tiếp của biểu thức BT2 là TRUE hay FALSE;
Ví dụ vd7.php dưới đây sẽ giúp bạn hình dung tổng quát về những vấn đề chúng ta đã nói ở phía trên:
Cấu trúc lặp FOR và vấn đề xử lý chuỗi
Các bạn đã biết, đã thao tác nhiều với dữ liệu kiểu chuỗi (văn bản) có dạng $str = ‘Xin chao the gioi!’; Nhưng bạn có biết, chuỗi là kiểu dữ liệu đặc biệt mà bạn có thể truy xuất đến từng ký tự bên trong nó bằng cách viết tên biến kèm theo vị trí ký tự thế này $str[0], $str[1]
Qua ví dụ vd8.php, chỉ cần tinh ý một chút các bạn sẽ nhận ra rằng:
- Ký tự đầu tiên của chuỗi được coi là ký tự ở vị trí thứ… 0 (thay vì thứ 1)
- Nếu chạy một vòng lặp từ ký tự thứ 0 đến ký tự thứ chiều_dài_chuỗi trừ đi 1, thì chúng ta sẽ truy xuất được từ đầu chuỗi đến cuối chuỗi.
Như thế này chẳng hạn:
Ở ví dụ này, chúng ta dùng hàm strlen($str) để xác định độ dài chuỗi $str. Tuy nhiên, do biểu thức BT2 được thực thi trong suốt quá trình lặp nên việc đưa lời gọi hàm strlen($str) vào BT2 như ví dụ trên là chưa tối ưu trong viết code. Vì như vậy, cứ mỗi lần lặp đi lặp lại, PHP lại phải thực hiện lời gọi hàm strlen($str) để tìm xem giá trị độ dài chuỗi là bao nhiêu, trong khi con số này là không đổi và chỉ cần thực hiện 1 lần duy nhất như ví dụ dưới đây:
Bài tập:
Bài 8.1 – Chuỗi $str bắt đầu từ ký tự $str[0] và kết thúc ở ký tự thứ $str[strlen($str)-1]. Vậy bạn có biết ký tự $str[-1] và $str[strlen($str)] mang giá trị gì không? Hãy giải thích tại sao nó lại có giá trị như vậy?
Bài 8.2 – Cho người dùng nhập vào một chuỗi (nói tắt là “nhập chuỗi”), in ra màn hình giá trị in hoa của chuỗi này bằng 2 cách không dùng FOR và có dùng FOR.
Bài 8.3 – Nhập chuỗi, in ra màn hình giá trị in thường của chuỗi này bằng 2 cách không dùng FOR và có dùng FOR.
Bài 8.4 – Nhập chuỗi, in ra màn hình chuỗi sau khi đã cắt bỏ hết các khoảng trắng (nếu có) ở bên trái (đầu) và bên phải (đít) của chuỗi bằng 2 cách không dùng FOR và có dùng FOR.
Bài 8.5 – Nhập chuỗi, “nắn” lại chuỗi cho đẹp bằng cách bỏ đi các khoảng trắng ở 2 đầu trái, phải của chuỗi; đồng thời xoá hết các khoảng trắng liên tiếp bên trong chuỗi sao cho chỉ còn lại một khoảng trắng. Ví dụ chuỗi “…..Hoc PHP……………Online…..that vui…..“ sẽ trở thành “Hoc PHP Online that vui”.
Bài 8.6 – Nhập số nguyên dương n, in ra màn hình tháp ngược như sau (giả sử n=5):
*****
****
***
**
*
Bài 8.7 – Nhập chuỗi, in ra màn hình banner quảng cáo với các dấu hoa thị * phủ xung quanh chuỗi dạng như sau (ví dụ chuỗi nhập vào là “Hello World”)
Bài 8.8 – Nhập chuỗi, in ra màn hình banner quảng cáo với các dấu kẻ khung phủ xung quanh chuỗi dạng như sau (ví dụ chuỗi nhập vào là “Hello World”)
Bài 8.9 – Nhập số n, in ra màn hình tháp số dạng như sau (giả sử n = 7):
1
12
123
1234
12345
123456
1234567
Bài 8.10 – Nhập số n, nếu n chẵn thì ngưng chương trình, nếu n lẻ thì in ra màn hình tháp hoa thị như sau (giả sử n = 7):
Bài 8.11 – Nhập chuỗi $str, nhập số nguyên dương n trong khoảng [1;5] và thực hiện mã hoá chuỗi $str bằng cách biến các ký tự trong chuỗi $str thành ký tự tương ứng có vị trí mã ASCII lớn hơn vị trí cũ n đơn vị. Bảng mã ASCII các bạn tìm hiểu ở Google. Hàm lấy mã ASCII của ký tự bất kỳ là ord($ky_tu). Hàm viết ra ký tự có mã ASCII $t là chr($t).
Download: Các ví dụ trong bài học
Leave a comment
Liên kết nhanh
Bài viết mới
- Bài 8 – Vòng lặp FOR, phức tạp nhưng đầy sức mạnh
- Bài 7 – Câu lệnh điều kiện rút gọn, câu lệnh điều kiện phức hợp & câu lệnh rẽ nhánh
- Thảo luận về bài tập 6
- Bài 6 – Câu lệnh điều kiện
- Thảo luận về bài tập 5
- Bài 5 – Hằng, biến biến và cách nhập dữ liệu từ bàn phím
- Thảo luận về bài tập 4 (tiếp theo)
- Thảo luận về bài tập 4
- Bài 4 – Biến và kiểu dữ liệu
- Thảo luận về bài tập 3
Phản hồi gần đây
- Thảo luận về bài tập 4 (tiếp theo) on
- Bài 2 – Lập trình web bằng PHP là gì? on
- Bài 2 – Lập trình web bằng PHP là gì? on
- Thảo luận về bài tập 3 on
- Thảo luận về bài tập 2 on
- Bài 1 – Một số cam kết trước khi học lập trình on
- Bài 1 – Một số cam kết trước khi học lập trình on
- Bài 2 – Lập trình web bằng PHP là gì? on
- Bài 1 – Một số cam kết trước khi học lập trình on
- Bài 1 – Một số cam kết trước khi học lập trình on
0 nhận xét:
Đăng nhận xét