C语言基础-三、流程控制语句

目录

1、顺序结构

2、分支结构

[2.1 if 语句](#2.1 if 语句)

[单分支 if](#单分支 if)

[双分支 if-else](#双分支 if-else)

[多分支 if-else if](#多分支 if-else if)

[2.2 switch 语句](#2.2 switch 语句)

3、循环结构

[3.1 for 循环](#3.1 for 循环)

[3.2 while 循环](#3.2 while 循环)

[3.3 do-while 循环](#3.3 do-while 循环)

[3.4 for vs while 对比](#3.4 for vs while 对比)

4、循环应用示例

[4.1 统计范围内能被6和8整除的数](#4.1 统计范围内能被6和8整除的数)

[4.2 整数反转](#4.2 整数反转)

[4.3 判断整数是否为回文数](#4.3 判断整数是否为回文数)

[4.4 判断字符串是否为回文](#4.4 判断字符串是否为回文)

[4.5 用循环实现乘除法](#4.5 用循环实现乘除法)

5、嵌套循环

[5.1 打印图形](#5.1 打印图形)

[5.2 九九乘法表](#5.2 九九乘法表)

[5.3 统计质数(1-100)](#5.3 统计质数(1-100))

[5.4 计算 1¹ + 2² + 3³ + ... + 10¹⁰](#5.4 计算 1¹ + 2² + 3³ + ... + 10¹⁰)

[6、跳出循环与 goto](#6、跳出循环与 goto)

[6.1 break 和 continue](#6.1 break 和 continue)

[6.2 goto 语句](#6.2 goto 语句)

7、枚举思想

[7.1 水仙花数(三位数)](#7.1 水仙花数(三位数))

[7.2 完数](#7.2 完数)


1、顺序结构

定义:程序从上往下依次执行,是程序默认的执行方式。

cpp 复制代码
// 示例
int a = 10;
int b = 20;
int sum = a + b;
printf("%d\n", sum);  // 按顺序依次执行

2、分支结构

程序执行过程中根据条件选择不同的执行路径。

2.1 if 语句

单分支 if
cpp 复制代码
if (关系表达式) {
    语句体;
}
// 关系表达式成立(为真)时执行语句体
双分支 if-else
cpp 复制代码
if (关系表达式) {
    语句体A;
} else {
    语句体B;
}
// 关系表达式成立执行A,否则执行B
多分支 if-else if
cpp 复制代码
if (关系表达式1) {
    语句体A;
} else if (关系表达式2) {
    语句体B;
} else if (关系表达式3) {
    语句体C;
} else {
    语句体N;
}

⚠️ 注意

  • 不加花括号时,else 会匹配最近一个同级的 if
  • 建议始终使用花括号,避免歧义
cpp 复制代码
// ❌ 容易出错的写法
if (a > 0)
    if (b > 0)
        printf("1");
else  // 这个else匹配的是内层if,不是外层if
    printf("2");

// ✅ 推荐写法
if (a > 0) {
    if (b > 0) {
        printf("1");
    }
} else {
    printf("2");
}

2.2 switch 语句

cpp 复制代码
switch (表达式) {
    case 值1:
        语句体1;
        break;
    case 值2:
        语句体2;
        break;
    ...
    default:
        语句体n;
        break;  // default后的break可省略(通常在最后)
}

执行流程

  1. 计算表达式的值
  2. 依次与 case 后的值比较,匹配则执行相应语句
  3. 遇到 break 结束 switch,否则继续执行后续 casecase穿透
  4. 所有 case 都不匹配时,执行 default

⚠️ 注意事项

  • switch 表达式只能是整数类型(int、char、enum等)
  • case 后的值必须是常量表达式
  • 每个 case 后建议加 break,避免意外穿透
cpp 复制代码
// case穿透示例(有意为之)
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:
        days = 28;
        break;
}

3、循环结构

重复执行某段代码,直到满足结束条件。

3.1 for 循环

cpp 复制代码
for (初始化语句; 条件判断语句; 条件控制语句) {
    循环体语句;
}
部分 说明 执行时机
初始化语句 设置循环初始状态 循环开始前执行一次
条件判断语句 循环继续的条件 每次循环前判断
条件控制语句 更新循环变量 每次循环体执行后
循环体语句 要重复执行的代码 条件为真时执行

执行流程

cpp 复制代码
初始化 → 条件判断 → (真)循环体 → 条件控制 → 条件判断 → ...
                              ↓
                            (假)结束

灵活写法

cpp 复制代码
// 方式一:初始化在外部
int i = 1;
for (; i <= 100; i++) {
    printf("hello world\n");
}

// 方式二:标准写法
for (int i = 1; i <= 100; i++) {
    printf("hello world\n");
}

// 方式三:省略部分(无限循环)
for (;;) {
    // 需要手动break退出
}

3.2 while 循环

cpp 复制代码
初始化语句;
while (条件判断语句) {
    循环体语句;
    条件控制语句;
}

适用场景:不知道循环次数,只知道结束条件

3.3 do-while 循环

cpp 复制代码
初始化语句;
do {
    循环体语句;
    条件控制语句;
} while (条件判断语句);

执行流程

复制代码
初始化 → 循环体 → 条件控制 → 条件判断 → (真)循环体 → ...
                                      ↓
                                    (假)结束

⚠️ 注意do-while 至少执行一次循环体

3.4 for vs while 对比

特性 for 循环 while 循环
适用场景 已知循环次数或范围 未知循环次数,只知结束条件
结构 三部分集中声明 分散声明
运行规则 相同 相同

4、循环应用示例

4.1 统计范围内能被6和8整除的数

cpp 复制代码
// 1. 键盘录入两个数字
int num1, num2;
printf("请录入两个整数:\n");
scanf("%d %d", &num1, &num2); 
// 2. 确定范围(处理大小顺序)
int min = num1 < num2 ? num1 : num2;
int max = num1 > num2 ? num1 : num2;

// 3. 统计个数
int count = 0;
for (int i = min; i <= max; i++) {
    if (i % 6 == 0 && i % 8 == 0) {  // 等价于 i % 24 == 0
        count++;
    }
}

// 4. 打印结果
printf("在这个范围当中,既能被6整除又能被8整除的数字一共有%d个\n", count); 

4.2 整数反转

cpp 复制代码
int number = 123;
int rev = 0;

// 循环结束条件:number == 0
while (number != 0) {
    int temp = number % 10;    // 获取最后一位
    number = number / 10;      // 去掉最后一位
    rev = rev * 10 + temp;     // 拼接到rev
}

printf("%d\n", rev);  // 输出:321

执行过程追踪(以456为例):

轮次 temp number rev
1 6 45 6
2 5 4 6×10+5=65
3 4 0 65×10+4=654

4.3 判断整数是否为回文数

cpp 复制代码
#include <stdio.h>

int main() {
    int num, original, reversed = 0, remainder;
    
    printf("请输入一个整数:");
    scanf("%d", &num);
    
    original = num;  // 保存原始值
    
    // 反转数字
    while (num != 0) {
        remainder = num % 10;           // 获取最后一位
        reversed = reversed * 10 + remainder;  // 构建反转数
        num /= 10;                      // 去掉最后一位
    }
    
    // 判断是否回文
    if (original == reversed) {
        printf("%d 是回文数。\n", original);
    } else {
        printf("%d 不是回文数。\n", original);
    }
    
    return 0;
}

4.4 判断字符串是否为回文

cpp 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    char str[100];
    int i, length;
    int isPalindrome = 1;  // 假设是回文
    
    printf("请输入一个字符串:");
    scanf("%s", str);
    
    length = strlen(str);
    
    // 从两端向中间比较字符
    for (i = 0; i < length / 2; i++) {
        if (str[i] != str[length - i - 1]) {
            isPalindrome = 0;  // 发现不同,不是回文
            break;
        }
    }
    
    if (isPalindrome) {
        printf("%s 是回文字符串。\n", str);
    } else {
        printf("%s 不是回文字符串。\n", str);
    }
    
    return 0;
}

4.5 用循环实现乘除法

cpp 复制代码
// 乘法:a × b = a + a + ... + a(共b次)
int multiply(int a, int b) {
    int result = 0;
    for (int i = 0; i < b; i++) {
        result += a;
    }
    return result;
}

// 除法:a ÷ b,通过不断减b计算商和余数
int divide(int a, int b, int *remainder) {
    int quotient = 0;
    while (a >= b) {
        a -= b;
        quotient++;
    }
    *remainder = a;
    return quotient;
}

// 示例:11 ÷ 3
// 11 - 3 = 8  → 第1次
// 8  - 3 = 5  → 第2次
// 5  - 3 = 2  → 第3次
// 结果:商 = 3,余数 = 2

5、嵌套循环

5.1 打印图形

cpp 复制代码
// 倒三角
for (int i = 1; i <= 5; i++) {
    for (int j = i; j <= 5; j++) {  // 每行(6-i)个*
        printf("*");
    }
    printf("\n");
}
/* 输出:
*****
****
***
**
*
*/

// 正三角
for (int i = 1; i <= 5; i++) {
    for (int j = 1; j <= i; j++) {  // 每行i个*
        printf("*");
    }
    printf("\n");
}
/* 输出:
*
**
***
****
*****
*/

5.2 九九乘法表

cpp 复制代码
for (int i = 1; i <= 9; i++) {
    for (int j = 1; j <= i; j++) {
        printf("%d × %d = %d\t", j, i, i * j);
    }
    printf("\n");
}

5.3 统计质数(1-100)

cpp 复制代码
// 质数:大于1的自然数,除了1和它本身外没有其他因数
int count = 0;

for (int i = 2; i <= 100; i++) {
    int isPrime = 1;  // 假设是质数
    
    // 优化:只需判断到 sqrt(i)
    for (int j = 2; j * j <= i; j++) {
        if (i % j == 0) {
            isPrime = 0;  // 找到因子,不是质数
            break;
        }
    }
    
    if (isPrime) {
        count++;
    }
}

printf("1-100共有%d个质数\n", count);  // 输出:25

5.4 计算 1¹ + 2² + 3³ + ... + 10¹⁰

cpp 复制代码
long long res = 0;

for (int i = 1; i <= 10; i++) {
    long long pow = 1;
    for (int j = 1; j <= i; j++) {
        pow = pow * i;
    }
    res = res + pow;
}

printf("%lld\n", res);

6、跳出循环与 goto

6.1 break 和 continue

关键字 作用 适用
break 跳出当前循环 for/while/do-while/switch
continue 跳过本次循环,进入下一次 for/while/do-while

6.2 goto 语句

cpp 复制代码
// 标号定义
label_name:
    语句;

// 跳转使用
goto label_name;

⚠️ 注意goto 会破坏代码结构

cpp 复制代码
// 跳出多层循环的替代方案(推荐用标志位)
int found = 0;
for (int i = 0; i < 10 && !found; i++) {
    for (int j = 0; j < 10 && !found; j++) {
        if (condition) {
            found = 1;
        }
    }
}

7、枚举思想

定义:列举问题的所有可能性,逐一检查是否符合要求。

7.1 水仙花数(三位数)

各位数字的立方和等于该数本身(如 153 = 1³ + 5³ + 3³)

方法一:单循环拆位

cpp 复制代码
#include <stdio.h>

int main() {
    printf("所有水仙花数:\n");
    
    for (int num = 100; num <= 999; num++) {
        int a = num / 100;        // 百位
        int b = (num / 10) % 10;  // 十位
        int c = num % 10;         // 个位
        
        if (num == a*a*a + b*b*b + c*c*c) {
            printf("%d ", num);
        }
    }
    
    return 0;
}

方法二:三重循环枚举

cpp 复制代码
for (int a = 1; a <= 9; a++) {      // 百位:1-9
    for (int b = 0; b <= 9; b++) {  // 十位:0-9
        for (int c = 0; c <= 9; c++) {  // 个位:0-9
            int num = 100*a + 10*b + c;
            if (num == a*a*a + b*b*b + c*c*c) {
                printf("%d\n", num);
            }
        }
    }
}

7.2 完数

定义:一个正整数,它除了自身之外的所有正因数(真因数)之和等于它本身。

  • 例如:6 = 1 + 2 + 3,28 = 1 + 2 + 4 + 7 + 14

基础版本

cpp 复制代码
#include <stdio.h>

int main() {
    int n;
    printf("请输入一个正整数:");
    scanf("%d", &n);
    
    printf("%d以内的完数有:", n);
    
    int count = 0;
    
    for (int i = 1; i <= n; i++) {
        int sum = 0;
        
        // 找出所有真因数
        for (int j = 1; j < i; j++) {
            if (i % j == 0) {
                sum += j;
            }
        }
        
        if (sum == i) {
            printf("%d ", i);
            count++;
        }
    }
    
    if (count == 0) {
        printf("没有完数");
    }
    
    printf("\n");
    return 0;
}

优化版本

cpp 复制代码
#include <stdio.h>

int main() {
    int n;
    printf("请输入一个正整数:");
    scanf("%d", &n);
    
    printf("%d以内的完数有:", n);
    
    int count = 0;
    
    // 1不是完数,从2开始
    for (int i = 2; i <= n; i++) {
        int sum = 1;  // 1一定是真因数
        
        // 优化:只需遍历到 i/2
        for (int j = 2; j <= i / 2; j++) {
            if (i % j == 0) {
                sum += j;
            }
        }
        
        if (sum == i) {
            printf("%d ", i);
            count++;
        }
    }
    
    if (count == 0) {
        printf("没有完数");
    }
    
    printf("\n");
    return 0;
}
相关推荐
qq8406122332 小时前
Nodejs+vue基于elasticsearch的高校科研期刊信息管理系统_mb8od
前端·vue.js·elasticsearch
小杨互联网2 小时前
项目CyberScan Pro jar软件安全成分分析插件
java·jar·软件成分分析·jar安全分析
组合缺一3 小时前
Java 版 Claude Code CLI 来了!(国产开源项目)Solon Code CLI 发布
java·ai·开源·llm·solon·cli·claudecode
StandbyTime3 小时前
C语言学习-菜鸟教程C经典100例-练习79
c语言
哆啦A梦15883 小时前
Vue3魔法手册 作者 张天禹 012_路由_(一)
前端·typescript·vue3
javaIsGood_4 小时前
Java基础面试题
java·开发语言
indexsunny4 小时前
互联网大厂Java求职面试实战:基于电商场景的技术问答及解析
java·spring boot·redis·kafka·security·microservices·面试指导
RaidenLiu4 小时前
别再手写 MethodChannel 了:Flutter Pigeon 工程级实践与架构设计
前端·flutter·前端框架
Forget_85504 小时前
RHEL——LVS模式
java·开发语言·lvs