Bài 2.4: Bài tập thực hành rẽ nhánh cơ bản trong C++

Chào mừng bạn quay trở lại với hành trình chinh phục C++! Sau khi đã làm quen với việc nhập xuất dữ liệu cơ bản, đã đến lúc chúng ta học cách làm cho chương trình của mình trở nên linh hoạtthông minh hơn. Đó chính là lúc các cấu trúc rẽ nhánh phát huy tác dụng!

Bài viết này sẽ tập trung vào việc thực hành các câu lệnh rẽ nhánh cơ bản nhất trong C++: if, else if, else, và cả switch. Thông qua các ví dụ bài tập cụ thể, bạn sẽ thấy cách áp dụng chúng để đưa ra các quyết định khác nhau trong luồng thực thi của chương trình.

Không dài dòng nữa, chúng ta hãy cùng bắt tay vào code ngay nào!

Tại sao cần rẽ nhánh?

Hãy tưởng tượng bạn đang viết một chương trình tính tiền vé xem phim. Giá vé có thể khác nhau tùy theo độ tuổi: trẻ em (dưới 12 tuổi) giá X, người lớn (từ 12 đến 60 tuổi) giá Y, và người già (trên 60 tuổi) giá Z. Làm sao chương trình biết áp dụng giá nào? Nó cần kiểm tra tuổi của khách hàng và rẽ nhánh sang các đoạn mã tính giá khác nhau tương ứng. Đó chính là sức mạnh của rẽ nhánh!

Công cụ rẽ nhánh cơ bản trong C++

Chúng ta có các công cụ chính sau để thực hiện rẽ nhánh:

  1. if Statement: Thực thi một khối lệnh chỉ khi một điều kiện là đúng (true).
  2. if...else Statement: Thực thi khối lệnh này nếu điều kiện đúng, ngược lại thực thi khối lệnh khác.
  3. if...else if...else Statement: Kiểm tra nhiều điều kiện nối tiếp. Thực thi khối lệnh đầu tiên có điều kiện đúng. Nếu không có điều kiện nào đúng, thực thi khối lệnh trong else (nếu có).
  4. switch Statement: Một cách khác để rẽ nhánh khi bạn cần so sánh một biến với nhiều giá trị cố định khác nhau.

Bây giờ, hãy cùng thực hành với các ví dụ cụ thể!

Ví dụ 1: Kiểm tra số dương

Bài toán đơn giản nhất để bắt đầu với if.

Yêu cầu: Viết chương trình nhập vào một số nguyên và kiểm tra xem số đó có phải là số dương hay không. Nếu là số dương, in ra thông báo tương ứng.

Code:

#include <iostream> // Cần cho cin và cout

int main() {
    int num;

    cout << "Nhap mot so nguyen: ";
    cin >> num; // Nhap gia tri vao bien num

    // Kiem tra dieu kien: num co lon hon 0 khong?
    if (num > 0) {
        // Neu dieu kien (num > 0) la true, thuc thi doan code nay
        cout << num << " la so duong." << endl;
    }

    cout << "Ket thuc chuong trinh." << endl; // Dong nay luon duoc thuc thi

    return 0;
}

Giải thích:

  • Chương trình yêu cầu người dùng nhập một số và lưu vào biến num.
  • Câu lệnh if (num > 0) kiểm tra điều kiện num > 0. Đây là một biểu thức logic, kết quả của nó chỉ có thể là true (đúng) hoặc false (sai).
  • Nếu num lớn hơn 0 (ví dụ: bạn nhập 5), điều kiện num > 0true. Chương trình sẽ đi vào bên trong khối dấu ngoặc nhọn {} ngay sau if và thực thi lệnh cout << num << " la so duong." << endl;.
  • Nếu num không lớn hơn 0 (ví dụ: bạn nhập -3 hoặc 0), điều kiện num > 0false. Chương trình sẽ bỏ qua khối lệnh bên trong {} của if và tiếp tục thực thi từ dòng code ngay sau khối đó (ở đây là cout << "Ket thuc chuong trinh." << endl;).
  • Lưu ý: Dòng "Ket thuc chuong trinh." luôn được in ra, bất kể số bạn nhập là gì, vì nó nằm ngoài khối if.
Ví dụ 2: Kiểm tra chẵn hay lẻ

Sử dụng cấu trúc if...else để xử lý hai trường hợp đối lập.

Yêu cầu: Viết chương trình nhập vào một số nguyên và kiểm tra xem đó là số chẵn hay số lẻ.

Code:

#include <iostream>

int main() {
    int num;

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

    // Kiem tra dieu kien: so chia het cho 2?
    if (num % 2 == 0) {
        // Neu dieu kien (num % 2 == 0) la true (so chan)
        cout << num << " la so chan." << endl;
    } else {
        // Neu dieu kien tren la false (so le)
        cout << num << " la so le." << endl;
    }

    return 0;
}

Giải thích:

  • Chúng ta sử dụng toán tử modulo % để lấy số dư. num % 2 == 0 nghĩa là "số dư khi chia num cho 2 có bằng 0 không?". Điều này chính xác là cách kiểm tra một số có chẵn hay không.
  • Nếu điều kiện num % 2 == 0true, khối lệnh trong if được thực thi, in ra "la so chan".
  • Nếu điều kiện là false (tức là số dư khác 0 khi chia cho 2, chỉ có thể là 1 với số nguyên), chương trình sẽ tự động nhảy đến khối lệnh trong else và thực thi, in ra "la so le".
  • Với if...else, chắc chắn một trong hai khối lệnh sẽ được thực thi, không bao giờ cả hai, và không bao giờ không có khối nào được thực thi (trừ khi có lỗi runtime hoặc logic khác ngoài if-else này).
Ví dụ 3: Xếp loại học sinh theo điểm

Bài tập điển hình cho cấu trúc if...else if...else khi có nhiều hơn hai trường hợp.

Yêu cầu: Nhập điểm số (thang 10) của một học sinh và xếp loại:

  • Điểm >= 8: Giỏi
  • Điểm >= 6.5: Khá
  • Điểm >= 5: Trung bình
  • Dưới 5: Yếu

Code:

#include <iostream>

int main() {
    double diem; // Diem thuong la so thuc

    cout << "Nhap diem so (thang 10): ";
    cin >> diem;

    // Kiem tra dieu kien lan luot tu tren xuong
    if (diem >= 8) {
        cout << "Xep loai: Gioi" << endl;
    } else if (diem >= 6.5) {
        // Neu diem < 8 VA diem >= 6.5
        cout << "Xep loai: Kha" << endl;
    } else if (diem >= 5) {
        // Neu diem < 6.5 VA diem >= 5
        cout << "Xep loai: Trung binh" << endl;
    } else {
        // Neu diem < 5 (tat ca cac dieu kien tren deu sai)
        cout << "Xep loai: Yeu" << endl;
    }

    return 0;
}

Giải thích:

  • Cấu trúc if...else if...else cho phép kiểm tra nhiều điều kiện một cách tuần tự.
  • Chương trình kiểm tra điều kiện diem >= 8 trước.
    • Nếu đúng, in ra "Gioi" và bỏ qua tất cả các else ifelse còn lại, kết thúc khối rẽ nhánh.
  • Nếu điều kiện diem >= 8 sai, nó sẽ chuyển sang kiểm tra điều kiện trong else if đầu tiên: diem >= 6.5.
    • Nếu đúng (khi này, ta biết chắc chắn diem < 8), in ra "Kha" và bỏ qua các else if, else còn lại.
  • Quá trình này tiếp tục cho đến khi gặp một điều kiện đúng hoặc đến cuối.
  • Nếu tất cả các điều kiện trong ifelse if đều sai, khối lệnh trong else cuối cùng sẽ được thực thi (in ra "Yeu").
  • Thứ tự của các điều kiện rất quan trọng trong if...else if. Bạn nên đặt các điều kiện cụ thể hơn hoặc phạm vi hẹp hơn lên trước.
Ví dụ 4: Kiểm tra năm nhuận

Bài tập này sử dụng kết hợp các toán tử logic (&& - AND, || - OR) trong điều kiện rẽ nhánh.

Yêu cầu: Nhập một năm và kiểm tra xem đó có phải là năm nhuận hay không.

  • Năm nhuận là năm chia hết cho 400.
  • Hoặc, năm nhuận là năm chia hết cho 4 nhưng không chia hết cho 100.

Code:

#include <iostream>

int main() {
    int year;

    cout << "Nhap nam: ";
    cin >> year;

    // Dieu kien kiem tra nam nhuan:
    // (chia het cho 400) HOAC (chia het cho 4 VA khong chia het cho 100)
    if ((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)) {
        cout << year << " la nam nhuan." << endl;
    } else {
        cout << year << " khong phai la nam nhuan." << endl;
    }

    return 0;
}

Giải thích:

  • Điều kiện trong if sử dụng kết hợp các toán tử logic:
    • year % 400 == 0: Kiểm tra xem năm có chia hết cho 400 không.
    • year % 4 == 0: Kiểm tra xem năm có chia hết cho 4 không.
    • year % 100 != 0: Kiểm tra xem năm có KHÔNG chia hết cho 100 không.
    • && (AND): Kết hợp hai điều kiện. Biểu thức (year % 4 == 0 && year % 100 != 0) chỉ đúng khi cả hai điều kiện con đều đúng.
    • || (OR): Kết hợp hai biểu thức lớn. Điều kiện tổng thể ((year % 400 == 0) || (...)) chỉ đúng khi ít nhất một trong hai vế (vế chia hết cho 400, hoặc vế "chia hết cho 4 và không 100") là đúng.
  • Dấu ngoặc đơn () được sử dụng để nhóm các điều kiện con và làm rõ thứ tự ưu tiên của các toán tử logic (mặc dù && có ưu tiên cao hơn ||, việc dùng ngoặc giúp code dễ đọc hơn).
  • Nếu điều kiện tổng thể là true, khối if được thực thi. Ngược lại, khối else được thực thi.
Ví dụ 5: Sử dụng switch cho menu đơn giản

switch rất hữu ích khi bạn có một biến và muốn thực hiện các hành động khác nhau dựa trên giá trị cụ thể của biến đó.

Yêu cầu: Xây dựng một menu đơn giản cho phép người dùng chọn một trong các phép toán cơ bản (+, -, *, /) và thực hiện phép toán đó trên hai số.

Code:

#include <iostream>

int main() {
    char op; // Bien luu phep toan (+, -, *, /)
    double num1, num2; // Hai so de thuc hien phep toan

    cout << "Nhap phep toan (+, -, *, /): ";
    cin >> op;

    cout << "Nhap hai so: ";
    cin >> num1 >> num2;

    // Su dung switch de xu ly phep toan
    switch (op) {
        case '+': // Neu op co gia tri la '+'
            cout << num1 << " + " << num2 << " = " << num1 + num2 << endl;
            break; // Thoat khoi switch

        case '-': // Neu op co gia tri la '-'
            cout << num1 << " - " << num2 << " = " << num1 - num2 << endl;
            break; // Thoat khoi switch

        case '*': // Neu op co gia tri la '*'
            cout << num1 << " * " << num2 << " = " << num1 * num2 << endl;
            break; // Thoat khoi switch

        case '/': // Neu op co gia tri la '/'
            if (num2 != 0) { // Kiem tra truoc khi chia de tranh loi chia cho 0
                cout << num1 << " / " << num2 << " = " << num1 / num2 << endl;
            } else {
                cout << "Loi: Chia cho 0!" << endl;
            }
            break; // Thoat khoi switch

        default: // Neu op khong khop voi bat ky case nao
            cout << "Phep toan khong hop le!" << endl;
            // Khong can break o day vi day la case cuoi
    }

    return 0;
}

Giải thích:

  • Lệnh switch (op) sẽ so sánh giá trị của biến op với các giá trị trong các case.
  • Khi giá trị của op khớp với một case nào đó (ví dụ, bạn nhập '+'), chương trình sẽ bắt đầu thực thi từ dòng code ngay sau case '+':'.
  • Lệnh break; rất quan trọng trong switch. Nó làm chương trình thoát ra khỏi khối switch ngay lập tức sau khi thực thi xong case đó. Nếu thiếu break, chương trình sẽ tiếp tục thực thi các case tiếp theo (hiện tượng này gọi là "fall-through"), điều mà thường không mong muốn.
  • Trường hợp default: là tùy chọn. Nó sẽ được thực thi nếu giá trị của biến op không khớp với bất kỳ case nào được liệt kê.
  • Trong case '/', chúng ta có một câu lệnh if lồng bên trong để xử lý trường hợp người dùng cố gắng chia cho số 0, tránh gây ra lỗi runtime. Điều này cho thấy bạn có thể lồng ghép các cấu trúc điều khiển bên trong nhau.
Lưu ý quan trọng về khối lệnh

Trong C++, khi một câu lệnh rẽ nhánh (if, else, else if, case trong switch) chỉ cần thực thi một dòng code duy nhất, bạn có thể bỏ qua cặp dấu ngoặc nhọn {}. Ví dụ:

if (num > 0)
    cout << "So duong." << endl; // Chi mot dong, co the bo ngoac

Tuy nhiên, thực hành tốt được khuyến nghị là luôn sử dụng dấu ngoặc nhọn {} cho khối lệnh, ngay cả khi chỉ có một dòng. Điều này giúp code dễ đọc hơn, tránh sai sót khi bạn muốn thêm nhiều lệnh vào khối đó sau này.

Bài tập ví dụ: C++ Bài 2.A4: Số lớn nhất, số nhỏ nhất

cho 3 số nguyên \(a\), \(b\) và \(c\), hãy tìm xem số nào lớn nhất và số nào nhỏ nhất trong 3 số trên.

INPUT FORMAT

3 số nguyên \(a\), \(b\) và \(c\) cách nhau bởi 1 dấu cách \((-10^6 <= a, b, c <= 10^6)\).

OUTPUT FORMAT

Gồm 2 dòng: dòng đầu in ra số lớn nhất trong 3 số, dòng thứ 2 in ra số nhỏ nhất.

Ví dụ 1:

Input
1 2 3
Ouput
3
1

Ví dụ 2:

Input
3 3 3
Output
3
3

Giải thích ví dụ mẫu:

  • Ví dụ 1: Số lớn nhất là 3 và số nhỏ nhất là 1.
  • Ví dụ 2: Tất cả các số đều bằng 3, nên cả số lớn nhất và số nhỏ nhất đều là 3.

<br>

Hướng dẫn các bước thực hiện:

  1. Khai báo thư viện: Bạn cần sử dụng các chức năng nhập xuất (đọc từ bàn phím, in ra màn hình) và có thể cần các hàm hỗ trợ tìm max/min. Thư viện cơ bản cho nhập xuất là <iostream>. Thư viện <algorithm> chứa các hàm maxmin rất hữu ích cho bài toán này.
  2. Hàm chính (main): Mọi chương trình C++ đều bắt đầu từ hàm main.
  3. Khai báo biến: Cần 3 biến để lưu trữ 3 số nguyên a, b, c đọc từ input. Sử dụng kiểu dữ liệu int là đủ vì phạm vi giá trị cho phép (-10^6 <= a, b, c <= 10^6) nằm trong giới hạn của int.
  4. Đọc dữ liệu: Sử dụng đối tượng cin từ thư viện <iostream> để đọc 3 số nguyên từ input, chúng được cách nhau bởi dấu cách nên bạn có thể đọc chúng liên tiếp.
  5. Tìm số lớn nhất (maximum):
    • Bạn có thể sử dụng hàm max. Hàm này có thể so sánh hai giá trị. Để so sánh ba giá trị, bạn có thể dùng max lồng nhau, ví dụ: max(so_thu_nhat, max(so_thu_hai, so_thu_ba)).
    • Hoặc, từ C++11 trở lên, max cũng hỗ trợ nhận một danh sách khởi tạo (initializer list), cho phép tìm max của nhiều số một cách ngắn gọn: max({so_thu_nhat, so_thu_hai, so_thu_ba}). Cách này rất phù hợp với yêu cầu "code ngắn gọn" và "ưu tiên dùng std".
  6. Tìm số nhỏ nhất (minimum):
    • Tương tự như tìm max, bạn có thể sử dụng hàm min lồng nhau: min(so_thu_nhat, min(so_thu_hai, so_thu_ba)).
    • Hoặc dùng phiên bản với danh sách khởi tạo: min({so_thu_nhat, so_thu_hai, so_thu_ba}). Đây cũng là cách ngắn gọn và dùng std.
  7. In kết quả: Sử dụng đối tượng cout từ thư viện <iostream> để in ra kết quả.
    • In giá trị lớn nhất trước, theo sau là ký tự xuống dòng (\n hoặc endl).
    • In giá trị nhỏ nhất sau đó, theo sau là ký tự xuống dòng.
  8. Kết thúc chương trình: Trả về 0 từ hàm main để báo hiệu chương trình kết thúc thành công.

Làm thêm nhiều bài tập miễn phí tại đây

Comments

There are no comments at the moment.