3.2.1 Câu lệnh if
Cấu trúc rẽ nhánh sử dụng câu lệnh if cho phép lựa chọn thực hiện hành động dựa trên giá trị của biểu thức điều kiện theo cú pháp sau đây:
if (<biểu thức điều kiện>) <câu lệnh 1> [else <câu lệnh2>]
trong đó:
- <biểu thức điều kiện> là biểu thức logic có kết quả trả về là sai (0, false) hoặc đúng (khác 0, true).
- Phần else là không bắt buộc phải có; câu lệnh if không có phần else được gọi là câu lệnh if thiếu, câu lệnh if có phần else gọi là câu lệnh if đầy đủ
- <câu lệnh 1>, <câu lệnh 2> là câu lệnh hợp lệ bất kỳ; < câu lệnh 1> được thực hiện khi <biểu thức điều kiện> cho kết quả đúng, ngược lại, < câu lệnh 2> được thực hiện
Lưu đồ câu lệnh if đầy đủ như hình sau:
Trình tự thực hiện câu lệnh if đầy đủ:
Bước 1: Tính giá trị <Biểu thức điều kiện>
Bước 2: Nếu <Biểu thức điều kiện> có giá trị đúng (true hoặc khác 0) thì thực hiện <câu lệnh 1> trong phần if, ngược lại (<Biểu thức điều kiện> có giá trị sai (false hoặc bằng 0) thì thực hiện <câu lệnh 2> trong phần else (nếu có).
39
Bước 3: Chuyển quyền điều khiển sang câu lệnh kế tiếp sau lệnh if đầy đủ.
Ví dụ 3.2. Thuật toán giải phƣơng trình ax + b = 0
float a, b, x;
printf(“Nhap hai so a, b: ”); scanf(“%f%f”, &a, &b); if (a == 0)
if (b == 0) printf(“Vo so nghiem.\n”); else printf(“Vo nghiem.\n”);
else {
x = -b/a;
printf(“Mot nghiem x = %8.2f\n”, x); }
Chú ý:
- Câu lệnh if thiếu và câu lệnh if đầy đủ là một câu lệnh đơn
- <Biểu thức điều kiện> sau từ khóa if phải được viết trong cặp dấu ngoặc đơn - Trong trường hợp <câu lệnh> là khối lệnh gồm nhiều câu lệnh, cần đặt chúng
trong cặp móc nhọn {<khối lệnh>}
Ví dụ 3.3. Khối lệnh gồm nhiều câu lệnh
So sánh ba đoạn chương trình sau đây: - Đoạn chương trình 1
int a = 0, x =1, y = 1; if (a>0) {
x++; y++; }
printf("x = %d; y = %d\n", x, y); //Xuat “x = 1, y = 1” - Đoạn chương trình 2
int a = 0, x =1, y = 1; if (a>0) x++;
y++; //x++ nam trong nhanh a>0, y++ nam ngoai. printf("x = %d; y = %d\n", x, y); //Xuat “x = 1, y = 2” - Đoạn chương trình 3
int a = 0, x =1, y = 1; if (a>0) x++;
y++; //cau truc if da ket thuc else x+=2; //loi bien dich tai else printf("x = %d; y = %d\n", x, y);
40
Nhận xét:
- Đoạn chương trình 1: hai câu lệnh x++ và y++ nằm trong cấu trúc if, được thực hiện khi a>0.
- Đoạn chương trình 2: câu lệnh x++ nằm trong cấu trúc if, được thực hiện khi a>0; câu lệnh y++ nằm ngoài cấu trúc if, được thực hiện sau đó.
- Đoạn chương trình 3: câu lệnh x++ nằm trong cấu trúc if, được thực hiện khi a>0; câu lệnh y++ nằm ngoài cấu trúc if, được thực hiện sau đó; cấu trúc if đã kết thúc (if thiếu). Sự xuất hiện của else sau đó gây ra lỗi biên dịch.
Chú ý:
- Câu lệnh if có thể lồng vào nhau và else sẽ tương ứng với if gần nó nhất; giữa một cặp if … else chỉ có duy nhất một khối lệnh.
- Nên dùng else để loại trừ trường hợp.
Ví dụ 3.4. Xếp loại học lực theo điểm tổng kết (DTK)
So sánh hai đoạn chương trình:
- Sử dụng các câu lệnh if thiếu một cách độc lập (1): if (DTK < 5) printf("Hoc luc yeu\n");
if (DTK >= 5 && DTK < 7) printf("Hoc luc trung binh\n"); if (DTK >= 7 && DTK < 8) printf("Hoc luc kha\n");
if (DTK >= 8) printf("Hoc luc yeu\n"); - Sử dụng câu lệnh if đầy đủ lồng vào nhau (2):
if (DTK < 5) printf("Hoc luc yeu\n");
else if (DTK < 7) printf("Hoc luc trung binh\n"); else if (DTK < 8) printf("Hoc luc kha\n");
else printf("Hoc luc yeu\n"); Nhận xét:
- Đoạn chương trình (1) yêu cầu thực hiện tất cả 4 câu lệnh if thiếu với 4 biểu thức điều kiện (tổng cộng có 6 toán tử quan hệ và 2 toán tử logic)
- Đoạn chương trình (2) yêu cầu thực hiện duy nhất 1 câu lệnh if đầy đủ lồng vào nhau, gồm 4 nhánh nhưng câu lệnh sẽ kết thúc khi có một trong số các biểu thức điều kiện có kết quả đúng (true hoặc khác 0). Trường hợp xấu nhất, nhánh else
41 cuối cùng được thực hiện. Như vậy, câu lệnh này thực hiện tối đa 3 toán tử quan hệ và không yêu cầu toán tử logic.
3.2.2 Câu lệnh switch
Một trường hợp đặc biệt của câu lệnh if đầy đủ lồng nhau, khi biểu thức điều kiện của mỗi nhánh là một phép so sánh giữa cùng một biểu thức với các giá trị thuộc kiểu rời rạc như số nguyên, ký tự. Khi đó, câu lệnh switch được sử dụng với cú pháp sau đây:
switch (<biểu thức>) {
case <giá trị 1>: <câu lệnh 1>; break;
case <giá trị 2>: <câu lệnh 2>; break; . . . .
case <giá trị n>: <câu lệnh n>; break;
default: <câu lệnh khác>; break; }
Với câu lệnh switch nói trên, tùy theo giá trị của <biểu thức> trùng khớp với <giá trị k> của nhánh case nào thì <câu lệnh k> tương ứng được thực hiện cho đến khi gặp lệnh break; thì thoát khỏi câu lệnh switch.
42
Trình tự thực hiện câu lệnh switch:
Bước 1: Tính giá trị <biểu thức>
Bước 2: Lần lượt so sánh giá trị của <biểu thức> vừa tính được với các giá trị <giá trị 1>, <giá trị 2>, … trong mỗi nhánh case. Nếu nhánh nào có sự trùng khớp thì <câu lệnh> tương ứng được thực hiện, cho đến khi gặp lệnh break. Nếu không có nhánh nào có giá trị trùng khớp với giá trị của <biểu thức> thì <câu lệnh khác> ở nhánh default được thực hiện.
Bước 3: Thoát khỏi câu lệnh switch, và chuyển quyền điều khiển sang câu lệnh kế tiếp.
Ví dụ 3.5. Số ngày của tháng (năm không nhuận)
#include <stdio.h> int main() { int th; //thang printf("Thang: "); scanf("%d", &th); switch (th) {
case 2: printf("So ngay: 28\n"); break;
case 4:
case 6:
case 9:
case 11: printf("So ngay: 30\n"); break; default: printf("So ngay: 31\n"); break; }
getchar(); return 0; }