Bài 4.2: Bài tập thực hành toán tử so sánh và logic trong C++

Bài 4.2: Bài tập thực hành toán tử so sánh và logic trong C++
Chào mừng các bạn quay trở lại với chuỗi bài học C++! Sau khi đã làm quen với các kiểu dữ liệu cơ bản và toán tử số học, hôm nay chúng ta sẽ bước vào một lĩnh vực cực kỳ quan trọng trong lập trình: đưa ra quyết định. Mọi chương trình máy tính, dù đơn giản hay phức tạp, đều cần khả năng kiểm tra điều kiện và hành động khác nhau dựa trên kết quả kiểm tra đó. Và đó chính là lúc toán tử so sánh và toán tử logic phát huy sức mạnh của mình.
Hãy tưởng tượng bạn đang viết một chương trình game. Bạn cần kiểm tra xem điểm của người chơi có đủ để lên cấp không, hay máu của quái vật đã về 0 chưa. Hoặc khi xây dựng một ứng dụng web, bạn cần xác minh xem mật khẩu người dùng nhập có đúng với mật khẩu đã lưu hay không, hay xem người dùng có đủ tuổi để truy cập một nội dung nào đó không. Tất cả những kịch bản này đều dựa trên việc sử dụng các toán tử mà chúng ta sắp tìm hiểu.
Kết quả của một phép so sánh hoặc một biểu thức logic luôn là một giá trị boolean, tức là chỉ có thể là true
(đúng) hoặc false
(sai). Trong C++, giá trị true
thường được biểu diễn là 1
, và false
là 0
.
Hãy cùng đi sâu vào từng loại toán tử nhé!
I. Toán tử So Sánh (Comparison Operators)
Toán tử so sánh được dùng để so sánh hai giá trị (có thể là biến, hằng số, hoặc biểu thức). Chúng trả về true
nếu phép so sánh đúng và false
nếu phép so sánh sai.
Đây là danh sách các toán tử so sánh phổ biến trong C++:
==
: Bằng (Equal to)!=
: Không bằng (Not equal to)>
: Lớn hơn (Greater than)<
: Nhỏ hơn (Less than)>=
: Lớn hơn hoặc bằng (Greater than or equal to)<=
: Nhỏ hơn hoặc bằng (Less than or equal to)
Hãy xem qua một vài ví dụ đơn giản để hiểu cách chúng hoạt động:
#include <iostream> // Cần thiết cho cout và endl
int main() {
int a = 10;
int b = 20;
int c = 10;
// Sử dụng các toán tử so sánh
cout << "a == b: " << (a == b) << endl; // So sánh a và b, kết quả false (0)
cout << "a == c: " << (a == c) << endl; // So sánh a và c, kết quả true (1)
cout << "a != b: " << (a != b) << endl; // So sánh a và b, kết quả true (1)
cout << "b > a: " << (b > a) << endl; // So sánh b có lớn hơn a không, kết quả true (1)
cout << "a < b: " << (a < b) << endl; // So sánh a có nhỏ hơn b không, kết quả true (1)
cout << "a >= c: " << (a >= c) << endl; // So sánh a có lớn hơn hoặc bằng c không, kết quả true (1)
cout << "b <= c: " << (b <= c) << endl; // So sánh b có nhỏ hơn hoặc bằng c không, kết quả false (0)
return 0; // Kết thúc chương trình thành công
}
Giải thích:
- Chúng ta khai báo ba biến số nguyên
a
,b
,c
với các giá trị khác nhau. - Sau đó, chúng ta sử dụng
cout
để in ra kết quả của từng phép so sánh. - Kết quả
true
được in ra là1
, vàfalse
là0
. Bạn có thể thấy rõ điều này trong output của chương trình. Ví dụ,a == b
là sai (10 không bằng 20), nên kết quả làfalse
(in ra0
). Ngược lại,a == c
là đúng (10 bằng 10), nên kết quả làtrue
(in ra1
).
Lưu ý quan trọng: Toán tử so sánh bằng là ==
(hai dấu bằng), khác với toán tử gán =
(một dấu bằng). Đây là lỗi rất phổ biến đối với người mới học lập trình, hãy cẩn thận!
Hãy thử một ví dụ khác với kiểu dữ liệu khác:
#include <iostream>
#include <string> // Cần thiết cho string
int main() {
double price = 19.99;
double threshold = 20.0;
string city1 = "Hanoi";
string city2 = "Saigon";
string city3 = "Hanoi";
cout << "price < threshold: " << (price < threshold) << endl; // true
cout << "price >= threshold: " << (price >= threshold) << endl; // false
// So sánh chuỗi (string)
cout << "city1 == city2: " << (city1 == city2) << endl; // false
cout << "city1 == city3: " << (city1 == city3) << endl; // true
cout << "city1 != city2: " << (city1 != city2) << endl; // true
// So sánh theo thứ tự từ điển (lexicographical order)
cout << "city1 < city2: " << (city1 < city2) << endl; // true ('H' đứng trước 'S')
return 0;
}
Giải thích:
- Ví dụ này cho thấy toán tử so sánh hoạt động với cả số thực (
double
) và chuỗi ký tự (string
). - Với chuỗi,
==
kiểm tra xem hai chuỗi có giống hệt nhau hay không. - Các toán tử
<
,>
,<=
,>=
khi áp dụng cho chuỗi sẽ so sánh chúng theo thứ tự từ điển (giống như sắp xếp trong từ điển), dựa trên giá trị ASCII của các ký tự.
Toán tử so sánh là nền tảng để đặt câu hỏi trong chương trình của bạn. Kết quả của những câu hỏi này (true
hoặc false
) sẽ là đầu vào cho các toán tử logic.
II. Toán tử Logic (Logical Operators)
Trong khi toán tử so sánh giúp chúng ta so sánh hai giá trị, toán tử logic lại giúp chúng ta kết hợp hoặc đảo ngược các giá trị boolean (true
/false
) hoặc các biểu thức mà kết quả của chúng là boolean (như kết quả của phép so sánh).
Có ba toán tử logic chính trong C++:
&&
: AND (VÀ) - Kết quả làtrue
chỉ khi cả hai toán hạng đều làtrue
.||
: OR (HOẶC) - Kết quả làtrue
nếu ít nhất một trong hai toán hạng làtrue
.!
: NOT (KHÔNG) - Đảo ngược giá trị boolean của toán hạng (true thành false, false thành true). Đây là toán tử một ngôi (unary), chỉ tác động lên toán hạng đứng sau nó.
Hãy xem cách chúng hoạt động:
1. Toán tử &&
(Logical AND)
Biểu thức A && B
chỉ đúng (true
) khi cả A và B đều đúng. Nếu A sai, hoặc B sai, hoặc cả hai đều sai, thì kết quả sẽ là sai (false
).
#include <iostream>
int main() {
bool condition1 = true;
bool condition2 = false;
// Bảng chân trị (Truth Table) cho &&
cout << "true && true: " << (true && true) << endl; // true (1)
cout << "true && false: " << (true && false) << endl; // false (0)
cout << "false && true: " << (false && true) << endl; // false (0)
cout << "false && false: " << (false && false) << endl; // false (0)
// Ví dụ với biến
cout << "condition1 && condition2: " << (condition1 && condition2) << endl; // true && false -> false
return 0;
}
Giải thích: Toán tử &&
đòi hỏi sự đồng thuận hoàn toàn. Chỉ khi cả hai "người" đều nói "có" thì kết quả cuối cùng mới là "có".
2. Toán tử ||
(Logical OR)
Biểu thức A || B
đúng (true
) khi ít nhất một trong hai toán hạng A hoặc B đúng. Nó chỉ sai (false
) khi cả A và B đều sai.
#include <iostream>
int main() {
bool condition1 = true;
bool condition2 = false;
// Bảng chân trị (Truth Table) cho ||
cout << "true || true: " << (true || true) << endl; // true (1)
cout << "true || false: " << (true || false) << endl; // true (1)
cout << "false || true: " << (false || true) << endl; // true (1)
cout << "false || false: " << (false || false) << endl; // false (0)
// Ví dụ với biến
cout << "condition1 || condition2: " << (condition1 || condition2) << endl; // true || false -> true
return 0;
}
Giải thích: Toán tử ||
linh hoạt hơn. Chỉ cần một trong hai "người" nói "có" là kết quả cuối cùng đã là "có" rồi. Chỉ khi cả hai cùng nói "không" thì kết quả mới là "không".
3. Toán tử !
(Logical NOT)
Toán tử !
đứng trước một biểu thức boolean và đảo ngược giá trị của nó. Nếu biểu thức đó là true
, !
sẽ biến nó thành false
. Nếu biểu thức đó là false
, !
sẽ biến nó thành true
.
#include <iostream>
int main() {
bool isRaining = false;
bool isCold = true;
// Đảo ngược giá trị
cout << "!true: " << (!true) << endl; // false (0)
cout << "!false: " << (!false) << endl; // true (1)
// Ví dụ với biến
cout << "!isRaining: " << (!isRaining) << endl; // !false -> true (Không mưa -> trời đẹp)
cout << "!isCold: " << (!isCold) << endl; // !true -> false (Không lạnh -> trời ấm/nóng)
return 0;
}
Giải thích: Toán tử !
đơn giản là phép phủ định. "Không đúng" tức là "sai", và "không sai" tức là "đúng".
III. Kết Hợp Toán tử So Sánh và Logic
Đây là nơi mọi thứ trở nên thú vị và thực tế hơn. Chúng ta thường sử dụng toán tử logic để kết hợp các kết quả từ toán tử so sánh, tạo ra các điều kiện phức tạp hơn.
Ví dụ, để kiểm tra xem một số x
có nằm trong khoảng từ 10 đến 20 (bao gồm cả 10 và 20) hay không, chúng ta cần hai phép so sánh: x >= 10
và x <= 20
. Để cả hai điều kiện này cùng đúng, chúng ta sẽ kết hợp chúng bằng toán tử &&
: (x >= 10) && (x <= 20)
.
Để kiểm tra xem một ký tự c
có phải là một chữ cái (viết hoa hoặc viết thường) hay không, chúng ta cần kiểm tra hai trường hợp: c >= 'a' && c <= 'z'
(chữ thường) HOẶC c >= 'A' && c <= 'Z'
(chữ hoa). Chúng ta sẽ kết hợp hai trường hợp này bằng toán tử ||
: (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
.
Hãy xem một ví dụ đầy đủ:
#include <iostream>
#include <string>
int main() {
int age = 25;
double salary = 55000.0;
string status = "Employed";
// Điều kiện 1: Tuổi từ 18 đến 65 VÀ mức lương trên 50000
bool criteria1 = (age >= 18 && age <= 65) && (salary > 50000);
cout << "Đáp ứng tiêu chí 1 (Tuổi 18-65 VÀ Lương > 50k): " << criteria1 << endl; // true
// Điều kiện 2: Đã kết hôn HOẶC Tình trạng là "Employed"
bool isMarried = false; // Giả sử người này chưa kết hôn
bool criteria2 = isMarried || (status == "Employed");
cout << "Đáp ứng tiêu chí 2 (Đã kết hôn HOẶC Tình trạng Employed): " << criteria2 << endl; // false || true -> true
// Điều kiện 3: KHÔNG phải là người đã nghỉ hưu VÀ tuổi lớn hơn 20
bool isRetired = false;
bool criteria3 = !isRetired && (age > 20);
cout << "Đáp ứng tiêu chí 3 (KHÔNG về hưu VÀ Tuổi > 20): " << criteria3 << endl; // !false && true -> true && true -> true
// Điều kiện phức tạp: (Tuổi < 18 HOẶC Tuổi > 60) VÀ KHÔNG phải là sinh viên
bool isStudent = true;
bool criteria4 = (age < 18 || age > 60) && (!isStudent);
cout << "Đáp ứng tiêu chí 4 ((Tuổi < 18 HOẶC > 60) VÀ KHÔNG sinh viên): " << criteria4 << endl; // (false || false) && (!true) -> false && false -> false
return 0;
}
Giải thích:
- Chúng ta dùng các biến
age
,salary
,status
,isMarried
,isRetired
,isStudent
để mô phỏng dữ liệu. criteria1
: Kiểm tra hai điều kiện so sánh (age
trong khoảng 18-65,salary
> 50000) được kết hợp bằng&&
. Cả hai phần đều đúng nên kết quả cuối cùng làtrue
.criteria2
: Kiểm traisMarried
HOẶCstatus == "Employed"
. Mặc dùisMarried
làfalse
, nhưngstatus == "Employed"
làtrue
, nên kết quả||
làtrue
.criteria3
: Sử dụng!
để phủ địnhisRetired
(từfalse
thànhtrue
), rồi kết hợp vớiage > 20
bằng&&
. Cả hai phần đềutrue
nên kết quả làtrue
.criteria4
: Đây là một ví dụ phức tạp hơn. Biểu thức(age < 18 || age > 60)
là(false || false)
, cho kết quảfalse
. Biểu thức(!isStudent)
là(!true)
, cho kết quảfalse
. Cuối cùng,false && false
cho kết quảfalse
.
Việc sử dụng dấu ngoặc đơn ()
rất quan trọng để nhóm các biểu thức và đảm bảo thứ tự thực hiện đúng như ý bạn.
IV. Thứ Tự Ưu Tiên của Toán tử
Giống như trong toán học, các toán tử trong C++ có thứ tự ưu tiên nhất định. Toán tử !
có ưu tiên rất cao (thường cao hơn cả toán tử số học), tiếp theo là các toán tử so sánh (==
, !=
, >
, <
, >=
, <=
), và cuối cùng là toán tử logic &&
(ưu tiên cao hơn) và ||
(ưu tiên thấp hơn).
Ví dụ:
!a && b
sẽ được hiểu là(!a) && b
.a > b && c < d
sẽ được hiểu là(a > b) && (c < d)
.a || b && c
sẽ được hiểu làa || (b && c)
(vì&&
ưu tiên hơn||
).
Tuy nhiên, để làm cho mã nguồn của bạn dễ đọc và tránh nhầm lẫn, luôn luôn nên sử dụng dấu ngoặc đơn ()
để nhóm các biểu thức con và làm rõ thứ tự thực hiện, ngay cả khi thứ tự ưu tiên mặc định cho kết quả tương tự.
Ví dụ, thay vì viết age < 18 || age > 60 && !isStudent
, hãy viết rõ ràng hơn: (age < 18 || age > 60) && (!isStudent)
. Điều này giúp bạn và người đọc hiểu ngay lập tức ý định của bạn là kiểm tra xem tuổi có NẰM NGOÀI KHOẢNG cho phép hay không, VÀ người đó KHÔNG phải là sinh viên.
Kết Thúc
Các toán tử so sánh và logic là cốt lõi của việc ra quyết định trong lập trình C++. Chúng cho phép chương trình của bạn phản ứng với các điều kiện khác nhau, điều khiển luồng thực thi và tạo ra các hành vi thông minh hơn. Hãy thực hành thật nhiều với các bài tập để làm quen và sử dụng chúng một cách thành thạo.
Hãy thử viết các đoạn mã nhỏ để kiểm tra các điều kiện khác nhau, ví dụ:
- Kiểm tra xem một năm có phải là năm nhuận không.
- Kiểm tra xem nhiệt độ và độ ẩm có nằm trong khoảng lý tưởng không.
- Kiểm tra xem một chuỗi có rỗng hoặc có độ dài lớn hơn 10 ký tự không.
Việc nắm vững các toán tử này là bước đệm quan trọng để bạn học về các cấu trúc điều khiển luồng như if
, else if
, else
, switch
, và các vòng lặp, những thứ sẽ sử dụng kết quả boolean của các toán tử này để hoạt động.
Comments