二、分支语句和循环语句

二、分支语句和循环语句

1.C语言语句

C语言的一个语句以一个分号;结尾

C语句可分为以下五类:

  1. 表达式语句
  2. 函数调用语句
  3. 控制语句
  4. 复合语句
  5. 空语句

本章介绍控制语句

控制语句用于控制程序的执行流程,以实现程序的各种结构方式(C语言支持三种结构:顺序结构、选 择结构、循环结构),它们由特定的语句定义符组成,C语言有九种控制语句。

可分成以下三类:

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

2.分支语句

2.1 if语句

当编写C程序时,经常需要根据不同的条件来选择性地执行代码。这就是if语句的作用。if语句是一种条件语句,根据条件的真假决定执行不同的代码块。

if语句的基本语法如下:

if (condition) {
    // 如果条件为真,执行这里的代码
}

if语句由关键字if、一个圆括号内的条件表达式condition和一个花括号内的代码块组成。条件表达式会被计算求值,如果结果为真(非零),则执行花括号内的代码块;如果结果为假(零),则跳过整个if语句,继续执行后续的代码。

以下是if语句的执行流程:

  1. 判断条件表达式的值。
  2. 如果条件为真,则执行if语句的代码块。
  3. 如果条件为假,则跳过if语句的代码块,继续执行后续的代码。

if-else语句的语法如下:

if (condition) {
    // 如果条件为真,执行这里的代码
} else {
    // 如果条件为假,执行这里的代码
}

以下是一个使用if-else语句的示例:

int num = -5;

if (num > 0) {
    printf("Number is positive.\n");
} else {
    printf("Number is not positive.\n");
}

在上面的例子中,根据num的值,如果num大于0,则输出"Number is positive.“;如果num不大于0,则输出"Number is not positive.”。

多分支else if的语法如下:

if (condition1) {
    // 如果条件1为真,执行这里的代码
} else if (condition2) {
    // 如果条件1为假且条件2为真,执行这里的代码
} else {
    // 如果所有条件都为假,执行这里的代码
}

在使用else if时,必须放在if语句之后,并在else语句之前。可以使用多个else if来添加更多的条件分支。

以下是一个使用else if的示例:

int score = 75;

if (score >= 90) {
    printf("优秀\n");
} else if (score >= 80) {
    printf("良好\n");
} else if (score >= 70) {
    printf("中等\n");
} else if (score >= 60) {
    printf("及格\n");
} else {
    printf("不及格\n");
}

在上面的例子中,根据变量score的值,根据不同的分数范围输出不同的等级。根据条件的先后顺序,只会执行第一个满足条件的代码块。如果score大于等于90,则输出"优秀";如果不满足第一个条件但满足第二个条件(80 <= score < 90),则输出"良好";

在C语言表达式中,0表示假,非0表示真

2.1.1 悬空else

当你写了这个代码:

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匹配,而是和第二个匹配,所以a==1 为假,程序直接return 0;

在C语言中,else与最近的未匹配的if语句进行匹配

改正:

//适当的使用{}可以使代码的逻辑更加清楚。
//代码风格很重要
#include 
int main() {
    int a = 0;
    int b = 2;
    if (a == 1) {
        if (b == 2) {
            printf("hehe\n");
        }
    } else {   //else匹配左边的右括号的if
        printf("haha\n");
    }
    return 0;
}

2.1.2 if书写形式的对比

//代码1
if (condition) {
    return x;
}
return y;

//代码2
if (condition) 
{
    return x;
} 
else 
{
    return y;
}

//代码3
int num = 1;
if (num == 5) 
{
    printf("hehe\n");
}

//代码4
int num = 1;
if (5 == num) 
{
    printf("hehe\n");
}

2.2 switch语句

switch是一种条件语句,用于根据表达式的值选择不同的执行路径。它提供了一种比使用多个if语句更简洁和可读性更好的方式来处理多个可能的分支。

switch语句的基本结构如下:

switch (expression) {
    case constant1:
        // 执行代码块1
        break;
    case constant2:
        // 执行代码块2
        break;
    ...
    case constantN:
        // 执行代码块N
        break;
    default:
        // 当expression与上述常量都不匹配时执行的代码块
}

expression是一个表达式,它的结果会与每个case语句后面的常量进行比较。如果expression的值与某个case后面的常量匹配,那么与该case语句关联的代码块将被执行。break语句用于在执行完一个分支后跳出switch语句,防止继续执行下一个分支。

以下是对switch语句的一些重要注意事项:

  1. expression的结果必须是整数类型(如intcharenum),不能是浮点数或字符串。
  2. case后面的常量必须是常量表达式,即在编译时就能确定的值,不能是变量。
  3. 每个case分支中的代码块可以包含任意数量的语句,如果没有break语句,将会继续执行下一个分支,这称为"case穿透"。
  4. default分支是可选的,用于处理expression与所有case都不匹配的情况。如果没有default分支,那么当没有匹配的case时,switch语句将不执行任何操作。
  5. switch语句可以嵌套在其他switch语句中,但要注意避免过度嵌套导致代码难以理解。

下面是一个简单的switch语句的示例:

int day = 2;
switch (day) {
    case 1:
        printf("Monday\n");
        break;
    case 2:
        printf("Tuesday\n");
        break;
    case 3:
        printf("Wednesday\n");
        break;
    default:
        printf("Invalid day\n");
}

在这个示例中,根据变量day的值,程序会打印出相应的输出,即"Tuesday"。如果day的值是1、3或其他任何值,将会打印不同的输出。如果day的值不匹配任何case,将执行default分支,并打印"Invalid day"。

通过使用switch语句,可以根据表达式的值在多个选择之间进行快速切换,并执行相应的代码块。

2.2.1 switch嵌套使用

void test{
    int n = 1;
    int m = 2;
    switch (n) {
        case 1:
            m++;
        case 2:
            n++;
        case 3:
            switch (n) {//switch允许嵌套使用
                case 1:
                    n++;
                case 2:
                    m++;
                    n++;
                    break;
            }
        case 4:
            m++;
            break;
        default:
            break;
    }
    printf("m = %d, n = %d\n", m, n);
}
//输出结果:m = 5, n = 3
  • case语句可以被连续匹配,从而实现"case穿透"效果,即匹配到某个case后,会继续执行后续的case语句,直到遇到break语句或switch语句结束。
  • switch语句可以嵌套使用,允许在一个case语句中再次使用switch语句。
  • default分支是可选的,用于处理所有未匹配到的情况。
  • 注意在使用switch语句时,要注意控制流的流向,确保代码逻辑正确。

3.循环语句

3.1 while循环

while循环是一种基于条件的迭代结构,用于重复执行一段代码块,直到给定的条件不再满足为止。它的基本语法如下:

while (condition) {
    // 循环体代码
    // 在每次迭代时执行的代码
}

condition是一个表达式,通常是与布尔值相关的条件。只要condition为真(非零),循环体中的代码就会被执行。在每次迭代中,首先会对condition进行判断,如果判断结果为真,则执行循环体中的代码。然后再次检查condition,以决定是否继续执行下一次迭代。只要condition保持为真,循环将一直执行。

while循环的执行过程如下:

  1. 检查condition的值。
  2. 如果condition为假(0),则退出循环,不再执行循环体中的代码。
  3. 如果condition为真(非零),则执行循环体中的代码。
  4. 返回第1步,继续检查condition的值,并根据判断结果决定是否继续执行循环。

下面是一个简单的示例,展示了while循环的使用:

int count = 0;
while (count < 5) {
    printf("Count: %d\n", count);
    count++;
}

在这个示例中,初始值为0的count变量被定义。然后进入while循环,检查count < 5的条件。由于初始值为0,满足条件,因此执行循环体中的代码。循环体中打印出当前的count值,然后count递增。接着回到while循环的开头,再次检查条件,重复上述步骤,直到count的值不再小于5为止。

3.1.1 while循环中的break和continue

while循环中,您可以使用breakcontinue语句来控制循环的行为。

  1. break语句:当在循环中遇到break语句时,程序会立即退出循环,继续执行循环之后的代码。它用于提前终止循环,不再执行剩余的迭代。

下面是一个使用break语句的示例:

int i = 0;
while (i < 5) {
    if (i == 3) {
        break;
    }
    printf("%d ", i);
    i++;
}

在这个示例中,当i的值等于3时,遇到了break语句。此时,循环被终止,不再执行剩余的迭代。因此,输出结果为:

0 1 2

​ 2.continue语句:当在循环中遇到continue语句时,程序会立即跳过当前迭代的剩余代码,直接进入下一次迭代。它用于跳过某些特定的迭代,但不会终止循环。

下面是一个使用continue语句的示例:

下面是一个使用continue语句的示例:

int i = 0;
while (i < 5) {
    i++;
    if (i == 3) {
        continue;
    }
    printf("%d ", i);
}

在这个示例中,当i的值等于3时,遇到了continue语句。此时,当前迭代中printf语句之后的代码被跳过,直接进入下一次迭代。因此,输出结果为:

1 2 4 5

注意:在使用breakcontinue语句时,要小心避免无限循环或逻辑错误。确保在适当的条件下使用这些语句,以达到预期的控制流程。

观察几个代码:

#include 
int main() {
    int ch = 0;
    while ((ch = getchar()) != EOF)
        putchar(ch);
    return 0;
}
//这里的代码适当的修改是可以用来清理缓冲区的.

#include 
int main() {
    char ch = '\0';
    while ((ch = getchar()) != EOF) {
        if (ch < '0' || ch > '9')
            continue;
        putchar(ch);
    }
    return 0;
}
//这个代码的作用是:只打印数字字符,跳过其他字符的

3.2 do while循环

do...while循环是一种后测试循环结构,它会先执行循环体中的代码,然后再检查循环条件。只要循环条件满足,就会继续执行循环体,直到循环条件不再满足为止。do...while循环至少会执行一次循环体,即使循环条件一开始就不满足。

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

do {
    // 循环体代码
    // 在每次迭代时执行的代码
} while (condition);

首先,do关键字后面的循环体中的代码会被执行一次。然后,执行完一次循环体后,程序会检查循环条件 condition。如果循环条件为真(非零),则继续执行下一次迭代,再次执行循环体中的代码。如果循环条件为假(0),则退出循环,继续执行循环之后的代码。

下面是一个简单的示例,展示了do...while循环的使用:

int count = 0;
do {
    printf("Count: %d\n", count);
    count++;
} while (count < 5);

在这个示例中,首先执行一次循环体,打印出初始的count值。然后检查循环条件 count < 5,如果满足,则继续执行下一次迭代。在每次迭代中,打印出当前的count值,然后count递增。循环继续进行,直到 count 的值不再小于5为止。

3.2.1 do while循环中的break和continue

do...while循环中,breakcontinue语句的用法和作用与其他循环结构(如forwhile)中的用法相同。它们用于在循环体内控制循环的执行流程。

  1. break语句:当在循环中遇到break语句时,程序会立即退出当前的循环,不再执行剩余的迭代,并继续执行循环之后的代码。

下面是一个使用break语句的示例:

int i = 0;
do {
    if (i == 3) {
        break;
    }
    printf("%d ", i);
    i++;
} while (i < 5);

在这个示例中,当 i 的值等于3时,遇到了break语句。此时,循环被终止,不再执行剩余的迭代。因此,输出结果为:

0 1 2
  1. continue语句:当在循环中遇到continue语句时,程序会立即跳过当前迭代的剩余代码,直接进入下一次迭代。

下面是一个使用continue语句的示例:

int i = 0;
do {
    i++;
    if (i == 3) {
        continue;
    }
    printf("%d ", i);
} while (i < 5);

在这个示例中,当 i 的值等于3时,遇到了continue语句。此时,当前迭代中 printf 语句之后的代码被跳过,直接进入下一次迭代。因此,输出结果为:

1 2 4 5

3.3 for循环

for循环是一种常用的循环结构,用于重复执行一段代码,它由三个部分组成:初始化表达式、循环条件和循环迭代语句。

for循环的基本语法如下:

for (初始化表达式; 循环条件; 循环迭代语句) {
    // 循环体代码
    // 在每次迭代时执行的代码
}
  1. 执行初始化表达式,一般用于初始化循环变量。
  2. 检查循环条件,如果循环条件为真(非零),则执行循环体内的代码。如果循环条件为假(0),则退出循环,继续执行循环之后的代码。
  3. 执行循环体内的代码。
  4. 执行循环迭代语句,一般用于更新循环变量的值。
  5. 回到第二步,重新检查循环条件,然后根据循环条件的结果决定是否继续执行循环。

下面是一个简单的示例,展示了for循环的使用

for (int i = 0; i < 5; i++) {
    printf("%d ", i);
}

在这个示例中,初始化表达式 int i = 0 初始化了循环变量 i 的初始值为0。循环条件 i < 5 检查变量 i 是否小于5,如果满足,则执行循环体内的代码。在每次迭代中,打印出当前的 i 值。循环迭代语句 i++ 用于递增循环变量 i 的值。循环将继续进行,直到循环条件不再满足。

这段代码将会输出以下内容:

0 1 2 3 4

3.3.1 for循环对比while循环

int i = 0;
//实现相同的功能,使用while
i = 1;         //初始化部分
while (i <= 10)//判断部分
{
    printf("hehe\n");
    i = i + 1;//调整部分
}

//实现相同的功能,使用for
for (i = 1; i <= 10; i++) {
    printf("hehe\n");
}

可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹;for循环使用的频率也最高。

3.3.2 for循环中的break和continue

for循环中,breakcontinue语句的用法和作用与其他循环结构(如whiledo...while)中的用法相同。

//代码1
int main() {
    int i = 0;
    for (i = 1; i <= 10; i++) {
        if (i == 5)
            break;
        printf("%d ", i);
    }
    return 0;
}
//输出结果:1 2 3 4

//代码2
int main() {
    int i = 0;
    for (i = 1; i <= 10; i++) {
        if (i == 5)
            continue;
        printf("%d ", i);
    }
    return 0;
}
//输出结果:1 2 3 4 6 7 8 9 10

3.3.3 for循环的循环控制变量

建议:

  1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
  2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。
int i = 0;
//前闭后开的写法
for (i = 0; i < 10; i++) {}
//两边都是闭区间
for (i = 0; i <= 9; i++) {}

3.3.4 for循环的变种

for (;;) {
    printf("hehe\n");
}

for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问题。

如果省略掉初始化部分,这里打印多少个hehe?

int i = 0;
int j = 0;
for (i = 0; i < 10; i++) {
    for (j = 0; j < 10; j++) {
        printf("hehe\n");
    }
}
//100次hehe

如果省略掉初始化部分,这里打印多少个hehe?

int i = 0;
int j = 0;
for (; i < 10; i++) {
    for (; j < 10; j++) {
        printf("hehe\n");
    }
}
//10次heh

使用多余一个变量控制循环

int x, y;
for (x = 0, y = 0; x < 2 && y < 5; ++x, y++) {
    printf("hehe\n");
}
//2次hehe

练习:

请问循环要循环多少次?

int main() {
    int i = 0;
    int k = 0;
    for (i = 0, k = 0; k = 0; i++, k++)
        k++;
    return 0;
}

该程序的循环次数为0次。

在for循环的条件部分,使用了赋值操作符(=)而不是相等操作符(==),导致条件始终为真(非零),所以循环将无限执行。由于在循环体内对k进行了自增操作(k++),但在循环条件中重新对k赋值为0,导致每次循环后k的值都会被重置为0。因此,循环永远无法结束,程序将陷入无限循环状态,永远不会返回0。

4.goto语句

在C语言中,goto语句用于无条件地转移到程序中的标记(label)。它允许跳转到程序中的任意位置,包括在当前函数或块内。

下面是一个示例程序,展示了goto语句的用法:

#include 

int main() {
    int i = 0;

    start:
    printf("i = %d\n", i);
    i++;

    if (i < 5) {
        goto start;
    }

    return 0;
}

需要注意的是,滥用goto语句可能会导致代码难以理解和维护,因此应谨慎使用。通常情况下,可以使用循环和条件语句(如forwhileif等)来替代goto语句,使代码更具结构性和可读性。

你可能感兴趣的:(#,C语言初阶,c语言)