C&C++快速入门

6、选择结构

1、课程目标

  • 掌握if-else条件判断语句
  • 掌握switch-case多分支选择
  • 理解条件表达式(三元运算符)
  • 了解条件判断在安全编程中的应用

2、名词解释

术语 英文 说明
条件语句 Conditional Statement 根据条件执行不同代码块
布尔表达式 Boolean Expression 结果为真或假的表达式
短路求值 Short-circuit Evaluation 逻辑运算提前终止的特性
三元运算符 Ternary Operator ?: 条件表达式
分支预测 Branch Prediction CPU对条件跳转的预测机制
悬空else Dangling Else else与if的配对歧义问题
穿透 Fall-through switch中不加break的行为

3、代码实现

1. if-else语句详解

#include <stdio.h>
#include <windows.h>

int main() {
    printf("=== if-else 语句演示 ===\n\n");
    
    // 1. 基础if-else
    int value = 42;
    if (value > 0) {
        printf("%d 是正数\n", value);
    } else if (value < 0) {
        printf("%d 是负数\n", value);
    } else {
        printf("值为零\n");
    }
    
    // 2. 条件中的常见陷阱
    printf("\n【常见陷阱】\n");
    int x = 0;
    
    // 错误写法: 赋值而非比较
    // if (x = 1)  // 这总是为真!
    
    // 正确写法
    if (x == 1) {
        printf("x等于1\n");
    } else {
        printf("x不等于1 (x=%d)\n", x);
    }
    
    // 防御性写法:常量放左边
    if (1 == x) {  // 如果误写成 1 = x,编译器会报错
        printf("x等于1\n");
    }
    
    // 3. 嵌套if与悬空else
    printf("\n【嵌套if注意事项】\n");
    int a = 1, b = 0;
    
    // 歧义代码(不推荐)
    // if (a) if (b) printf("A"); else printf("B");
    
    // 明确的写法
    if (a) {
        if (b) {
            printf("a和b都为真\n");
        } else {
            printf("a为真,b为假\n");
        }
    }
    
    return 0;
}

2. switch-case语句

#include <stdio.h>
#include <windows.h>

void PrintErrorMessage(DWORD errorCode) {
    switch (errorCode) {
        case ERROR_SUCCESS:  // 0
            printf("操作成功\n");
            break;
            
        case ERROR_FILE_NOT_FOUND:  // 2
            printf("文件未找到\n");
            break;
            
        case ERROR_ACCESS_DENIED:  // 5
            printf("访问被拒绝\n");
            break;
            
        case ERROR_INVALID_HANDLE:  // 6
            printf("无效句柄\n");
            break;
            
        case ERROR_NOT_ENOUGH_MEMORY:  // 8
        case ERROR_OUTOFMEMORY:        // 14
            // 多个case共用处理(穿透)
            printf("内存不足\n");
            break;
            
        default:
            printf("未知错误: %lu\n", errorCode);
            break;
    }
}

int main() {
    printf("=== switch-case 演示 ===\n\n");
    
    // Windows错误码处理
    printf("【错误码处理】\n");
    PrintErrorMessage(ERROR_SUCCESS);
    PrintErrorMessage(ERROR_FILE_NOT_FOUND);
    PrintErrorMessage(ERROR_ACCESS_DENIED);
    PrintErrorMessage(12345);
    
    // 字符处理
    printf("\n【字符分类】\n");
    char ch = 'A';
    switch (ch) {
        case 'a': case 'e': case 'i': case 'o': case 'u':
        case 'A': case 'E': case 'I': case 'O': case 'U':
            printf("'%c' 是元音字母\n", ch);
            break;
        default:
            if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
                printf("'%c' 是辅音字母\n", ch);
            } else {
                printf("'%c' 不是字母\n", ch);
            }
    }
    
    return 0;
}

3. 三元运算符与条件表达式

#include <stdio.h>

int main() {
    printf("=== 三元运算符 ===\n\n");
    
    // 基础用法
    int a = 10, b = 20;
    int max = (a > b) ? a : b;
    printf("max(%d, %d) = %d\n", a, b, max);
    
    // 嵌套三元运算符(可读性差,不推荐)
    int x = 5;
    const char* result = (x > 0) ? "正数" : 
                         (x < 0) ? "负数" : "零";
    printf("%d%s\n", x, result);
    
    // 实用场景:赋值时选择
    int debug = 1;
    int logLevel = debug ? 3 : 1;  // 调试模式用更高日志级别
    printf("日志级别: %d\n", logLevel);
    
    // 绝对值
    int value = -42;
    int absValue = (value < 0) ? -value : value;
    printf("|%d| = %d\n", value, absValue);
    
    return 0;
}

4. 安全编程中的条件判断

#include <stdio.h>
#include <windows.h>

// 安全的文件打开示例
BOOL SafeOpenFile(LPCSTR filename, HANDLE* pHandle) {
    // 参数验证
    if (filename == NULL) {
        printf("错误: 文件名为空\n");
        return FALSE;
    }
    
    if (pHandle == NULL) {
        printf("错误: 输出参数为空\n");
        return FALSE;
    }
    
    // 尝试打开文件
    *pHandle = CreateFileA(
        filename,
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL
    );
    
    if (*pHandle == INVALID_HANDLE_VALUE) {
        DWORD error = GetLastError();
        printf("打开文件失败, 错误码: %lu\n", error);
        return FALSE;
    }
    
    return TRUE;
}

int main() {
    printf("=== 安全编程示例 ===\n\n");
    
    HANDLE hFile = NULL;
    
    // 测试各种情况
    SafeOpenFile(NULL, &hFile);              // 测试空文件名
    SafeOpenFile("test.txt", NULL);          // 测试空输出参数
    SafeOpenFile("nonexistent.txt", &hFile); // 测试不存在的文件
    
    // 成功打开(如果文件存在)
    if (SafeOpenFile("C:\\Windows\\System32\\notepad.exe", &hFile)) {
        printf("文件打开成功!\n");
        CloseHandle(hFile);
    }
    
    return 0;
}

5、课后作业

5.1、作业1:成绩等级转换

实现一个函数,将分数(0-100)转换为等级(A/B/C/D/F):

  • 90-100: A
  • 80-89: B
  • 70-79: C
  • 60-69: D
  • 0-59: F

5.2、作业2:简易计算器

使用switch实现支持+、-、*、/的简易计算器,要处理除零错误。

5.3、作业3:权限检查

实现一个函数,检查用户权限(使用位掩码):

#define PERM_READ   0x01
#define PERM_WRITE  0x02
#define PERM_EXEC   0x04
#define PERM_ADMIN  0x08

void CheckPermission(int userPerm, int requiredPerm);