C&C++快速入门
9、逻辑运算符
1、课程目标
- 掌握逻辑与、逻辑或、逻辑非运算符
- 理解短路求值的工作原理
- 掌握关系运算符
- 学会构建复杂的条件表达式
2、名词解释
| 术语 | 符号 | 说明 |
|---|---|---|
| 逻辑与 | && | 两个条件都为真则为真 |
| 逻辑或 | || | 任一条件为真则为真 |
| 逻辑非 | ! | 取反 |
| 短路求值 | Short-circuit | 能确定结果时不继续计算 |
| 等于 | == | 判断相等 |
| 不等于 | != | 判断不相等 |
| 大于 | > | 判断大于 |
| 小于 | < | 判断小于 |
| 大于等于 | >= | 判断大于或等于 |
| 小于等于 | <= | 判断小于或等于 |
3、代码实现
1. 关系运算符
#include <stdio.h>
int main() {
printf("=== 关系运算符 ===\n\n");
int a = 10, b = 20;
printf("a = %d, b = %d\n\n", a, b);
printf("a == b : %d\n", a == b); // 0 (false)
printf("a != b : %d\n", a != b); // 1 (true)
printf("a > b : %d\n", a > b); // 0
printf("a < b : %d\n", a < b); // 1
printf("a >= b : %d\n", a >= b); // 0
printf("a <= b : %d\n", a <= b); // 1
// 注意:比较结果是整数 0 或 1
printf("\n比较结果类型: %d字节\n", (int)sizeof(a < b));
return 0;
}
2. 逻辑运算符
#include <stdio.h>
int main() {
printf("=== 逻辑运算符 ===\n\n");
int a = 1, b = 0;
printf("a = %d (真), b = %d (假)\n\n", a, b);
// 逻辑与
printf("【逻辑与 &&】\n");
printf("a && b : %d\n", a && b); // 0
printf("a && a : %d\n", a && a); // 1
printf("b && b : %d\n", b && b); // 0
// 逻辑或
printf("\n【逻辑或 ||】\n");
printf("a || b : %d\n", a || b); // 1
printf("a || a : %d\n", a || a); // 1
printf("b || b : %d\n", b || b); // 0
// 逻辑非
printf("\n【逻辑非 !】\n");
printf("!a : %d\n", !a); // 0
printf("!b : %d\n", !b); // 1
printf("!!a : %d\n", !!a); // 1 (双重取反还原)
// 非零值都为真
printf("\n【非零值为真】\n");
printf("!0 : %d\n", !0); // 1
printf("!1 : %d\n", !1); // 0
printf("!42 : %d\n", !42); // 0
printf("!-1 : %d\n", !-1); // 0
return 0;
}
3. 短路求值
#include <stdio.h>
int GetValue(const char* name, int value) {
printf(" [调用 GetValue(\"%s\") = %d]\n", name, value);
return value;
}
int main() {
printf("=== 短路求值 ===\n\n");
// 逻辑与的短路
printf("【逻辑与短路】\n");
printf("测试: 0 && GetValue(\"B\", 1)\n");
int r1 = GetValue("A", 0) && GetValue("B", 1);
printf("结果: %d (第一个为0,不计算第二个)\n\n", r1);
printf("测试: 1 && GetValue(\"B\", 1)\n");
int r2 = GetValue("A", 1) && GetValue("B", 1);
printf("结果: %d (第一个为1,需要计算第二个)\n\n", r2);
// 逻辑或的短路
printf("【逻辑或短路】\n");
printf("测试: 1 || GetValue(\"B\", 0)\n");
int r3 = GetValue("A", 1) || GetValue("B", 0);
printf("结果: %d (第一个为1,不计算第二个)\n\n", r3);
printf("测试: 0 || GetValue(\"B\", 1)\n");
int r4 = GetValue("A", 0) || GetValue("B", 1);
printf("结果: %d (第一个为0,需要计算第二个)\n", r4);
return 0;
}
4. 短路求值的实用场景
#include <stdio.h>
#include <windows.h>
int main() {
printf("=== 短路求值应用 ===\n\n");
// 1. 空指针保护
printf("【空指针保护】\n");
char* str = NULL;
// 如果str为NULL,不会调用strlen
if (str && strlen(str) > 0) {
printf("字符串不为空\n");
} else {
printf("字符串为空或NULL\n");
}
// 2. 句柄有效性检查
printf("\n【句柄检查】\n");
HANDLE hFile = INVALID_HANDLE_VALUE;
// 句柄无效时不会调用CloseHandle
if (hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile)) {
printf("句柄关闭成功\n");
} else {
printf("句柄无效或关闭失败\n");
}
// 3. 默认值模式
printf("\n【默认值模式】\n");
int userValue = 0;
int defaultValue = 100;
int result = userValue ? userValue : defaultValue;
// 或者用逻辑或
// int result = userValue || defaultValue; // 注意:这样结果是0或1
printf("用户值: %d, 结果: %d\n", userValue, result);
// 4. 安全的链式调用
printf("\n【安全链式调用】\n");
int arr[5] = {1, 2, 3, 4, 5};
int index = 10; // 越界索引
int arrSize = 5;
// 先检查越界,再访问数组
if (index >= 0 && index < arrSize && arr[index] > 0) {
printf("有效的正数\n");
} else {
printf("无效索引或非正数\n");
}
return 0;
}
5. 复杂条件表达式
#include <stdio.h>
// 检查是否是有效的用户名字符
int IsValidNameChar(char c) {
return (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
c == '_';
}
// 检查是否是闰年
int IsLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
// 检查是否在范围内
int InRange(int value, int min, int max) {
return value >= min && value <= max;
}
int main() {
printf("=== 复杂条件表达式 ===\n\n");
// 测试用户名字符
printf("【用户名字符检查】\n");
printf("'a' 有效: %d\n", IsValidNameChar('a'));
printf("'5' 有效: %d\n", IsValidNameChar('5'));
printf("'_' 有效: %d\n", IsValidNameChar('_'));
printf("'@' 有效: %d\n", IsValidNameChar('@'));
// 测试闰年
printf("\n【闰年检查】\n");
printf("2000 闰年: %d\n", IsLeapYear(2000));
printf("2024 闰年: %d\n", IsLeapYear(2024));
printf("1900 闰年: %d\n", IsLeapYear(1900));
printf("2023 闰年: %d\n", IsLeapYear(2023));
// 测试范围
printf("\n【范围检查】\n");
printf("50 在 [0,100]: %d\n", InRange(50, 0, 100));
printf("150 在 [0,100]: %d\n", InRange(150, 0, 100));
return 0;
}
6、课后作业
6.1、作业1:简化条件
将以下代码简化:
if (x > 0) {
if (x < 100) {
result = 1;
} else {
result = 0;
}
} else {
result = 0;
}
6.2、作业2:短路求值应用
使用短路求值实现安全的字符串长度检查函数:
int SafeStrlen(const char* str);
// 如果str为NULL返回0,否则返回实际长度
6.3、作业3:密码验证
实现密码强度检查函数,要求:
- 长度至少8位
- 包含大写字母
- 包含小写字母
- 包含数字