在本文中,我们学习分支语句,循环语句和 goto 语句
一:什么是语句?
在 C 语言中,语句是一条完整的执行单元,它用于表达某种操作或执行特定的任务。 C 语言中的程序由一个个语句组成,每个语句都按照一定的顺序被执行,每个语句必须以分号结尾,分号表示语句的结束。编译器会按照语句的顺序逐一执行代码中的语句,以完成相应的操作和任务。
在 c 语言中,有九种控制语句,可分为以下三类:
- 条件判断语句( 也叫分支语句 ):if 语句、switch 语句;
- 循环执行语句:do while 语句、while 语句、for 语句;
- 转向语句:break 语句、goto 语句、continue 语句、return 语句。
二:分支语句
在人生中,我们会面临着多种选择,不同的选择又有不同的结果,这就产生了分支
以上便是一个简单的双分支示意图,在 c 语言中我们通过 if 语句和 switch 语句来实现分支结构
2.1 if 语句
那 if 语句的语法结构是怎样的呢?
- 单分支:
if(表达式)
{
语句;
}
- 双分支:
if(表达式)
{
语句1;
}
else //注意:else 后面不带表达式
{
语句2;
}
- 多分支:
if(表达式1)
{
语句1;
}
else if(表达式2)
{
语句2;
}
else //注意:else 后面不带表达式
{
语句3;
}
以下是这段代码的执行方式:
- 首先,会对表达式 1 进行求值判断。如果表达式 1 的结果为真,则执行语句 1,并跳过后续的 else if 和 else 部分。
- 如果表达式 1 的结果为假,则会继续对表达式 2 进行求值判断。如果表达式 2 的结果为真,则执行语句 2,并跳过后续的 else 部分。
- 如果即表达式 1 和表达式 2 的结果都为假 ,则执行语句 3。
条件语句的每个条件表达式都会按从上到下的顺序进行求值判断。一旦某个条件满足,则会执行相应的语句块,并跳过后续的条件和语句块。如果没有任何条件满足,则会执行最后的 else 语句块,或者整个条件语句结束。
2.2.1 if - if - if 语句和 if - else if - else语句的区别
if - else if - else 和 if - if - if 不同, if - else if - else:只有一个分支会被执行。一旦条件满足,会执行相应代码块,并跳过后续分支,而 if - if - if:多个分支可以同时被执行。每个 if 语句都会独立地进行条件判断和执行。
2. 2.2 悬空 else 问题
接下来看一段代码:
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if(a == 1)
if(b == 2)
printf("hehe\n");
else
printf("haha\n");
return 0;
}
这是一段有坑的代码:一般人可能会认为,因为 a == 1 这个条件不满足,所以会执行 else 这个语句,打印 haha,其实不然,下面是代码的运行的结果:
这是为什么呢?原因是因为 else 是和离它最近的 if 进行匹配的,所以这段代码的结果是打印 hehe 那么我们该怎么避免这种错误呢?我们可以适当的使用{ }可以使代码的逻辑更加清楚,以下是改进的代码:
#include <stdio.h>
int main()
{
int a = 0;
int b = 2;
if(a == 1)
{
if(b == 2)
{
printf("hehe\n");
}
}
else
{
printf("haha\n");
}
return 0;
}
这样 else 就是和第一个 if 进行匹配了,注意, else 和 if 一定要同等级,虽然第二个 if 在视觉上更近一些,但是第二个 if 和 else 的等级不一样。请注意辨别
2.2.3 if 条件内的判断技巧
请大家判断以下两个代码哪个更好
//代码1
int num = 1;
if(num == 5)
{
printf("hehe\n");
}
//代码2
int num = 1;
if(5 == num)
{
printf("hehe\n");
}
这两段代码作用相同,判断变量 num 是否等于 5,并打印出 “hehe”。在这种情况下,两段代码效果相同,但是其实代码 4 中的写法更好,将常量值放在等式的左侧。这种写法称为"常量左移"或"常量前置",是一种常见的编程习惯。
使用常量左移的好处是可以避免在条件表达式时,错误地将 = 写成 ==,这种错误是比较常见的。将常量放在左侧时,如果不小心写成 if ( num = 5 ),编译会出现问题,因为赋值操作返回的是赋值的值,所以 num = 5 的结果为真,执行 if 中的代码块,这样就和我们的初衷就背离了
2.2 switch 语句
2.2.1 switch 的语法
在 C 语言中,switch 语句用于根据某个表达式的值选择执行不同的代码块。它的语法结构如下:
switch (expression)
{
case constant1:
// 代码块1
break;
case constant2:
//代码块2
break;
default:
// 代码块3
}
其中 expression 是需要进行比较的表达式,可以是整数或字符类型。每个 case 后面的 constant 是一个常量,它会与 expression 进行比较。如果 expression 的值与某个 case 后面的 constant 相等,程序将执行对应的代码块。如果没有匹配到任何 case,那么将执行 default 后面的代码块。
break 语句用于跳出 switch 语句。当程序执行完某个 case 的代码块后,如果没有 break 语句,程序将会继续执行下一个 case 的代码块,直到遇到 break 或者 switch 语句结束。这种不加 break 的情况被称为 “case 穿透”,举个例子:
switch (value)
{
case 1:
// 代码块 1
case 2:
// 代码块 2
case 3:
// 代码块 3
default:
// 代码块 4
}
如果 value 的值为 1,那么将会执行 代码块 1、代码块 2 和 代码块 3 和 代码块 4。因为在第一个 case 中没有使用 break,所以程序会继续向下执行。
2.2.2 switch 处理多分支和 if 语句处理多分支的区别
在 c 语言中,switch 语句也是一种分支语句。常常用于多分支的情况,例如我们需要写这样一个程序:
- 输入1,输出星期一
- 输入2,输出星期二
- 输入3,输出星期三
- 输入4,输出星期四
- 输入5,输出星期五
- 输入6,输出星期六
- 输入7,输出星期日
如果用 if - else if - else 语句写的话应该是这样:
#include <stdio.h>
int main() {
int day;
printf("请输入一个数字: ");
scanf("%d", &day);
if (day == 1)
{
printf("星期一\n");
}
else if (day == 2)
{
printf("星期二\n");
}
else if (day == 3)
{
printf("星期三\n");
}
else if (day == 4)
{
printf("星期四\n");
}
else if (day == 5)
{
printf("星期五\n");
}
else if (day == 6)
{
printf("星期六\n");
}
else if (day == 7)
{
printf("星期日\n");
}
else
{
printf("输入无效,请输入一个介于1-7之间的数字。\n");
}
return 0;
}
这样写显得有点臃肿, c 语言为我们提供了一个专门处理多分支的语句 switch,用 switch 语句我们可以这样写:
#include <stdio.h>
int main() {
int day;
printf("请输入一个数字代表星期几(1-7):");
scanf("%d", &day);
switch(day)
{
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
case 6:
printf("星期六\n");
break;
case 7:
printf("星期日\n");
break;
default:
printf("无效的输入\n");
}
return 0;
}
使用 switch 语句处理多分支和使用 if 语句处理多分支都可以实现相同的功能,但它们在某些方面有不同的优势。
注意:switch 语句只能处理整数类型或字符类型。它对于范围的处理能力有限,而 if 语句可以使用逻辑运算符来处理更复杂的条件。
三:循环语句
在生活中,有些事情需要我们重复不断的去完成,比如说睡觉,洗澡,吃饭,学习,在 c 语言中我们可以通过 while 循环 for 循环和 do while 循环来重复执行某一段代码,下面我们来一 一介绍
3.1 while 循环
在 C 语言中,while 循环是一种基本的循环结构,它允许我们根据给定的条件重复执行一段代码。while 循环的基本语法如下:
while (condition) {
// 执行的代码块
}
当 condition 条件为真时,循环中的代码块会被执行。执行完一次代码块后,会再次判断condition 条件是否为真,如果为真,则再次执行代码块,以此类推,直到 condition 条件为假,才会退出循环,使用 while 循环的时候注意以下几点:
- 循环条件:要确保循环条件最终能够变为假,否则会造成无限循环。
- 循环体:循环体中的代码块会被重复执行,因此要确保循环体中的代码能够正常运行,要有循环变量的更新,以免陷入死循环或产生错误结果。
下面是一个使用 while 循环的简单示例:
#include <stdio.h>
int main() {
int count = 0;
while (count < 5)
{
printf("Count: %d\n", count);
count++; // 更新循环变量
}
return 0;
}
在上述示例中,通过设置 count 变量,循环执行 5 次。我们在代码块中每循环一次让 count 自增 1,这样能够让条件最终变假,不会陷入死循环
3.2 for 循环
在 C 语言中,for 循环是一种用于重复执行代码块的循环结构。它允许我们指定循环变量的初始值、循环条件和每次循环后更新循环变量的操作。for 循环的语法如下:
for (初始化表达式; 循环条件; 更新表达式) {
// 循环体
}
for 循环的作用是重复执行循环体,并允许我们对循环变量进行精确控制。我们可以使用它来实现一系列需要重复执行的任务,下面是一个简单的例子,展示了如何使用 for 循环计算 1 到 10 的和:
#include <stdio.h>
int main()
{
int sum = 0;
for (int i = 1; i <= 10; i++)
{
sum += i;
}
printf("Sum: %d\n", sum);
return 0;
}
在这个例子中,我们使用了三个重要的组成部分来控制循环的行为:
- 初始化表达式:我们将循环变量 i 设置为1,指定了循环的起始值。
- 循环条件:我们使用 i <= 10 作为循环条件,这意味着当 i 小于等于10时循环继续执行,否则循环结束。
- 更新表达式:在每次循环结束后,我们使用 i++ 将循环变量 i 增加1,以便进行下一次迭代。
循环体部分中,我们将当前的 i 值累加到 sum 变量中,因此在每次循环迭代中,sum 的值会被更新,最终,我们输出了 sum 的值,结果为 1 到 10 的和,即 55。
使用 for 循环时需要注意:
- 每个组成部分之间使用分号进行分隔。
- 初始化表达式和更新表达式可以包含多个语句,以逗号分隔。
for (x = 0,y = 0; x < 2 && y< 5;++x,++y)
{
//代码块
}
接下来这段代码是最简单的死循环,因为这个 for 循环没有判断条件,所以判断结果默认为真
for( ;;)
3.3 break 和 continue
在 C 语言中,break 和 continue 是控制循环的关键字。continue 和 break 都可以用在 for、while、do-while 循环以及 switch 语句中。它们分别用于终止循环和跳过当前迭代,让程序按照特定的需求执行。
- break 语句:当 break 语句出现在循环体内部时,会立即终止该循环,并跳出循环外的下一条语句。
#include <stdio.h>
int main()
{
int i;
for (i = 1; i <= 10; i++)
{
if (i == 5)
{
break;
}
printf("%d ", i);
}
printf("Loop ended!\n");
return 0;
}
输出:
1 2 3 4 Loop ended!
在上面的示例中,当 i 等于5时,break 语句会立即终止循环,因此只输出了 1、2、3 和 4。
- continue 语句: continue 语句用于提前结束当前迭代,但并不会终止整个循环。
#include <stdio.h>
int main()
{
int i;
for (i = 1; i <= 10; i++)
{
if (i == 5)
{
continue;
}
printf("%d ", i);
}
printf("Loop ended!\n");
return 0;
}
输出:
1 2 3 4 6 7 8 9 10 Loop ended!
在上面的示例中,当 i 等于 5 时,continue 语句会跳过当前迭代,而不执行后面的代码。因此,输出中没有数字 5。
3.4 for 循环和 while 循环的对比
下面我们来看一段代码:
#include <stdio.h>
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
if(i == 5)
break;
printf("%d ",i);
}
return 0;
}
//代码2
#include <stdio.h>
int main() {
int count = 0;
while (count < 5)
{
printf("Count: %d\n", count);
count++; // 更新循环变量
}
return 0;
}
在 for 循环中,循环变量的初始化、条件判断和更新都在一个地方进行,使得代码更加集中、简洁。而 while 循环的三个部分可能比较偏远,这样查找和修改循环变量就不够集中和方便
3.5 do while循环
当你想要先执行一次循环体,然后再根据条件判断是否继续执行循环时,可以使用 C 语言中的 do-while 循环,do-while 循环的基本语法如下:
do
{
// 循环体
} while (条件);
do - while 循环的执行过程是这样的:首先执行循环体,然后在循环体执行完之后再进行条件判断。如果条件满足,则继续执行循环体,否则结束循环,do - while 循环和 for 循环 while 循环没什么不同,都是重复做一件事情,只是 do - while 循环会先执行一次代码块中的代码,仅此而已,因为使用场景有限,所以不是很经常使用
四:goto 语句
在 C 语言中,goto 语句可以用来无条件地转移到程序中的某个标签处执行代码。它的基本语法如下:
goto label;
// ...
label://冒号
// 代码块
其中,label 是由用户自定义的标签,用来标识需要跳转到的位置。在执行到 goto 语句时,程序将会跳转到 label 所在的位置,继续执行标签处的代码块。
#include <stdio.h>
int main() {
int i = 1;
loop:
printf("%d ", i);
i++;
if (i <= 10) {
goto loop; // 跳转到loop标签处继续循环
}
return 0;
}
在上述代码中,我们使用了一个标签 loop 来表示循环的起始点。通过使用 goto 语句,我们在每次打印完数字后跳转到 loop 标签处,从而实现了循环打印 1-10 的效果。
注意:尽管 goto 语句在某些特定情况下可能很方便,但它容易导致代码的可读性和维护性降低。因此,在实际开发中应尽量避免过多地使用 goto 语句。