Bài 4.5: Bài tập thực hành kết hợp toán tử và rẽ nhánh trong C++

Chào mừng trở lại với series blog về C++ của FullhouseDev!

Chúng ta đã đi qua các khái niệm cơ bản về toán tử (như cộng, trừ, nhân, chia, so sánh, logic) và cấu trúc rẽ nhánh (if, else if, else). Mỗi khái niệm này đều quan trọng, nhưng sức mạnh thực sự của lập trình C++ thường nằm ở khả năng kết hợp chúng một cách linh hoạt.

Bài viết này không chỉ đơn thuần là lý thuyết, mà chúng ta sẽ cùng nhau thực hành qua các ví dụ cụ thể để thấy rõ cách toán tử tạo ra các điều kiện logic, và cấu trúc rẽ nhánh sử dụng chính những điều kiện đó để điều khiển luồng chạy của chương trình. Đây là nền tảng để xây dựng các chương trình có khả năng "suy nghĩ" và đưa ra quyết định dựa trên dữ liệu đầu vào.

Tại Sao Phải Kết Hợp?

Hãy hình dung bạn muốn viết một chương trình đơn giản để xác định xem một người có đủ tuổi để xem một bộ phim hay không.

  • Bạn cần lấy tuổi của người đó (nhập dữ liệu).
  • Bạn cần so sánh tuổi đó với tuổi quy định (sử dụng toán tử so sánh >).
  • Dựa trên kết quả so sánh (true hoặc false), bạn cần in ra thông báo thích hợp (sử dụng cấu trúc rẽ nhánh if/else).

Đây chính là một ví dụ kinh điển về sự kết hợp giữa toán tử và rẽ nhánh. Toán tử cung cấp kết quả của sự kiểm tra, còn rẽ nhánh quyết định hành động dựa trên kết quả đó.

Các Loại Kết Hợp Phổ Biến

Chúng ta thường kết hợp:

  1. Toán tử số học (+, -, *, /, %) với toán tử so sánh (==, !=, <, >, <=, >=) để tạo ra điều kiện.
    • Ví dụ: Kiểm tra xem (diem_ly + diem_hoa) / 2 >= 5.0 hay không.
  2. Toán tử so sánh tạo ra các giá trị boolean (true hoặc false).
    • Ví dụ: age >= 18.
  3. Toán tử logic (&&, ||, !) để kết hợp nhiều điều kiện boolean lại với nhau.
    • Ví dụ: Kiểm tra xem age >= 18 && has_ticket == true hay không.
  4. Cấu trúc rẽ nhánh (if, else if, else) nhận các giá trị boolean này làm điều kiện để thực thi khối lệnh tương ứng.

Thực Hành Qua Các Ví Dụ

Bây giờ, chúng ta sẽ đi sâu vào các bài tập thực hành cụ thể. Mỗi ví dụ sẽ tập trung vào một khía cạnh kết hợp khác nhau.

Ví Dụ 1: Kiểm Tra Số Chẵn/Lẻ

Đây là một bài tập cơ bản nhưng minh họa rõ ràng việc sử dụng toán tử số học (% - chia lấy dư) kết hợp với toán tử so sánh (==) trong câu lệnh if.

#include <iostream>

int main() {
    int number;

    cout << "Nhap mot so nguyen: ";
    cin >> number;

    // Su dung toan tu % va == de kiem tra dieu kien
    if (number % 2 == 0) {
        cout << number << " la so chan." << endl;
    } else {
        cout << number << " la so le." << endl;
    }

    return 0;
}
  • Giải thích:
    • Chúng ta nhập một số nguyên vào biến number.
    • Điều kiện trong câu lệnh ifnumber % 2 == 0.
      • number % 2: Đây là toán tử số học chia lấy dư. Nó tính phần dư khi number chia cho 2.
      • == 0: Đây là toán tử so sánh bằng. Nó so sánh kết quả của number % 2 với 0.
    • Kết quả của toàn bộ biểu thức number % 2 == 0 sẽ là true nếu số đó chia hết cho 2 (là số chẵn), và false nếu không (là số lẻ).
    • Câu lệnh if sẽ thực thi khối mã bên trong nó nếu điều kiện là true, ngược lại, khối mã trong else sẽ được thực thi.
Ví Dụ 2: Xác Định Loại Tam Giác Dựa Trên Độ Dài Ba Cạnh

Bài toán này phức tạp hơn một chút, đòi hỏi kết hợp toán tử so sánh và toán tử logic (&&). Chúng ta cần kiểm tra điều kiện tồn tại của tam giác trước, sau đó mới phân loại.

#include <iostream>

int main() {
    double a, b, c;

    cout << "Nhap do dai 3 canh cua tam giac: ";
    cin >> a >> b >> c;

    // Kiem tra dieu kien ton tai cua tam giac
    if (a + b > c && a + c > b && b + c > a) {
        cout << "Day la mot tam giac." << endl;

        // Phan loai tam giac sau khi biet no ton tai
        if (a == b && b == c) {
            cout << " -> Tam giac deu." << endl;
        } else if (a == b || a == c || b == c) {
            cout << " -> Tam giac can." << endl;
        } else {
            cout << " -> Tam giac thuong." << endl;
        }

    } else {
        cout << "Day khong phai la mot tam giac hop le." << endl;
    }

    return 0;
}
  • Giải thích:
    • Chúng ta nhập ba giá trị double cho độ dài ba cạnh a, b, c.
    • Điều kiện trong if đầu tiên (a + b > c && a + c > b && b + c > a) sử dụng:
      • Toán tử số học + để tính tổng hai cạnh.
      • Toán tử so sánh > để kiểm tra tổng hai cạnh có lớn hơn cạnh còn lại không.
      • Toán tử logic && (AND) để kết hợp ba điều kiện so sánh. Tam giác tồn tại chỉ khi cả ba điều kiện con đều đúng.
    • Nếu điều kiện tồn tại tam giác đúng, chương trình đi vào khối if và thực hiện phân loại (sử dụng các câu lệnh if/else if/else lồng nhau hoặc nối tiếp):
      • a == b && b == c: Sử dụng toán tử so sánh == và toán tử logic && để kiểm tra tam giác đều (ba cạnh bằng nhau).
      • a == b || a == c || b == c: Sử dụng toán tử so sánh == và toán tử logic || (OR) để kiểm tra tam giác cân (chỉ cần một trong ba cặp cạnh bằng nhau).
    • Khối else của if ngoài cùng được thực thi nếu điều kiện tồn tại tam giác là false.
Ví Dụ 3: Tính Tiền Giảm Giá Dựa Trên Doanh Số và Loại Khách Hàng

Ví dụ này minh họa việc sử dụng kết hợp nhiều loại toán tử và cấu trúc if-else if-else để xử lý nhiều trường hợp.

#include <iostream>
#include <string> // Can de su dung string

int main() {
    double doanh_so;
    string loai_khach_hang; // "Vip" hoac "Thuong"
    double ty_le_giam_gia = 0.0;

    cout << "Nhap doanh so mua hang: ";
    cin >> doanh_so;

    cout << "Nhap loai khach hang (Vip/Thuong): ";
    cin >> loai_khach_hang;

    // Su dung if-else if-else de xac dinh ty le giam gia
    // Ket hop toan tu so sanh (>, >=, ==) va logic (&&)
    if (loai_khach_hang == "Vip" && doanh_so >= 5000000) {
        ty_le_giam_gia = 0.15; // 15% cho khach Vip doanh so cao
    } else if (loai_khach_hang == "Vip") {
        ty_le_giam_gia = 0.10; // 10% cho khach Vip doanh so thap hon
    } else if (loai_khach_hang == "Thuong" && doanh_so >= 2000000) {
        ty_le_giam_gia = 0.05; // 5% cho khach Thuong doanh so cao
    } else {
        ty_le_giam_gia = 0.0; // Khong giam gia
    }

    double so_tien_giam = doanh_so * ty_le_giam_gia;
    double tong_tien_phai_tra = doanh_so - so_tien_giam;

    cout << "Doanh so: " << doanh_so << " VND" << endl;
    cout << "Loai khach hang: " << loai_khach_hang << endl;
    cout << "Ty le giam gia: " << (ty_le_giam_gia * 100) << "%" << endl;
    cout << "So tien duoc giam: " << so_tien_giam << " VND" << endl;
    cout << "Tong tien phai tra: " << tong_tien_phai_tra << " VND" << endl;

    return 0;
}
  • Giải thích:
    • Chúng ta nhập doanh_so (số thực) và loai_khach_hang (chuỗi).
    • Chuỗi if-else if-else được sử dụng để kiểm tra các điều kiện khác nhau:
      • loai_khach_hang == "Vip" && doanh_so >= 5000000: Kết hợp so sánh chuỗi (==) và so sánh số (>=) cùng với toán tử logic &&. Điều kiện này chỉ đúng khi cả hai phần đều đúng.
      • loai_khach_hang == "Vip": Chỉ kiểm tra loại khách hàng. Điều kiện này được kiểm tra chỉ khi điều kiện if phía trên nó là false.
      • loai_khach_hang == "Thuong" && doanh_so >= 2000000: Tương tự điều kiện đầu tiên, nhưng cho loại khách hàng "Thuong". Điều kiện này được kiểm tra chỉ khi tất cả các điều kiện if/else if phía trên nó đều là false.
      • Khối else cuối cùng bắt các trường hợp còn lại (ví dụ: khách hàng thường với doanh số dưới 2.000.000 VND).
    • Dựa vào điều kiện nào đúng đầu tiên, một ty_le_giam_gia phù hợp sẽ được gán.
    • Cuối cùng, toán tử số học *- được sử dụng để tính toán số tiền giảm và tổng tiền phải trả.
Ví Dụ 4: Sử Dụng switch Với Kết Quả Từ Toán Tử (Một Cách Tiếp Cận Khác)

Mặc dù switch thường hoạt động tốt nhất với các giá trị nguyên hoặc enum, chúng ta vẫn có thể sử dụng kết quả của một phép toán tử (nếu kết quả đó là số nguyên) để điều khiển cấu trúc switch. Ví dụ, phân loại học lực dựa trên điểm trung bình.

#include <iostream>

int main() {
    double diem_trung_binh;

    cout << "Nhap diem trung binh (thang 10): ";
    cin >> diem_trung_binh;

    // Chuyen doi diem trung binh sang thang nguyen de su dung trong switch
    // Day la mot ky thuat de "map" mot khoang gia tri sang mot so nguyen
    int danh_muc_diem = static_cast<int>(diem_trung_binh / 1.0); // Su dung toan tu / va ep kieu

    cout << "Diem trung binh: " << diem_trung_binh << endl;
    cout << "Danh muc diem nguyen: " << danh_muc_diem << endl; // De kiem tra

    // Su dung switch case de phan loai hoc luc
    switch (danh_muc_diem) {
        case 10:
        case 9:
            cout << "Hoc luc: Xuat sac" << endl;
            break;
        case 8:
            cout << "Hoc luc: Gioi" << endl;
            break;
        case 7:
            cout << "Hoc luc: Kha" << endl;
            break;
        case 6:
        case 5:
            cout << "Hoc luc: Trung binh" << endl;
            break;
        default:
            // Bao gom cac diem < 5 hoac > 10 (neu co loi nhap lieu)
            if (diem_trung_binh >= 0 && diem_trung_binh < 5) { // Van ket hop if de xu ly truong hop < 5
                 cout << "Hoc luc: Yeu" << endl;
            } else {
                 cout << "Diem khong hop le." << endl;
            }
            break;
    }

    return 0;
}
  • Giải thích:
    • Chúng ta nhập diem_trung_binh (số thực).
    • Để dùng switch, chúng ta cần một giá trị nguyên. Biểu thức static_cast<int>(diem_trung_binh / 1.0) sử dụng toán tử số học / và ép kiểu static_cast<int> để chuyển đổi điểm trung bình thành một số nguyên. Ví dụ: 9.5 -> 9, 8.2 -> 8, 6.0 -> 6.
    • Giá trị nguyên danh_muc_diem này sau đó được dùng trong câu lệnh switch.
    • Mỗi case tương ứng với một khoảng điểm đã được "map" vào số nguyên (10 và 9 cho Xuất sắc, 8 cho Giỏi, v.v.).
    • default bắt các trường hợp còn lại. Lưu ý: Trong default, chúng ta vẫn có thể sử dụng if để xử lý chi tiết hơn các trường hợp trong phạm vi đó (ví dụ: phân biệt điểm < 5 và điểm không hợp lệ khác).

Comments

There are no comments at the moment.