C语言的分支与循环结构
前言
描述算法的计算步骤需要设计算法的控制结构,包括顺序结构,分支结构和循环结构。顺序结构指的是按顺序依次执行规则,分支结构则是根据条件选择一些规则的一部分执行,循环结构则控制规则的多次执行。下面讲解C语言中分支与循环结构是如何使用的。
分支结构
if-else语句
注意所有分支和循环语句除非套上大括号,否则默认只管一条语句,但是不能像普通语句一样加;否则默认结束。C语言中主要使用if-else语句实现分支结构,示例如下:
C
int input_number = 1;
if (input_number >= 0) //条件为真时执行,否则不执行
printf("正数\n");
else if (input_number <= 0 && input_number != 0) //!=表示不等于
printf("负数\n");
else //三个分支根据条件只选择一个执行
printf("0\n");
条件表达式返回真假,&&为逻辑与,二者均为真总体为真,否则为假;逻辑或||二者均为假才为假,否则为真,若左侧表达式的真假足以确定整个表达式的值,则不再执行后续表达式。
若有多个if-else语句,else总是和距离最近但未被else配对的if配对。
switch语句
switch语句本质上是特殊形式的if-else语句,并未新增任何其他功能。示例如下:
C
int reminder = 1;
switch (reminder) //reminder表示模2的余数
{
case 0:
printf("偶数\n");
break;
case 1:
printf("奇数\n");
break;
default:
printf("输入错误\n");
break;
}
注意switch(整型表达式),故case后面只能跟整型常量,switch在设计之初不像if-else语句一样一个条件成立,不再执行其余分支,表达式的值只决定执行的起点,用break终止继续执行。default类似于if-else语句中的else,位置任意,若其余均不成立,则执行default。
循环结构
while语句
C
int input_number = 1234;
while (input_number) //从个位逆序打印输入的正整数的每一位
{
printf("%d\n", input_number % 10); //一个数取模10即该数的个位
input_number /= 10; //n位数获取前面的n-1位数
}
while(表达式):当表达式结果为真时,反复执行。
for语句
C
int k = 10;
int n = 0;
int F_prev = 1; // 1赋值给F(n-1)
int F_curr = 4; //F(n)
int a_prev = 1;
for (n = 2; n <= k; ++n)
{
int a_curr = F_curr - F_prev;
int b_curr = a_curr - a_prev;
int F_next = F_curr + a_curr + b_curr; //二次差分求函数值
//更新数据
F_prev = F_curr;
F_curr = F_next; //注意顺序
a_prev = a_curr;
}
printf("%d\n", F_curr);
for(n = 2; 条件; ++n)表示n从2到k,先判条件是否成立,成立后执行循环体,最后再执行n++,回到判断条件,依次类推。 上述代码没有采用数组而采用循环依次更新数据是为了节约空间(当k很大时)。
for循环也可以用两个变量,示例如下:
C
int a = 0;
int b = 0;
for (b = 0, a = 10; b < a; b++, a--)
{
printf("b=%d,a=%d\n", b, a);
}
逗号表达式exp1,...,expN:从左往右依次执行,整个表达式结果仅取决于最后一个表达式,但是不能直接执行最后的表达式,因为最后一个表达式结果可能依赖于前面的表达式。
do-while语句
C
int input_number = 1234;
int count = 0;
do
{
count++; //需要先++:0也是1位数!
input_number /= 10;
}
while (input_number);
printf("%d\n", count); //input_number是几位数
do-while语句几乎和while语句一样,但是执行顺序不同。do-while是先执行循环体,再判断while条件是否成立,适合于至少得执行一次循环体(这里0也是一位数)。
goto语句
C
int i=0;
LOOP:
printf("%d ", i);
i++;
if (i <= 10)
goto LOOP;
goto来自于汇编的跳转指令(C脱胎于底层汇编语言),一开始没有while循环,因此用如上的goto来构造循环,但可能会破坏程序执行顺序,只能在一个函数内跳转,慎用!
LOOP称为地址标记,命名规则和变量相同,仅是地址标记,不占用运算指令,由编译器记录跳转位置的内存地址。
一种值得提倡的实践实例如下:
C
for (int i = 1; i < 10; i++)
{
for (int j = 1; j < 10; j++)
{
if (i * j == 42)
{
goto END_LOOP; // 直接一次性跳出两层循环
}
}
}
END_LOOP:
printf("找到目标\n");
注意break只能跳出一层循环,但goto可一次性跳出多层循环。
循环的关键字--break和continue
需要跳出本层循环体,用break终止本层循环,用continue跳过循环体中本次循环continue后面的部分,进行循环体的下一次循环。
循环的嵌套
C
int i = 0;
printf("2\n");
for (i = 3; i <= 10000; i += 2)
{
int is_prime = 1; //标记i是否为素数,假设原本i是素数
int j = 0;
for (j = 3; j * j <= i; j += 2)
{
if (i % j == 0)
{
is_prime = 0;
break;
}
}
if (is_prime)
{
printf("%d\n", i);
}
}
循环嵌套要格外小心,比如这里的is_prime不能在外层for循环外面定义:若某个i不为素数,则is_prime在内层循环中被置为0,若下一次的i为素数,则is_prime一直为0,会漏掉这个素数。内层循环与外层循环变量不同是为了避免冲突,例如如下会导致死循环:
C
int input_number = 0;
int count = 0;
for (input_number = 1; input_number <= 100; input_number++)
{
while (input_number)
{
if (input_number % 10 == 9)
{
count++;
}
input_number /= 10;
}
}
这是因为input_number在内层循环中第一次就被置为了0,永远到不了100!
总结
分支与循环结构是 C 语言程序逻辑的核心骨架,也是实现复杂算法的基础。顺序结构保证代码逐行执行,分支结构实现条件筛选,循环结构完成重复操作,三者相互配合,构成了所有程序的控制逻辑。
本文系统梳理了 if-else、switch 两大分支语句,while、for、do-while、goto 四种循环实现方式,并重点总结了 break、continue 的跳转规则与嵌套循环的易错坑点。同时结合实际案例,辨析了各类结构的执行顺序、适用场景与语法禁忌。
熟练掌握分支与循环的执行逻辑、匹配规则、跳转机制,规避缩进欺骗、变量污染、语句范围错乱等常见 bug,是后续学习函数、算法逻辑的重中之重。吃透基础控制结构,才能写出逻辑清晰、高效简洁、稳定性强的代码。