控制流

C语言控制流:二路分支、多路分支、三大循环、break/continue、常量修饰,学完就能写实用脚本!


一、二路分支:if · if-else

  • 逻辑:程序中某段代码需要在满足某个条件时才能运行
  • 形式:
    a.if 语句:表达一种 如果-则 的条件执行关系
    b.if-else 语句:表达一种 如果-否则 的互斥分支关系

① 基本写法

if (表达式)          // 表达式为真(非0)才执行
{
    语句块;
}
//示例
// if 语句
if(a%2 == 0)
{
    printf("a是偶数\n");
}

② 互斥分支

if (表达式)
{
    语句块A;
}
else
{
    语句块B;
}
//习惯:哪怕只有一条语句,也请加大括号!避免后期维护出错。
//示例
//if-else 语句
if(a%2 == 0)
{
    printf("a是偶数\n");
}
else
{
    printf("a是奇数\n");
}

③ 多条件级联

if (score >= 90)            // 从高到低判断
    puts("A");
else if (score >= 80)
    puts("B");
else if (score >= 60)
    puts("C");
else
    puts("D");

注意事项

a. if 语句可以单独使用else 语句不可以,else 语句必须跟 if 语句配套使用

b. 不管是 if 语句还是 else 语句,代码块都必须使用大括号 {} 括起来,否则只有首个逻辑语句有效

错误示例 vs 正确示例

// ❌ 错误:缺少大括号,只有 printf 受 if 控制
if (condition)
    printf("条件成立\n");
    do_something();  // 这行总是会执行!

// ✅ 正确:使用大括号明确代码块
if (condition) {
    printf("条件成立\n");
    do_something();  // 只在条件成立时执行
}
// ❌ 错误:else 不能单独使用
else {
    printf("这会导致编译错误\n");
}

// ✅ 正确:else 必须配套 if 使用
if (condition) {
    // 条件成立时执行
} else {
    // 条件不成立时执行
}

二、多路分支:switch-case

  • 逻辑:根据不同的条件执行不同的代码片段
    语法
switch( 整型表达式 )
{
     case 整型预设值1:  
         代码块
         break ; // 跳出switch
    case 整型预设值2:  
         代码块
         break ; // 跳出switch
    case 整型预设值N:  
         代码块
         break ; // 跳出switch
    default: // 以上都不匹配
        代码块...
        break ; // 可有可无
}

规则速记:

  • 1.switch(整型表达式) —— 必须是整型或字符,不能是字符串/浮点
  • 2.case 常量: —— 编译期常量,不能是变量或const int
  • 3.没有break就继续往下落break 语句的作用是跳出整个 swtich 结构,没有 break 程序会略过后方的case往直接执行下一个逻辑块的代码,跳过判断直接运行
  • 4.default可省略不是必须的,一般放在最后面(因此不需要 break)

示例:简易计算器

char op;
int  a = 6, b = 2;

scanf(" %c", &op);          // 注意前面空格,吃掉回车
switch (op) {
case '+': printf("%d\n", a + b); break;
case '-': printf("%d\n", a - b); break;
case '*': printf("%d\n", a * b); break;
case '/':
    if (b != 0) printf("%d\n", a / b);
    else        puts("Div0!");     break;
default: puts("Unknown op");       break;
}

三、循环三连击:while · do-while · for

while循环

运行示例

入口判断(当条件满足时 【进入】 循环体,不满足时退出)

① while —— 先判断再执行

// 循环输出一系列整数,直到100为止
int a;
scanf("%d", &a); //  99 
while(a <= 100) // 如果a 小于等于100 则进入循环
{
    printf("%d\n", a);
    a++;
}

do-while 循环

运行示例

出口判断,当条件为假时【离开】循环

② do-while ——先执行再判断,至少1次

// 循环输出一系列整数,直到100为止
int a;
scanf("%d", &a);
do
{
    printf("%d\n", a);
    a++;
}while(a <= 100);  // 如果a 大于等于 100 则退出循环
//    do while的最后必须有 ; 分号

语法点

  • while 循环先进行判断,条件为真后才执行循环体,因此循环体可能一遍也不执行。
  • do-while 循环先执行循环体,再进行判断,因此循环体至少会执行一遍。
  • do-while 循环中的while 语句后面有分号

for循环

逻辑: 与 while 循环类似,但更加紧凑,for 循环将控制循环的变量集中在一行

  • 语法
for ( 初始化语句 ; 条件判断 ; 条件迭代  )  // 三个表达式,每一个表达式都是一个独立的逻辑语句 
                                        // (分号 ; 是一个逻辑语句的结束标记 )
{
    // 循环体    
}

注意:

  • 初始化语句 --> 只会在第一次循环【之前】被执行,也只能执行一次
  • 条件判断 --> 在每一次循环执行之前被判断
  • 条件迭代 --> 在每一次循环执行之后被执行

③ for ——三要素放一行,最紧凑

// 循环输出一系列整数,直到100为止
int a;
for(a=30; a<=100; a++)
{
    printf("%d\n", a);
}

for( ;  ; )
{
    //死循环   
}

语法点:

  • 循环头的标准语法是: for(表达式1 ; 表达式2 ; 表达式3)
  • 表达式1一般用来初始化循环控制变量
  • 表达式2一般用来作为循环判定条件,为真则进入循环,为假则跳出循环
  • 表达式3一般用来更新循环控制变量
  • 三个表达式均可以省略,但分号不能省略

四、break vs continue

关键字 作用域 效果
break 循环 / switch ① 跳出 switch 语句; ② 跳出当层循环体(while\ do-while \ for
continue 循环 结束当次循环,进入下次循环

示例

switch(n)
{
case 1:
    printf("one\n");
    break;  // 跳出 switch 语句
case 2:
    printf("two\n");
    break;        
}

while(1)
{
    int n = scanf("%d", &a);
    if(n == 0)
        break; // 跳出当层 while 循环体
}

for(int i=1; i<=100; i++)
{
    if(i%7 == 0)
        continue; // 跳过所有能被7整除的数
     
    printf("%d\n", i);       
}

五、常量修饰 const

读法规则:从右往左读,* 读作 "指向"

const int ci = 10;      // ci 本身不可改
int const ci2 = 20;     // 同上

const int *p1 = &ci;    // p1 指向常量,*p1 不可改,p1 可改
int *const p2 = &x;     // p2 自身不可改,*p2 可改
const int *const p3 = &ci; // p3 和 *p3 都不可改
//示例
#include <stdio.h>

int main(void)
{
    int x = 100;
    int y = 200;
    
    // 1. 普通常量
    const int MAX_SIZE = 1024;
    // MAX_SIZE = 2048;  // ❌ 编译错误:不能修改常量
    
    // 2. 指向常量的指针
    const int *p1 = &x;
    // *p1 = 300;       // ❌ 错误:不能通过p1修改x的值
    p1 = &y;            // ✅ 正确:可以改变p1指向的地址
    
    // 3. 常量指针
    int *const p2 = &x;
    *p2 = 300;          // ✅ 正确:可以通过p2修改x的值
    // p2 = &y;         // ❌ 错误:不能改变p2指向的地址
    
    // 4. 指向常量的常量指针
    const int *const p3 = &x;
    // *p3 = 400;       // ❌ 错误:不能通过p3修改x的值
    // p3 = &y;         // ❌ 错误:不能改变p3指向的地址
    
    return 0;
}

六、goto语句

逻辑:无条件跳转
示例

int main()
{
    printf("%d\n", __LINE__); // 打印第3行 
    
    // 无条件跳转到label处 
    goto label;
    printf("%d\n", __LINE__); // 打印第7行,此处被略过
label:  
    printf("%d\n", __LINE__); // 打印第9行
}

语法:

  • goto语句直接跳转到本代码块中的标签处
  • 标签指的是以冒号结尾的标识符

作用:

  • goto语句的无条件跳转不利于程序的可读性,一般不建议使用
  • goto语句常被用在程序的错误处理中

综合实战:字符统计小工具

需求:从键盘读入一行字符,统计大写、小写、数字、其他各多少个?
完整源码

#include <stdio.h>
#include <ctype.h>      

int main(void)
{
    int upper = 0, lower = 0, digit = 0, other = 0;
    int ch;                     // 必须用 int,以便接收 EOF

    puts("请输入一串字符,回车结束:");
    while ((ch = getchar()) != '\n' && ch != EOF) {
        if (isupper(ch))       ++upper;
        else if (islower(ch))  ++lower;
        else if (isdigit(ch))  ++digit;
        else                   ++other;
    }

    printf("大写=%d 小写=%d 数字=%d 其他=%d\n", upper, lower, digit, other);
    return 0;
}

运行示例

运行示例
posted @ 2025-10-11 16:17  林明杰  阅读(14)  评论(0)    收藏  举报