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>
using namespace std;

int main() {
    int n;
    cout << "Nhap mot so nguyen: ";
    cin >> n;
    if (n % 2 == 0) {
        cout << n << " la so chan." << endl;
    } else {
        cout << n << " la so le." << endl;
    }
    return 0;
}
  • Ví dụ Output:

    Nhap mot so nguyen: 10
    10 la so chan.
    Nhap mot so nguyen: 7
    7 la so le.
  • Giải thích:

    • Chúng ta nhập một số nguyên vào biến n.
    • Điều kiện trong câu lệnh ifn % 2 == 0.
      • n % 2: Đây là toán tử số học chia lấy dư. Nó tính phần dư khi n chia cho 2.
      • == 0: Đây là toán tử so sánh bằng. Nó so sánh kết quả của n % 2 với 0.
    • Kết quả của toàn bộ biểu thức n % 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>
using namespace std;

int main() {
    double a, b, c;
    cout << "Nhap do dai 3 canh cua tam giac: ";
    cin >> a >> b >> c;
    if (a + b > c && a + c > b && b + c > a) {
        cout << "Day la mot tam giac." << endl;
        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;
}
  • Ví dụ Output:

    Nhap do dai 3 canh cua tam giac: 3 4 5
    Day la mot tam giac.
     -> Tam giac thuong.
    Nhap do dai 3 canh cua tam giac: 5 5 5
    Day la mot tam giac.
     -> Tam giac deu.
    Nhap do dai 3 canh cua tam giac: 2 2 3
    Day la mot tam giac.
     -> Tam giac can.
    Nhap do dai 3 canh cua tam giac: 1 2 5
    Day khong phai la mot tam giac hop le.
  • 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>
using namespace std;

int main() {
    double ds;
    string lk;
    double tlg = 0.0;

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

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

    if (lk == "Vip" && ds >= 5000000) {
        tlg = 0.15;
    } else if (lk == "Vip") {
        tlg = 0.10;
    } else if (lk == "Thuong" && ds >= 2000000) {
        tlg = 0.05;
    } else {
        tlg = 0.0;
    }

    double stg = ds * tlg;
    double tpt = ds - stg;

    cout << "Doanh so: " << ds << " VND" << endl;
    cout << "Loai khach hang: " << lk << endl;
    cout << "Ty le giam gia: " << (tlg * 100) << "%" << endl;
    cout << "So tien duoc giam: " << stg << " VND" << endl;
    cout << "Tong tien phai tra: " << tpt << " VND" << endl;

    return 0;
}
  • Ví dụ Output:

    Nhap doanh so mua hang: 6000000
    Nhap loai khach hang (Vip/Thuong): Vip
    Doanh so: 6e+06 VND
    Loai khach hang: Vip
    Ty le giam gia: 15%
    So tien duoc giam: 900000 VND
    Tong tien phai tra: 5.1e+06 VND
    Nhap doanh so mua hang: 1500000
    Nhap loai khach hang (Vip/Thuong): Vip
    Doanh so: 1.5e+06 VND
    Loai khach hang: Vip
    Ty le giam gia: 10%
    So tien duoc giam: 150000 VND
    Tong tien phai tra: 1.35e+06 VND
    Nhap doanh so mua hang: 2500000
    Nhap loai khach hang (Vip/Thuong): Thuong
    Doanh so: 2.5e+06 VND
    Loai khach hang: Thuong
    Ty le giam gia: 5%
    So tien duoc giam: 125000 VND
    Tong tien phai tra: 2.375e+06 VND
    Nhap doanh so mua hang: 1000000
    Nhap loai khach hang (Vip/Thuong): Thuong
    Doanh so: 1e+06 VND
    Loai khach hang: Thuong
    Ty le giam gia: 0%
    So tien duoc giam: 0 VND
    Tong tien phai tra: 1e+06 VND
  • Giải thích:

    • Chúng ta nhập ds (số thực) và lk (chuỗi).
    • Chuỗi if-else if-else được sử dụng để kiểm tra các điều kiện khác nhau:
      • lk == "Vip" && ds >= 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.
      • lk == "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.
      • lk == "Thuong" && ds >= 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 tlg 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>
using namespace std;

int main() {
    double dtb;
    cout << "Nhap diem trung binh (thang 10): ";
    cin >> dtb;
    int dmd = static_cast<int>(dtb);

    cout << "Diem trung binh: " << dtb << endl;
    cout << "Danh muc diem nguyen: " << dmd << endl;

    switch (dmd) {
        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:
            if (dtb >= 0 && dtb < 5) {
                 cout << "Hoc luc: Yeu" << endl;
            } else {
                 cout << "Diem khong hop le." << endl;
            }
            break;
    }
    return 0;
}
  • Ví dụ Output:

    Nhap diem trung binh (thang 10): 9.5
    Diem trung binh: 9.5
    Danh muc diem nguyen: 9
    Hoc luc: Xuat sac
    Nhap diem trung binh (thang 10): 8.0
    Diem trung binh: 8
    Danh muc diem nguyen: 8
    Hoc luc: Gioi
    Nhap diem trung binh (thang 10): 6.9
    Diem trung binh: 6.9
    Danh muc diem nguyen: 6
    Hoc luc: Trung binh
    Nhap diem trung binh (thang 10): 4.2
    Diem trung binh: 4.2
    Danh muc diem nguyen: 4
    Hoc luc: Yeu
    Nhap diem trung binh (thang 10): 11.0
    Diem trung binh: 11
    Danh muc diem nguyen: 11
    Diem khong hop le.
  • Giải thích:

    • Chúng ta nhập dtb (số thực).
    • Để dùng switch, chúng ta cần một giá trị nguyên. Biểu thức static_cast<int>(dtb) sử dụng é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 dmd 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.