Bỏ qua điều hướng, tới nội dung chính
Học C
Bài 5.312 phút đọc

else if

Sau bài này bạn sẽ làm được

  • Viết chuỗi else if cho bài toán phân loại
  • Giải thích vì sao thứ tự điều kiện quyết định kết quả
  • Nhận ra lỗi sắp xếp điều kiện sai chiều

Khi cần phân loại một giá trị vào nhiều nhóm, chuỗi else if là công cụ tự nhiên nhất. Nhưng nó có một đặc tính mà nếu không nắm sẽ dẫn tới kết quả sai hoàn toàn: thứ tự các điều kiện quyết định kết quả.

#Cú pháp

xep-loai.c
#include <stdio.h>

int main(void)
{
    double diem = 7.5;

    if (diem >= 8.5) {
        printf("Giỏi\n");
    } else if (diem >= 7.0) {
        printf("Khá\n");
    } else if (diem >= 5.0) {
        printf("Trung bình\n");
    } else {
        printf("Yếu\n");
    }

    return 0;
}

#Luồng chạy

Các điều kiện được kiểm tra lần lượt từ trên xuống. Gặp nhánh đúng đầu tiên là dừng, không xét tiếp.

Hai tính chất quan trọng của cấu trúc này:

  • Chỉ đúng một nhánh chạy. Ngay khi tìm được điều kiện đúng đầu tiên, các điều kiện còn lại không được kiểm tra nữa.
  • Có thể không nhánh nào chạy, nếu mọi điều kiện đều sai và không có nhánh else cuối.

Tính chất thứ nhất giúp bạn viết điều kiện gọn hơn. Ở nhánh diem >= 7.0, bạn không cần viết thêm && diem < 8.5, vì nếu điểm lớn hơn hoặc bằng 8,5 thì luồng đã dừng ở nhánh trước rồi.

Thừa và dễ sai
if (diem >= 8.5) {
    printf("Giỏi\n");
} else if (diem >= 7.0 && diem < 8.5) {
    printf("Khá\n");
} else if (diem >= 5.0 && diem < 7.0) {
    printf("Trung bình\n");
}

/* Điều kiện dư thừa. Tệ hơn, khi sửa ngưỡng 8.5
   bạn phải nhớ sửa ở HAI chỗ. */
Gọn và đúng
if (diem >= 8.5) {
    printf("Giỏi\n");
} else if (diem >= 7.0) {
    printf("Khá\n");
} else if (diem >= 5.0) {
    printf("Trung bình\n");
}

/* Mỗi ngưỡng chỉ xuất hiện một lần. */

#Thứ tự quyết định tất cả

Vì luồng dừng ở nhánh đúng đầu tiên, sắp xếp điều kiện sai thứ tự sẽ làm chương trình chạy sai mà không có cảnh báo nào.

Không nên
if (diem >= 5.0) {
    printf("Trung bình\n");
} else if (diem >= 7.0) {
    printf("Khá\n");        /* KHÔNG BAO GIỜ chạy */
} else if (diem >= 8.5) {
    printf("Giỏi\n");       /* KHÔNG BAO GIỜ chạy */
}

/* Điểm 9.0 thỏa mãn ngay điều kiện đầu tiên
   nên được xếp loại Trung bình. */
Nên
if (diem >= 8.5) {
    printf("Giỏi\n");
} else if (diem >= 7.0) {
    printf("Khá\n");
} else if (diem >= 5.0) {
    printf("Trung bình\n");
}

/* Điều kiện chặt nhất đứng trước. */

#Nhánh else cuối cùng

Nhánh else cuối không bắt buộc, nhưng thiếu nó thì có giá trị không rơi vào nhánh nào cả.

double diem = -5.0;   /* dữ liệu sai */

if (diem >= 8.5) {
    printf("Giỏi\n");
} else if (diem >= 7.0) {
    printf("Khá\n");
} else if (diem >= 5.0) {
    printf("Trung bình\n");
}

/* Không in gì cả. Người dùng không biết chuyện gì đã xảy ra. */

Khi nào nên chuyển sang switch

Nếu mọi điều kiện đều là so sánh bằng với một hằng số nguyên, thì switch ở bài 5.5 vừa dễ đọc hơn vừa có thể nhanh hơn.

/* Nên dùng switch */
if (lua_chon == 1) { }
else if (lua_chon == 2) { }
else if (lua_chon == 3) { }

/* Phải dùng else if, vì switch không so sánh khoảng được */
if (diem >= 8.5) { }
else if (diem >= 7.0) { }

Tự làm thử

  1. Viết hàm xếp loại học lực theo bốn mức, kiểm thử với đầy đủ giá trị biên.
  2. Cố tình sắp xếp sai thứ tự điều kiện, chạy thử với điểm 9.0 và quan sát kết quả.
  3. Viết lại hàm xếp loại dùng dấu nhỏ hơn thay vì dấu lớn hơn, chú ý đảo thứ tự.
  4. Viết chương trình phân loại chỉ số khối cơ thể theo năm mức, có kiểm tra dữ liệu đầu vào hợp lệ.
  5. Nhập một ký tự, phân loại thành chữ hoa, chữ thường, chữ số, khoảng trắng hoặc ký tự khác. Dùng else if.
  6. Viết chương trình tính tiền điện theo bậc thang, mỗi bậc một đơn giá khác nhau.

Trình chấm điểm tự động sẽ được bổ sung ở giai đoạn sau. Hiện tại bạn tự chạy thử trên máy.

Tóm tắt

  • else if không phải từ khóa riêng, nó là if lồng trong else với cách thụt lề gọn hơn.
  • Luồng dừng ở nhánh đúng đầu tiên, nên không cần viết điều kiện chặn hai đầu.
  • Thứ tự điều kiện quyết định kết quả. Điều kiện chặt nhất phải đứng trước.
  • Luôn có nhánh else cuối để không bỏ sót giá trị nào.
  • Kiểm thử bằng giá trị biên là cách chắc chắn nhất để bắt lỗi sắp xếp sai thứ tự.