Các Cấu Trúc Điều Khiển Chương Trình C (phần 3)
IV.6. Cấu trúc for
Đây cũng là toán tử điều khiển thực hiện lặp một số lệnh nào đó nhưng có cú pháp khác với hai chương trình lặp mà chúng ta đã xem xét ở phần trên, for trong C được dùng hết sức mềm dẻo nhưng nói chung nó sẽ trực quan và dễ hiểu hơn trong những tình huống lặp mà số bước lặp xác định. Trước khi trình bày cú pháp tổng quát của for chúng ta hãy xem xét một đoạn lệnh (in các kí tự từ ‘a’ tới ‘z’ và mã của chúng) như sau:
for0 printf“giatri;
đoạn lệnh trên có thể viết lại bằng chương trình
while là i =‘a’; while(i<=’z’) { printf“giatri; i++; }
Cú pháp for([bt_1]; [bt_2]; [bt_3]) S;
Trong đó S là một lệnh (đơn hoặc khối) được gọi là thân của vòng lặp, bt_1, bt_2, bt_3 là các biểu thức h ợp lệ, với ý nghĩa là: − bt_1: biểu thức khởi đầu − bt_2: biểu thức điều kiện - điều kiện lặp − bt_3: bước nhảy - thường dùng với ý nghĩa là thay đổi bước nhảy Cả 3 biểu thức này đều là tuỳ chọn, chúng có thể vắng mặt trong câu lệnh cụ thể nhưng các dấu chấm phẩy vẫn phải có. ¾ Hoạt động của for Hoạt động của for theo các bước sau:
b1: Thực hiện biểu thức khởi đầu - bt_1
b2: Tính giá trị bt_2 để xác định điều kiện lặp. Nếu bt_2 có giá trị ‘sai’ (==0) thì ra khỏi vòng lặp Ngược lại, nếu bt_2 có giá trị ‘đúng’ ( khác 0) thì chuyển tới bước 3
b3: Thực hiện lệnh S ( thân của for ), chuyển tới b4
b4: Thực hiện bt_3, rồi quay về b2.
ơn nữa mỗi thành phần (biểu thức) lại có thể là một hoặc nhiều biểu thức(đơn) phân cách nhau bởi dấu phẩy (,) ví dụ như:
Nếu <bt_1>, <bt_3> vắng mặt thì đơn thuần đó là các lệnh rỗng (không thực hiện gì), nếu chúng có nhiều biểu thức đơn cách nhau bởi dấu phẩy thì các biểu thức đơn đó được thực hiện tuần tự từ trái qua phải - thực ra vẫn có thể coi đây chỉ là một biểu thức, trong đó có các toán tử dấu phẩy (, ) và trật tự tính toán theo độ ưu tiên của các toán tử trong biểu thức. T ương tự như bt_1, bt_3; biểu thức điều kiện trong trường hợp nó chỉ gồm một biểu thức đơn thì giá trị của nó quyết định vòng lặp có còn được tiếp tục hay không, nhưng nếu nó có nhiều biểu thức đơn ví dụ như:
for2
printf“\ni=;
thì kết quả sẽ là: i=0, j=2 i=1, j=3 i=2, j=4 i=3, j=5
Như vậy vòng lặp dừng không theo điều kiện i <2 mà theo điều kiện j <6. Tức là giá trị của biểu thức bên phải nhất trong danh sách các biểu thức quyết định điều kiện của của vòng lặp – điều này do toán tử (, ) trả về toán hạng bên phải.
Ví dụ 6.1: Chương trình in các kí tự có mã từ 32 tới 255 trong bảng mã ASCII
1: #include <stdio.h>
2: void main(void)
3: {
4: int i;
5: for0
6: {
7: if -31 %10==0) printf("\n");
8: printf0;
9: }
10: getch0%10 ==0 thì chúng ta chuyển con trỏ xuống dòng mới (lệnh trên dòng 7)
– có nghĩa là cứ sau 10 bước thì chúng ta chuyển sang dòng mới, với mỗi i chúng ta in kí tự có mã là i cùng giá trị của nó (lệnh printf trên dòng 8).
Ví dụ 6.2: chương trình nhập n số nguyên từ bàn phím, tìm và in số lớn nhất, nhỏ nhất. Giải: Giả sử chúng ta có một dãy số a1, a2, .., an để xác định giá trị lớn nhất (gọi là max) và số nhỏ nhất (min)chúng ta thực hiện theo cách sau: 1. max = min = a1 ( xem một số đầu tiên là lớn nhất và cũng là nhỏ nhất) 2. i=2 3. nếu i > n thì thì kết thúc, ngược lại thì nếu ai > max thì max = ai ngược lại, nếu ai < min thì min =ai i =i+1 4. lặp lại bước 3
Khi kết thúc chúng ta có giá trị lớn nhất là max, giá trị nhỏ nhất là min. Nhưng cho tới bây giờ chúng ta chưa thể lưu được n số (trong yêu cầu này chúng ta cũng không cần phải lưu chúng) , vì thế chúng ta thực hiện theo phương pháp sau:
1: Nhập số thứ nhất từ bàn phím vào a
2: max = min = a ( xem một số đầu tiên là lớn nhất và cũng là nhỏ nhất)
3: i=2
4: nếu i > n thì thì kết thúc, ngược lại thì Nhập số thứ i từ bàn phím vào a nếu a > max thì max = a ngược lại, nếu a < min thì min =a i =i+1 5: lặp lại bước 4
Các bạn có chương trình như sau
#include <stdio.h>
#include <conio.h>
void main0;
scanf";
}while(n<1);
printf("Nhap so thu nhat : ");
scanf";
max=min=a;
for0 {
printf("Nhap so thu nhat : ");
scanf";
if(a>max) max=a;
else if(a<min) min =a;
}
printf"\ngiatrilonnhat=;
}
Ví dụ 6.3 : Viết chương trình giải bài toán sau: “Trăm trâu trăm cỏ Trâu đứng ăn năm Trâm nằm ăn ba Lụ khụ trâu già, ba con một cỏ hỏi mỗi loại có mấy con “ Giải: Rõ ràng là có ba loại trâu (phương trình ba ẩn) nhưng chỉ có hai phương trình đó là tổng số số trâu là 100 và tổng số cỏ cũng là 100. Chúng ta có d + n + g =100 (tổng số trâu) 5*d + 3 * n + g/3 =100 (tổng số cỏ) (d: số trâu đứng, n : số trâu nằm, g : số trâu già) Như vậy bài toán này không có nghiệm duy nhất, và nếu có thì chỉ lấy nghiệm là các số nguyên mà thôi.
Ở đây chúng ta sử dụng cách kiểm tra các bộ số gồm 3 số nguyên dương (d,n,g) tương ứng với số trâu của từng loại với d,n,g ∈ [1,..100], nếu thoả mãn hai phương trình trên thì đó là một nghiệm. Vậy ta thực hiện như sau: V ới d = 1 tới 20 // tối đa chỉ có 20 trâu đứng thì th ực hiện V ới n = 1 tới 33 // tối đa chỉ có 23 trâu nằm thực hiện g = 100 – d – n ; // số trâu già n ếu 0 và 0 thì in (d,n,g) là một nghiệm
#include <stdio.h>
#include <conio.h>
void main){ <;
printf("\nCac nghiem la\n");
printf("\ntrau_dung trau_nam trau_gia\n");
for0
for0
{
g=100-d-n;
if0&&0)
printf";
} }
• Chú ý : Ngoài các cấu trúc điều khiển chúng ta vừa nêu trên, trong ngôn ngữ C còn một cấu trúc điều khiển khác nữa là goto. Đây là lệnh nhảy không điều kiện tới một vị trí nào đó trong chương trình, vị trí đó được xác định bằng một nhãn (label).
Cú pháp goto <label>;
trong đó <label> là tên một nhãn hợp lệ. Khi gặp lệnh này điều khiển sẽ được chuyển tới lệnh tại vị trí tại nhãn <label>
Ví dụ: goto ketthuc; // với kết thúc là một nhãn Người ta chứng minh được là có thể dùng các cấu trúc điều khiển rẽ nhánh, lặp thay thế được goto, hơn nữa lạm dụng goto làm mất đi tính trong sáng và chặt chẽ của lập trình cấu trúc, do vậy trong giáo trình này chúng tôi không sử dụng goto.
IV.7. Câu lệnh continue và break
Trong thân của for cũng như các cấu trúc lặp khác, có thể có câu lệnh continue và break, với chức năng là:
• break : kết thúc vòng lặp (trong cùng) chứa nó. break cho ta khả năng kết thúc một vòng lặp từ một vị trí bên trong của vòng lặp mà không cần đến giá trị của biểu thức điều kiện. Nếu trong nhiều cấu trúc lặp lồng nhau thì break chỉ có tác dụng kết thúc một cấu trúc lặp trong cùng chứa nó mà thôi.
• continue: Trái với break, continue là câu lệnh có chức năng chuyển chu trình về đầu bước lặp tiếp theo. Có nghĩa là sẽ bỏ qua các lệnh trong thân của vòng lặp kể từ lệnh sau continue cho tới hết thân của vòng lặp. Nếu có nhiều cấu trúc lặp bao nhau thì lệnh continue cũng chỉ có tác dụng với cấu trúc lặp trong cùng chứa nó.
Chú ý: Trong for khi gặp continue thì các lệnh phía sau continue tới hết khối bị bỏ qua và chuyển tới thao tác thực hiện bt_3 ( bước nhảy) sau đó bắt đầu vòng lặp mới (kiểm tra điều kiện).
Ví dụ 6.4 : chương trình nhập số nguyên dương n từ bàn phím, tìm và in các ước của n và tổng các ước ra màn hình.
#include <stdio.h>
#include <conio.h>
void main){ <;
scanf";
}while(n<2);
printf"\nCacuoccua; for0
{
ifn continue;
printf";
tonguoc+=i;
}
printf"tongcacuocla;
}