BIT-2 分支和循环语句(1万字)

简介: BIT-2 分支和循环语句(1万字)

在本文中,我们学习分支语句,循环语句和goto语句

一:什么是语句?

在C语言中,语句是一条完整的执行单元,它用于表达某种操作或执行特定的任务。C语言中的程序由一个个语句组成,每个语句都按照一定的顺序被执行。

C语言中常见的语句有以下几种:

  1. 表达式语句(Expression statement):最简单的语句形式,由一个表达式和以分号结尾组成。例如:x = 10;
  2. 声明语句:用于在代码中声明一个或多个变量。例如:int x = 10;
  3. 控制流语句:用于控制程序的执行流程,包括条件语句、循环语句和跳转语句等。例如:if (x > 5) { ... }while (x < 10) { ... }break;
  4. 复合语句:也称为代码块,是由一对花括号括起来的语句序列。复合语句可以包含多个语句,并可以嵌套在其他语句中。例如:
{
  int x = 10;
  printf("x = %d\n", x);
}
  1. 空语句(Null statement):由一个分号组成,表示什么都不做。通常用于语法需要语句但实际不需要执行任何操作的情况下。例如:;

注意,每个语句必须以分号结尾,分号表示语句的结束。编译器会按照语句的顺序逐一执行代码中的语句,以完成相应的操作和任务。

在c语言中,又九种控制语句,可分为以下三类:

  1. 条件判断语句也叫分支语句:if语句、switch语句;
  2. 循环执行语句:do while语句、while语句、for语句;
  3. 转向语句:break语句、goto语句、continue语句、return语句。

二:分支语句

在人生中,我们会面临着多种选择,不同的选择又有不同的结果,这就产生了分支

以上便是一个简单的双分支示意图,在c语言中我们通过if语句和switch语句来实现分支结构

2.1if语句

那if语句的语法结构是怎样的呢?

  • 单分支:
if(表达式)
{
  语句;
}

双分支:

if(表达式)
{
  语句1;
}
else
{
  语句2;
}

多分支:

if(表达式1)
{
  语句1;
}
else if(表达式2)
{
  语句2;
}
else
{
  语句3;
}

注意:else后面不带表达式

以下是这段代码的执行方式:

  1. 首先,会对表达式1进行求值判断。如果表达式1的结果为真(非零),则执行语句1,并跳过后续的 else if 和 else 部分。如果表达式1的结果为假(0),则继续执行下一步。
  2. 如果表达式1的结果为假(0),则会继续对表达式2进行求值判断。如果表达式2的结果为真(非零),则执行语句2,并跳过后续的 else 部分。如果表达式2的结果为假(0),则继续执行下一步。
  3. 如果前面的条件都不满足(即表达式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 (condition1) 
{
    // 执行代码块1
} 
else if (condition2) 
{
    // 执行代码块2
} 
else if (condition3)
{
    // 执行代码块3
}
 else
{
    // 执行默认代码块
}
  • if-if-if语句:
    示例代码如下:
if (condition1) 
{
    // 执行代码块1
}
if (condition2) 
{
    // 执行代码块2
}
if (condition3) 
{
    // 执行代码块3
}
  1. 执行逻辑不同:
  • if-else if-else:当满足条件1时,执行代码块1,然后跳过后续的 else if 和 else 分支。如果条件1不满足,则继续检查下一个 else if 条件,依此类推如果没有任何条件满足,最后执行 else 分支(如果有)。
  • if-if-if:每个 if 语句都会独立地进行条件判断和执行。不论前面的条件是否满足,都会检查并执行每个 if 语句。
  1. 执行次数不同:
  • if-else if-else:只有一个分支会被执行。一旦条件满足,会执行相应代码块,并跳过后续分支。
  • if-if-if:多个分支可以同时被执行。每个 if 语句都会独立地进行条件判断和执行。

综上所述,if-else if-else 和 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,其实不然,下面是代码的运行的结果:

可见打印的结果是hehe而不是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中的代码块,这样就和我们的初衷就背离了

所以,代码4的写法更好,可以提高代码的安全性和可读性。

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 后面的代码块(如果有deault)。

在 switch 语句中,break 语句用于跳出 switch 语句。当程序执行完某个 case 的代码块后,如果没有 break 语句,程序将会继续执行下一个 case 的代码块,直到遇到 break 或者 switch 语句结束。这种不加 break 的情况被称为 “case 穿透”。

如果在某个 case 的代码块中不加 break,会导致程序继续执行下一个 case 的代码块,而不会进行比较。这可能是有意为之,也可能是错误。比如:

switch (value) 
{
    case 1:
        // 代码块 1
    case 2:
        // 代码块 2
        break;
    case 3:
        // 代码块 3
        break;
    default:
        // 代码块  4
}

如果 value 的值为 1,那么将会执行 代码块 1、代码块 2 和 代码块3 和代码块4。因为在第一个 case 中没有使用 break,所以程序会继续向下执行。加入 break 语句可以控制代码的执行流程,避免出现不可预期的结果。

总结一下,switch 语句是根据表达式的值选择执行不同的代码块。通过在各个 case 中使用 break 语句可以控制代码的流程。如果没有使用 break,会导致 case 穿透,程序会继续执行下一个 case 的代码块。

2.2.2switch处理多分支和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 语句的一些优点:

  1. 代码可读性:当存在多个互斥的选项时,使用 switch 语句可以使代码更加简洁和可读。每个 case 独立地处理一个特定的情况,使代码结构清晰。
  2. 性能优化:在某些情况下,使用 switch 语句可以提高代码的执行效率。因为 switch 语句的实现方式使用了跳转表(jump table),可以直接根据表达式的值跳转到对应的分支,而不需要逐个检查每个条件。
  3. 代码可维护性:当需要添加或修改分支条件时,使用 switch 语句可以更方便地进行扩展和维护。只需要添加或修改相应的 case 分支即可,而不需要修改大量的 if 条件。

需要注意的是,switch 语句只能处理离散的值,比如整数类型或字符类型。它对于范围的处理能力有限,而 if 语句可以使用逻辑运算符来处理更复杂的条件。

总之,选择使用 switch 语句还是 if 语句取决于具体的业务需求,以及在代码的可读性、性能和可维护性之间做出权衡。

三:循环语句

在生活中,有些事情需要我们重复不断的去完成,比如说睡觉,洗澡,吃饭,学习,而在c语言中我们可以通过while循环 for循环和do while循环来重复执行某一段代码。

下面我们来一一介绍

3.1 while循环

在C语言中,while循环是一种基本的循环结构,它允许我们根据给定的条件重复执行一段代码。while循环的基本语法如下:

while (condition) {
    // 执行的代码块
}

condition条件为真(非零)时,循环中的代码块会被执行。执行完一次代码块后,会再次判断condition条件是否为真,如果为真,则再次执行代码块,以此类推,直到condition条件为假(零),才会退出循环。

使用while循环的时候注意以下几点:

  1. 循环条件:要确保循环条件最终能够变为假,否则会造成无限循环。
  2. 循环体:循环体中的代码块会被重复执行,因此要确保循环体中的代码能够正常运行,要有循环变量的更新:要确保循环中的变量会根据需要进行更新,以免陷入死循环或产生错误结果。

下面是一个使用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;
}

在这个例子中,我们使用了三个重要的组成部分来控制循环的行为:

  1. 初始化表达式:我们将循环变量 i 设置为1,指定了循环的起始值。
  2. 循环条件:我们使用 i <= 10 作为循环条件,这意味着当 i 小于等于10时循环继续执行,否则循环结束。
  3. 更新表达式:在每次循环结束后,我们使用 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 语句中。它们分别用于终止循环和跳过当前迭代,让程序按照特定的需求执行。

  1. break语句:
  • 当break语句出现在循环体内部时,会立即终止该循环,并跳出循环外的下一条语句。
  • break语句通常与条件语句(如if)结合使用,用于提前结束循环。
  • 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。

  1. continue语句:
  • 当continue语句出现在循环体内部时,会跳过当前迭代中continue之后的代码,并进行下一次迭代。
  • 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。

总结:

  • break语句用于终止整个循环,并跳出循环外的下一条语句。
  • continue语句用于跳过当前迭代中continue之后的代码,进行下一次迭代。
  • break和continue语句通常与条件语句结合使用,以根据特定条件来控制循环的终止和跳过。

3.4for循环和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.5do while循环

当你想要先执行一次循环体,然后再根据条件判断是否继续执行循环时,可以使用C语言中的do-while循环。

do-while循环的基本语法如下:

do 
{
    // 循环体
} while (条件);

do-while循环的执行过程是这样的:首先执行循环体,然后在循环体执行完之后再进行条件判断。如果条件满足,则继续执行循环体,否则结束循环。因此,do-while循环保证至少执行一次循环体。

do-while 循环和 for 循环 while 循环没什么不同,都是重复做一件事情,只是 do-while ,循环会先执行一次代码块中的代码,仅此而已,因为使用场景有限,所以不是很经常使用

四:goto 语句

在C语言中,goto语句可以用来无条件地转移到程序中的某个标签(label)处执行代码。它的基本语法如下:

goto label;
// ...
label://冒号
    // 代码块

其中,label是由用户自定义的标签,用来标识需要跳转到的位置。在执行到goto语句时,程序将会跳转到label所在的位置,继续执行标签处的代码块。

使用goto语句的时候需要注意以下几点:

  1. 合理使用goto语句:由于goto语句具有无条件跳转的特性,过度使用它可能导致程序结构混乱,难以理解和维护。因此,应谨慎使用goto语句,避免滥用。
  2. 避免跳过变量初始化:当使用goto语句跳转到某个标签时,应确保经过的代码路径中的变量已经被正确初始化。否则,可能会导致未定义的行为。
  3. 避免跨越变量作用域:在使用goto语句时,应注意不要跨越变量的作用域。否则,可能会导致变量不可见或者访问非法内存的问题。
  4. 避免嵌套过多的goto语句:嵌套过多的goto语句会使代码变得复杂和难以理解。在逻辑结构清晰的情况下,尽量避免使用嵌套的goto语句。

以下是goto语句的使用示例

使用goto语句来实现循环打印1-10的代码:

#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语句在某些特定情况下可能很方便,但它容易导致代码的可读性和维护性降低。因此,在实际开发中应尽量避免过多地使用goto语句,尽量使用其他更结构化的语句(如for循环、while循环)来实现循环逻辑。

目录
相关文章
|
6月前
|
C语言
爱上C语言:分支与循环(分支篇)多个if与if — else if区别
爱上C语言:分支与循环(分支篇)多个if与if — else if区别
|
6月前
|
Go C语言
爱上C语言:分支与循环(循环篇)
爱上C语言:分支与循环(循环篇)
|
5月前
分支、循环语句的简介
分支、循环语句的简介
|
6月前
|
机器学习/深度学习 C语言
【C语言】分支循环第二章 1
【C语言】分支循环第二章
|
监控 C++
分支与循环(2)(下)
分支与循环(2)(下)
|
编译器 C语言
|
C语言
分支和循环习题以及知识点
分支和循环习题以及知识点
|
C++
C++ Primer Plus 第六章答案 分支语句和逻辑运算符
只有聪明人才能看见的摘要~( ̄▽ ̄~)~
75 0
|
存储 编译器 C语言
【C初阶】第二篇——分支语句和循环语句(if-else+switch+while+for)(一)
【C初阶】第二篇——分支语句和循环语句(if-else+switch+while+for)
【C初阶】第二篇——分支语句和循环语句(if-else+switch+while+for)(一)
|
算法 C语言
【C初阶】第二篇——分支语句和循环语句(if-else+switch+while+for)(二)
【C初阶】第二篇——分支语句和循环语句(if-else+switch+while+for)
【C初阶】第二篇——分支语句和循环语句(if-else+switch+while+for)(二)