Bài 4.3: Bài tập thực hành rẽ nhánh if-else lồng nhau trong C++

Bài 4.3: Bài tập thực hành rẽ nhánh if-else lồng nhau trong C++
Chào mừng trở lại với chuỗi bài học C++ của FullhouseDev! Ở các bài trước, chúng ta đã làm quen với cấu trúc rẽ nhánh if
và if-else
cơ bản, giúp chương trình của chúng ta đưa ra quyết định dựa trên một điều kiện đơn giản. Tuy nhiên, trong thế giới lập trình thực tế, các quyết định thường không chỉ dựa trên một điều kiện duy nhất. Thường thì, bạn cần kiểm tra một điều kiện, và chỉ khi điều kiện đó đúng (hoặc sai), bạn mới tiếp tục kiểm tra một điều kiện khác nữa. Đây chính là lúc cấu trúc rẽ nhánh if-else
lồng nhau phát huy sức mạnh của nó.
Bài học này sẽ đưa bạn đi sâu hơn vào cách sử dụng các câu lệnh if
và else
bên trong các khối if
hoặc else
khác. Hãy cùng khám phá làm thế nào để tạo ra logic chương trình mạnh mẽ và linh hoạt hơn nhé!
Rẽ Nhánh if-else
Lồng Nhau là Gì?
Đơn giản mà nói, rẽ nhánh if-else
lồng nhau (Nested if-else
) là việc đặt một câu lệnh if
hoặc if-else
(hoặc thậm chí là một cấu trúc if-else if-else
) vào bên trong khối mã của một câu lệnh if
hoặc else
khác.
Hãy tưởng tượng bạn muốn kiểm tra hai điều kiện liên tiếp:
- Đầu tiên, kiểm tra xem một người có đủ tuổi để lái xe không (ví dụ: >= 18 tuổi).
- Nếu họ đủ tuổi, thì kiểm tra xem họ có bằng lái xe hợp lệ không.
Bạn không cần kiểm tra điều kiện có bằng lái nếu người đó chưa đủ tuổi. Đây chính là kịch bản lý tưởng cho if-else
lồng nhau.
Cấu trúc chung:
if (dieu_kien_1) {
// Mã được thực thi nếu dieu_kien_1 đúng
// Bây giờ, kiểm tra dieu_kien_2 CHỈ KHI dieu_kien_1 đúng
if (dieu_kien_2) {
// Mã được thực thi nếu dieu_kien_1 đúng VÀ dieu_kien_2 đúng
} else {
// Mã được thực thi nếu dieu_kien_1 đúng NHƯNG dieu_kien_2 sai
}
} else {
// Mã được thực thi nếu dieu_kien_1 sai
// Bạn cũng có thể lồng ghép ở đây
if (dieu_kien_3) {
// Mã được thực thi nếu dieu_kien_1 sai NHƯNG dieu_kien_3 đúng
} else {
// Mã được thực thi nếu dieu_kien_1 sai VÀ dieu_kien_3 cũng sai
}
}
Lưu ý rằng việc thụt lề (indentation) là cực kỳ quan trọng để giữ cho code lồng nhau dễ đọc và dễ hiểu. C++ không bắt buộc thụt lề về mặt cú pháp, nhưng nó là một quy tắc vàng trong lập trình chuyên nghiệp.
Khi Nào Sử Dụng if-else
Lồng Nhau?
Bạn nên sử dụng cấu trúc lồng nhau khi logic của bạn yêu cầu kiểm tra một điều kiện phụ thuộc vào kết quả của một điều kiện khác. Các trường hợp phổ biến bao gồm:
- Kiểm tra nhiều tiêu chí phải cùng đúng hoặc kết hợp theo một trình tự nhất định.
- Xử lý các trường hợp đặc biệt bên trong các trường hợp chung.
- Xây dựng các quy tắc phân loại phức tạp.
Mặc dù đôi khi bạn có thể sử dụng các toán tử logic như &&
(AND) hoặc ||
(OR) để kết hợp điều kiện (ví dụ: if (dieu_kien_1 && dieu_kien_2)
), nhưng if-else
lồng nhau cho phép bạn thực thi các khối mã riêng biệt dựa trên từng bước của quá trình kiểm tra điều kiện, hoặc khi các điều kiện phức tạp không thể dễ dàng kết hợp bằng &&
hoặc ||
.
Hãy cùng đi qua các ví dụ cụ thể để thấy rõ hơn sức mạnh của cấu trúc này.
Các Ví Dụ Minh Họa
Để đơn giản hóa, chúng ta sẽ sử dụng using namespace std;
trong các ví dụ code ngắn gọn này.
Ví Dụ 1: Kiểm Tra Tuổi và Điều Kiện Phụ
Yêu cầu: Nhập tuổi của học sinh. Nếu học sinh từ 16 tuổi trở lên, kiểm tra xem điểm trung bình của họ có đạt 7.0 không để xem xét cấp học bổng.
#include <iostream>
int main() {
using namespace std; // Sử dụng namespace std
int tuoi;
double diemTrungBinh;
cout << "Nhap tuoi cua hoc sinh: ";
cin >> tuoi;
// Dieu kien 1: Kiem tra tuoi
if (tuoi >= 16) {
cout << "Hoc sinh du tuoi xem xet hoc bong.\n";
cout << "Nhap diem trung binh: ";
cin >> diemTrungBinh;
// Dieu kien 2 (long ben trong dieu kien 1): Kiem tra diem
if (diemTrungBinh >= 7.0) {
cout << "Hoc sinh DAP UNG du dieu kien hoc bong!\n";
} else {
cout << "Hoc sinh du tuoi nhung KHONG DU diem trung binh.\n";
}
} else {
cout << "Hoc sinh CHUA du tuoi xem xet hoc bong.\n";
}
return 0;
}
Giải thích:
- Chương trình đầu tiên kiểm tra
if (tuoi >= 16)
. - Nếu điều kiện này đúng, nó sẽ in ra thông báo và tiếp tục vào khối mã bên trong
if
. - Bên trong khối
if
đầu tiên, nó sẽ hỏi điểm trung bình và thực hiện một câu lệnhif-else
lồng nhau khác để kiểm tradiemTrungBinh >= 7.0
. - Kết quả cuối cùng phụ thuộc vào việc cả hai điều kiện có đúng hay không (cho trường hợp đủ tuổi) hoặc chỉ cần điều kiện tuổi sai là đủ để kết luận.
Ví Dụ 2: Phân Loại Điểm Số Chi Tiết
Yêu cầu: Nhập điểm thi (từ 0 đến 100). Phân loại chung (Đạt/Trượt - ví dụ >= 50 là Đạt) và nếu Đạt, phân loại chi tiết hơn (Giỏi >= 80, Khá >= 65, Trung bình >= 50).
#include <iostream>
int main() {
using namespace std;
int diemThi;
cout << "Nhap diem thi (0-100): ";
cin >> diemThi;
// Kiem tra diem co hop le trong pham vi 0-100 khong
if (diemThi >= 0 && diemThi <= 100) {
// Dieu kien 1: Kiem tra Dau hay Truot
if (diemThi >= 50) {
cout << "Ket qua: DAT\n";
// Dieu kien 2 (long): Kiem tra xep loai chi tiet neu DAT
if (diemThi >= 80) {
cout << "Xep loai: GIOI\n";
} else if (diemThi >= 65) {
cout << "Xep loai: KHA\n";
} else { // Diem >= 50 nhung < 65
cout << "Xep loai: Trung binh\n";
}
} else { // Diem < 50
cout << "Ket qua: TRUOT\n";
}
} else {
cout << "Diem nhap vao KHONG hop le!\n";
}
return 0;
}
Giải thích:
- Đầu tiên, chúng ta có một
if
bên ngoài kiểm tra tính hợp lệ của điểm (diemThi >= 0 && diemThi <= 100
). Đây là một lớp kiểm tra ban đầu tốt. - Bên trong khối
if
hợp lệ, chúng ta kiểm tra điều kiện "Đạt" (diemThi >= 50
). - Nếu điểm Đạt, chúng ta đi vào khối
if
thứ hai này và tiếp tục thực hiện một cấu trúcif-else if-else
lồng nhau để xác định xếp loại chi tiết (Giỏi, Khá, Trung bình). - Nếu điểm không Đạt (khi
diemThi < 50
), chương trình sẽ thực hiện khốielse
tương ứng vớiif (diemThi >= 50)
và in ra "TRUOT".
Ví Dụ 3: Lồng Ghép trong Khối else
Yêu cầu: Nhập giới tính ('N'/'n' cho Nữ, 'M'/'m' cho Nam) và tuổi. Nếu không phải Nữ, kiểm tra xem có phải Nam không. Nếu là Nam, kiểm tra tuổi để xem có đủ điều kiện tham gia câu lạc bộ bóng đá (Nam và >= 18 tuổi). Nếu không phải Nam, coi là giới tính khác.
#include <iostream>
#include <string> // Can cho string
int main() {
using namespace std;
char gioiTinh;
int tuoi;
cout << "Nhap gioi tinh (N/M): ";
cin >> gioiTinh;
// Dieu kien 1: Kiem tra co phai Nu khong
if (gioiTinh == 'N' || gioiTinh == 'n') {
cout << "Gioi tinh: Nu.\n";
} else {
// Neu khong phai Nu, KIEM TRA TIEP xem co phai Nam khong (long trong else)
if (gioiTinh == 'M' || gioiTinh == 'm') {
cout << "Gioi tinh: Nam.\n";
cout << "Nhap tuoi: ";
cin >> tuoi;
// Dieu kien 2 (long ben trong if la Nam): Kiem tra tuoi
if (tuoi >= 18) {
cout << "Du dieu kien tham gia cau lac bo bong da (Nam, >=18).\n";
} else {
cout << "La Nam nhung chua du tuoi tham gia cau lac bo bong da.\n";
}
} else {
// Neu khong phai Nu va cung khong phai Nam
cout << "Gioi tinh: Khac.\n";
}
}
return 0;
}
Giải thích:
- Đầu tiên kiểm tra giới tính có phải là Nữ hay không.
- Nếu không phải Nữ (điều kiện
if (gioiTinh == 'N' || gioiTinh == 'n')
sai), chương trình nhảy vào khốielse
. - Bên trong khối
else
này, chúng ta lại có một cấu trúcif-else
mới để kiểm tra xem giới tính có phải là Nam không. - Nếu là Nam (điều kiện
if (gioiTinh == 'M' || gioiTinh == 'm')
đúng bên trong khốielse
), chương trình tiếp tục vào khối mã củaif
đó, hỏi tuổi, và thực hiện một câu lệnhif-else
lồng thêm một cấp nữa để kiểm tra tuổi. - Nếu không phải Nữ và cũng không phải Nam, chương trình thực hiện khối
else
cuối cùng (tương ứng vớiif (gioiTinh == 'M' || gioiTinh == 'm')
) và in ra "Gioi tinh: Khac".
Ví dụ này cho thấy bạn hoàn toàn có thể lồng if-else
không chỉ trong khối if
mà còn trong khối else
nữa, tùy thuộc vào logic bạn muốn xây dựng.
Ví Dụ 4: Đặt Vé Rạp Chiếu Phim (Đơn Giản)
Yêu cầu: Giá vé xem phim phụ thuộc vào loại vé (thường/VIP) và thời điểm xem (buổi sáng/buổi tối).
#include <iostream>
#include <string>
int main() {
using namespace std;
string loaiVe;
string thoiGian;
double giaVe = 0.0;
bool inputHopLe = true; // Bien kiem tra dau vao co hop le khong
cout << "Chon loai ve (Thuong/VIP): ";
cin >> loaiVe;
cout << "Chon thoi gian (Sang/Toi): ";
cin >> thoiGian;
// Chuyen doi chuoi nhap vao sang dang dong nhat de so sanh
for(char &c : loaiVe) c = tolower(c);
for(char &c : thoiGian) c = tolower(c);
// Dieu kien 1: Kiem tra loai ve
if (loaiVe == "thuong") {
// Long Dieu kien 2: Kiem tra thoi gian neu la ve Thuong
if (thoiGian == "sang") {
giaVe = 80000.0;
} else if (thoiGian == "toi") {
giaVe = 100000.0;
} else {
cout << "Thoi gian khong hop le!\n";
inputHopLe = false;
}
} else if (loaiVe == "vip") {
// Long Dieu kien 2: Kiem tra thoi gian neu la ve VIP
if (thoiGian == "sang") {
giaVe = 120000.0;
} else if (thoiGian == "toi") {
giaVe = 150000.0;
} else {
cout << "Thoi gian khong hop le!\n";
inputHopLe = false;
}
} else {
cout << "Loai ve khong hop le!\n";
inputHopLe = false;
}
// Chi in gia ve neu dau vao hop le
if (inputHopLe) {
cout << "Gia ve cua ban la: " << giaVe << " VND\n";
}
return 0;
}
Giải thích:
- Chương trình đầu tiên kiểm tra
loaiVe
là "thuong" hay "vip" (hoặc không hợp lệ). Đây là tầngif-else if-else
đầu tiên. - Bên trong mỗi nhánh của tầng đầu tiên (khi
loaiVe
là "thuong" hoặc "vip"), chúng ta lại có một cấu trúcif-else if-else
lồng nhau để kiểm trathoiGian
là "sang" hay "toi". - Giá vé cuối cùng được xác định dựa trên sự kết hợp của cả hai điều kiện: loại vé và thời gian.
- Chúng ta cũng thêm biến
inputHopLe
để xử lý trường hợp người dùng nhập sai loại vé hoặc thời gian ở bất kỳ cấp độ nào.
Ví dụ này minh họa cách lồng ghép có thể xử lý các ma trận điều kiện (ví dụ: một bảng giá 2x2 hoặc lớn hơn).
Lưu Ý Quan Trọng: Tính Dễ Đọc và Phức Tạp
Mặc dù if-else
lồng nhau rất mạnh mẽ, nhưng nó cũng có một nhược điểm: khi bạn lồng quá sâu (ví dụ: if
bên trong if
bên trong if
...), code của bạn sẽ trở nên rất khó đọc, khó hiểu và khó gỡ lỗi (debug).
- Luôn luôn sử dụng thụt lề (indentation) nhất quán. Điều này giúp bạn dễ dàng nhìn thấy khối lệnh nào thuộc về điều kiện nào.
- Tránh lồng ghép quá 3-4 cấp độ. Nếu logic của bạn yêu cầu lồng ghép sâu hơn, hãy xem xét các cách tiếp cận khác như:
- Kết hợp điều kiện đơn giản bằng toán tử logic
&&
và||
. - Sử dụng các hàm riêng biệt để kiểm tra từng phần logic.
- Cấu trúc lại logic tổng thể.
- Kết hợp điều kiện đơn giản bằng toán tử logic
- Thêm chú thích (comments) cho các khối lồng ghép phức tạp để giải thích mục đích của chúng.
Bài Tập Thực Hành
Hãy thử áp dụng kiến thức đã học bằng cách giải bài tập nhỏ sau:
Viết chương trình C++:
- Nhập vào ba số nguyên bất kỳ từ người dùng.
- Đầu tiên, kiểm tra xem số thứ nhất có phải là số dương (> 0) hay không.
- Nếu số thứ nhất là số dương, tiếp tục kiểm tra xem số thứ hai có lớn hơn số thứ ba hay không.
- In ra các thông báo phù hợp cho tất cả các trường hợp có thể xảy ra (ví dụ: "So thu nhat la so duong", "So thu hai lon hon so thu ba", "So thu nhat khong phai so duong", "So thu hai khong lon hon so thu ba", v.v.).
Gợi ý: Bạn sẽ cần một câu lệnh if
bên ngoài kiểm tra số thứ nhất. Bên trong khối if
đó, bạn sẽ cần một câu lệnh if-else
khác để so sánh số thứ hai và số thứ ba. Đừng quên khối else
cho if
đầu tiên để xử lý trường hợp số thứ nhất không dương.
Comments