【C语言】 结构化编程与选择结构

编程结构介绍

C语言是一种面向过程的结构化编程语言,与C++的面向对象特性不同。结构化编程的核心思想是将复杂程序分解为三种基本结构,通过它们的组合实现任意复杂的程序逻辑。

三种基本编程结构

  1. 顺序结构

    • 程序默认的执行方式
    • 代码按照书写顺序从上到下依次执行
    • 每条语句执行一次
    • 最基本的程序结构,所有程序都包含顺序结构
  2. 选择结构(分支结构)

    • 根据条件判断的结果,选择性地执行部分代码
    • 实现程序的条件分支逻辑
    • 包括if-else和switch-case两种主要形式
  3. 循环结构

    • 在条件满足时重复执行特定代码段
    • 实现程序的重复执行逻辑
    • 包括for、while、do-while三种形式

九大控制语句(C语言关键字)

C语言通过以下9个关键字实现程序流程控制:

类别 语句 功能说明
选择结构 if-else 条件判断,二选一或多选一
选择结构 switch-case 多路分支选择
循环结构 for 计数循环,明确循环次数
循环结构 while 条件循环,先判断后执行
循环结构 do-while 条件循环,先执行后判断
跳转语句 break 跳出当前循环或switch结构
跳转语句 continue 跳过本次循环剩余部分
跳转语句 goto 无条件跳转(慎用)
函数控制 return 从函数返回

选择结构(分支结构)

选择结构允许程序根据条件判断结果,选择执行不同的代码路径,是程序实现智能判断的基础。

if-else语句

标准格式

c 复制代码
if (条件表达式) {
    // 程序段1:条件为真时执行
} else {
    // 程序段2:条件为假时执行
}

语法说明:

  • if:中文意为"如果"
  • else:中文意为"否则"
  • 条件表达式:可以是任何返回数值的表达式,C语言中0为假,非0为真
  • 大括号{}:用于包含多条语句,如果只有一条语句可以省略(但不推荐)

条件表达式的真值判断

c 复制代码
// 条件判断示例
if (0)           // 假,0为假
if (1)           // 真,非0为真
if (-1)          // 真,非0为真
if (0.000001)    // 真,浮点数非0为真
if (a)           // 等价于 if (a != 0)
if (a == 0)      // a等于0时为真
if (a = 1)       // 注意:这是赋值,不是比较!总是为真(a被赋值为1,表达式值为1)

重要提醒: =是赋值运算符,==才是比较运算符,两者容易混淆但功能完全不同!

if-else多分支结构

c 复制代码
// 多分支if-else结构
if (条件1) {
    // 程序段1
} else if (条件2) {
    // 程序段2
} else if (条件3) {
    // 程序段3
} else {
    // 程序段4:所有条件都不满足时执行
}

执行逻辑:

  1. 判断条件1,若为真则执行程序段1,然后直接结束整个if结构
  2. 若条件1为假,判断条件2,若为真则执行程序段2,然后结束
  3. 若条件2也为假,判断条件3,若为真则执行程序段3,然后结束
  4. 若所有条件都为假,执行else中的程序段4

if-else的省略形式

c 复制代码
// 形式1:省略else分支
if (条件) {
    // 条件为真时执行
}
// 条件为假时什么都不做,继续执行后续代码

// 形式2:省略大括号(单条语句)
if (条件)
    statement1;  // 只有这一条语句属于if结构
statement2;      // 这条语句总是执行,不属于if结构

// 等价于
if (条件) {
    statement1;
}
statement2;

最佳实践: 即使只有一条语句,也建议使用大括号,提高代码可读性和避免潜在错误。

if-else注意事项

  1. else不能单独使用,必须与if配对
  2. else与最近未匹配的if配对(注意嵌套时的匹配问题)
  3. if和else最多执行其中一个分支
  4. else后面不能直接跟条件表达式,如果需要条件判断应使用else if
  5. 使用大括号明确代码块范围,避免"悬挂else"问题
完整if-else示例
c 复制代码
#include <stdio.h>

int main(void) {
    char ch;
    printf("请输入一个字符:\n");
    scanf("%c", &ch);
    
    if (ch >= 'a' && ch <= 'z') {        // 小写字母
        ch -= 32;                        // 转换为大写(ASCII码差32)
        printf("转换为大写:%c\n", ch);
    } else if (ch >= 'A' && ch <= 'Z') { // 大写字母
        ch += 32;                        // 转换为小写
        printf("转换为小写:%c\n", ch);
    } else if (ch >= '0' && ch <= '9') { // 数字字符
        int num = ch - '0';              // 字符数字转换为整型数字
        printf("数字值:%d\n", num);
    } else {                             // 其他字符
        printf("输入的不是字母或数字\n");
    }
    
    return 0;
}

switch-case语句

switch-case是另一种实现多分支选择的结构,特别适用于基于离散值的选择。

标准格式

c 复制代码
switch (整型表达式) {
    case 常量1:
        程序段1;
        break;
    case 常量2:
        程序段2;
        break;
    case 常量3:
        程序段3;
        break;
    default:
        默认程序段;
        break;
}

语法规则

  1. 表达式必须是整型(int、char、enum等),不能是浮点型或字符串
  2. case后面必须是常量表达式,不能是变量或非常量表达式
  3. break的作用:跳出整个switch结构
  4. default的作用:所有case都不匹配时执行(可省略)
  5. 执行流程
    • 计算switch表达式的值
    • 与各个case常量比较,找到匹配项
    • 从匹配的case开始执行,直到遇到break或switch结束
    • 若无匹配且存在default,执行default部分

break的省略与穿透效应

c 复制代码
// 示例:根据月份判断季节
#include <stdio.h>

int main(void) {
    int month;
    printf("请输入月份:");
    scanf("%d", &month);
    
    printf("季节:");
    switch (month) {
        case 12:
        case 1:
        case 2:
            printf("冬季\n");
            break;
        case 3:
        case 4:
        case 5:
            printf("春季\n");
            break;
        case 6:
        case 7:
        case 8:
            printf("夏季\n");
            break;
        case 9:
        case 10:
        case 11:
            printf("秋季\n");
            break;
        default:
            printf("月份输入错误!\n");
    }
    
    return 0;
}

注意: 故意省略break可以实现多个case共享同一段代码,但需要明确注释,避免被认为是错误。

default的位置问题

c 复制代码
// default可以放在任意位置,但执行顺序总是在最后
switch (value) {
    case 1:
        printf("值为1\n");
        break;
    default:  // 放在中间
        printf("默认情况\n");
        break;
    case 2:
        printf("值为2\n");
        break;
}

// 实际执行顺序:
// 1. value==1 → 执行case 1
// 2. value==2 → 执行case 2
// 3. 其他值 → 执行default

完整switch-case示例

c 复制代码
// 示例:月份天数查询(switch实现)
#include <stdio.h>

int main(void) {
    int year, month, days;
    int isLeapYear = 0;
    
    printf("请输入年份:");
    scanf("%d", &year);
    printf("请输入月份:");
    scanf("%d", &month);
    
    // 判断闰年
    if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
        isLeapYear = 1;
    }
    
    // 使用switch判断月份天数
    switch (month) {
        case 1: case 3: case 5: case 7: case 8: case 10: case 12:
            days = 31;
            break;
        case 4: case 6: case 9: case 11:
            days = 30;
            break;
        case 2:
            if (isLeapYear) {
                days = 29;
            } else {
                days = 28;
            }
            break;
        default:
            printf("月份输入错误!\n");
            return -1;
    }
    
    printf("%d年%d月有%d天\n", year, month, days);
    return 0;
}

switch-case的局限性

  1. 只能处理整型表达式,不能处理浮点数或字符串
  2. case值必须是常量,不能是变量或范围
  3. 不适合处理复杂条件逻辑,特别是包含关系运算符的条件

if-else与switch-case对比与选择

适用场景对比

特性 if-else switch-case
表达式类型 任意表达式(返回数值) 仅限整型表达式
条件形式 关系表达式、逻辑表达式等 与常量值相等比较
多分支处理 通过else if链实现 通过多个case实现
范围判断 直接支持(如 score >= 90 不支持,需转换
可读性 复杂时较差 离散值选择时较好
执行效率 条件复杂时可能较慢 编译优化后可能更快

选择原则

优先使用if-else的情况:

  1. 条件基于数值范围(如分数段划分)
  2. 条件包含关系运算符(>、<、>=、<=)
  3. 条件包含逻辑运算符(&&、||、!)
  4. 判断条件非整型(如浮点数、字符串)
  5. 分支数量较少(3个以下)

优先使用switch-case的情况

  1. 基于离散整数值的选择
  2. 分支数量较多(4个以上)
  3. 多个分支共享相同代码
  4. 需要编译器优化跳转表的情况

选择结构实际编程建议与常见错误

编程建议:

  1. 明确优先选择条件:将最可能为真的条件放在前面,提高效率
  2. 使用大括号:即使只有一条语句也使用大括号,提高可读性和避免错误
  3. 合理注释:对复杂条件逻辑添加注释说明
  4. 避免深度嵌套:if-else嵌套不应超过3层,过深应考虑重构
  5. 统一编码风格:保持缩进一致,提高代码可读性

常见错误与避免方法

c 复制代码
// 错误1:误用=代替==
if (a = 5) {        // 错误:这是赋值,总是为真
    // ...
}

// 正确写法
if (a == 5) {       // 正确:比较是否相等
    // ...
}

// 错误2:悬空else问题
if (condition1)
    if (condition2)
        statement1;
else                // 这个else与哪个if匹配?
    statement2;

// 正确写法:使用大括号明确范围
if (condition1) {
    if (condition2) {
        statement1;
    }
} else {
    statement2;
}

// 错误3:switch中忘记break
switch (value) {
    case 1:
        printf("值为1\n");
        // 忘记break,会继续执行case 2
    case 2:
        printf("值为2\n");
        break;
}

// 错误4:case中使用变量
int var = 10;
switch (value) {
    case var:       // 错误:case后必须是常量
        // ...
        break;
}

性能优化建议:

  1. if-else链优化:将最可能为真的条件放在最前面
  2. switch优化:当case值连续时,编译器可能生成更高效的跳转表
  3. 避免重复计算:将多次使用的表达式结果保存到变量中
  4. 使用查表法:对于固定的映射关系,可以使用数组查表代替多重if-else
c 复制代码
// 查表法示例:根据月份获取天数(不考虑闰年)
int monthDays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

if (month >= 1 && month <= 12) {
    days = monthDays[month - 1];  // 直接查表,比多个if-else更高效
}
相关推荐
Yvonne爱编码2 小时前
JAVA数据结构 DAY3-List接口
java·开发语言·windows·python
一方_self2 小时前
了解和使用python的click命令行cli工具
开发语言·python
南宫码农2 小时前
我的电视 - Android原生电视直播软件 完整使用教程
android·开发语言·windows·电视盒子
CoderCodingNo2 小时前
【GESP】C++四级/五级练习题 luogu-P1223 排队接水
开发语言·c++·算法
爱编码的小八嘎2 小时前
C语言对话-22.想睡觉,偶然
c语言
sycmancia3 小时前
C++进阶01——示例
开发语言·c++
CoderCodingNo3 小时前
【GESP】C++五级/四级练习题 luogu-P1413 坚果保龄球
开发语言·c++·算法
眼眸流转3 小时前
Java代码变更影响分析(一)
java·开发语言
Yvonne爱编码3 小时前
JAVA数据结构 DAY4-ArrayList
java·开发语言·数据结构