MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

C 语言控制结构深入解析

2021-11-074.2k 阅读

C 语言控制结构深入解析

顺序结构

在 C 语言中,顺序结构是程序执行的基础结构。它按照代码书写的先后顺序依次执行每一条语句,就像我们日常做事按部就班一样。例如:

#include <stdio.h>

int main() {
    int a = 5;
    int b = 3;
    int sum;

    sum = a + b;
    printf("两数之和为: %d\n", sum);

    return 0;
}

在这个简单的程序中,首先定义了三个整型变量 absum,接着给 ab 赋值,然后计算它们的和并存储在 sum 中,最后通过 printf 函数输出结果。每一步都是顺序执行的,前一个操作完成后才会进行下一个操作。

顺序结构是程序最基本的执行流程,它构成了程序的骨架,其他更复杂的控制结构也是在顺序结构的基础上构建的。

选择结构

if 语句

if 语句是 C 语言中最基本的选择结构,它根据给定的条件来决定是否执行特定的代码块。其基本语法如下:

if (条件表达式) {
    // 当条件表达式为真(非 0)时执行的代码块
}

例如,判断一个数是否为正数:

#include <stdio.h>

int main() {
    int num = 10;

    if (num > 0) {
        printf("%d 是正数\n", num);
    }

    return 0;
}

在这个例子中,num > 0 就是条件表达式,如果这个表达式的值为真(即 num 确实大于 0),那么就会执行 printf 语句输出相应信息。

if - else 语句

if - else 语句在 if 语句的基础上增加了一个分支,当条件表达式为假(0)时,执行 else 后面的代码块。语法如下:

if (条件表达式) {
    // 当条件表达式为真(非 0)时执行的代码块
} else {
    // 当条件表达式为假(0)时执行的代码块
}

比如判断一个数的奇偶性:

#include <stdio.h>

int main() {
    int num = 7;

    if (num % 2 == 0) {
        printf("%d 是偶数\n", num);
    } else {
        printf("%d 是奇数\n", num);
    }

    return 0;
}

这里 num % 2 == 0 是条件表达式,若表达式为真,说明 num 是偶数,执行 if 后的代码块;若为假,则执行 else 后的代码块,判断 num 为奇数。

多重 if - else 语句

有时候我们需要根据多个条件进行多种不同的判断,这时候就可以使用多重 if - else 语句。语法形式如下:

if (条件表达式1) {
    // 当条件表达式1为真(非 0)时执行的代码块
} else if (条件表达式2) {
    // 当条件表达式1为假且条件表达式2为真时执行的代码块
} else if (条件表达式3) {
    // 当条件表达式1、2为假且条件表达式3为真时执行的代码块
}
...
else {
    // 当所有条件表达式都为假时执行的代码块
}

例如,根据学生的成绩进行评级:

#include <stdio.h>

int main() {
    int score = 85;

    if (score >= 90) {
        printf("成绩评级为 A\n");
    } else if (score >= 80) {
        printf("成绩评级为 B\n");
    } else if (score >= 70) {
        printf("成绩评级为 C\n");
    } else if (score >= 60) {
        printf("成绩评级为 D\n");
    } else {
        printf("成绩评级为 F\n");
    }

    return 0;
}

这里通过多重 if - else 语句,根据不同的成绩范围给出相应的评级。

嵌套 if - else 语句

ifelse 的代码块中,还可以再嵌套 if - else 语句,以实现更复杂的条件判断。语法如下:

if (条件表达式1) {
    if (条件表达式2) {
        // 当条件表达式1和条件表达式2都为真时执行的代码块
    } else {
        // 当条件表达式1为真且条件表达式2为假时执行的代码块
    }
} else {
    // 当条件表达式1为假时执行的代码块
}

例如,在判断一个年份是否为闰年时,闰年的判断规则是能被 4 整除但不能被 100 整除,或者能被 400 整除。可以这样写代码:

#include <stdio.h>

int main() {
    int year = 2020;

    if (year % 4 == 0) {
        if (year % 100 != 0 || year % 400 == 0) {
            printf("%d 是闰年\n", year);
        } else {
            printf("%d 不是闰年\n", year);
        }
    } else {
        printf("%d 不是闰年\n", year);
    }

    return 0;
}

这里首先判断年份是否能被 4 整除,如果能,则进一步判断是否满足不能被 100 整除或者能被 400 整除的条件,以此来确定是否为闰年。

循环结构

while 循环

while 循环用于在满足给定条件的情况下,重复执行一段代码。其基本语法为:

while (条件表达式) {
    // 当条件表达式为真(非 0)时重复执行的代码块
}

例如,计算 1 到 10 的累加和:

#include <stdio.h>

int main() {
    int i = 1;
    int sum = 0;

    while (i <= 10) {
        sum += i;
        i++;
    }

    printf("1 到 10 的累加和为: %d\n", sum);

    return 0;
}

在这个例子中,i <= 10 是条件表达式,只要这个条件为真,就会执行循环体中的代码,即 sum += ii++sum += i 用于累加当前的 i 值,i++ 用于使 i 的值递增,以便最终能使条件表达式 i <= 10 为假,从而结束循环。

do - while 循环

do - while 循环与 while 循环类似,但它先执行一次循环体,然后再判断条件表达式。语法如下:

do {
    // 先执行一次的代码块
} while (条件表达式);

同样计算 1 到 10 的累加和,用 do - while 循环可以这样写:

#include <stdio.h>

int main() {
    int i = 1;
    int sum = 0;

    do {
        sum += i;
        i++;
    } while (i <= 10);

    printf("1 到 10 的累加和为: %d\n", sum);

    return 0;
}

可以看到,与 while 循环不同,do - while 循环不管条件表达式一开始是否为真,都会先执行一次循环体。这在某些需要先执行一次操作,再根据结果判断是否继续循环的场景中非常有用。

for 循环

for 循环是 C 语言中最常用的循环结构之一,它把循环控制的初始化、条件判断和更新操作集中在一个地方,使代码更加简洁明了。其基本语法为:

for (初始化表达式; 条件表达式; 更新表达式) {
    // 当条件表达式为真(非 0)时重复执行的代码块
}

还是计算 1 到 10 的累加和,for 循环的写法如下:

#include <stdio.h>

int main() {
    int sum = 0;

    for (int i = 1; i <= 10; i++) {
        sum += i;
    }

    printf("1 到 10 的累加和为: %d\n", sum);

    return 0;
}

在这个 for 循环中,int i = 1 是初始化表达式,它只在循环开始时执行一次,用于初始化循环变量 ii <= 10 是条件表达式,每次循环开始前都会判断这个条件,若为真则执行循环体,否则结束循环;i++ 是更新表达式,每次循环体执行完毕后会执行这个表达式,用于更新循环变量 i 的值。

循环嵌套

在一个循环的循环体中可以再包含另一个循环,这就是循环嵌套。例如,打印一个九九乘法表:

#include <stdio.h>

int main() {
    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <= i; j++) {
            printf("%d * %d = %d\t", j, i, i * j);
        }
        printf("\n");
    }

    return 0;
}

这里外层 for 循环控制行数,从 1 到 9。对于每一行,内层 for 循环控制该行的乘法运算个数,其循环次数与当前行号 i 相等。通过这种循环嵌套的方式,就可以完整地打印出九九乘法表。

跳转结构

break 语句

break 语句用于立即终止当前所在的循环(whiledo - whilefor)或 switch 语句,使程序跳转到循环或 switch 语句之后的下一条语句继续执行。例如,在一个 for 循环中,当找到满足特定条件的数时,就提前结束循环:

#include <stdio.h>

int main() {
    for (int i = 1; i <= 10; i++) {
        if (i == 5) {
            break;
        }
        printf("%d ", i);
    }
    printf("\n循环结束\n");

    return 0;
}

在这个例子中,当 i 等于 5 时,执行 break 语句,循环立即结束,程序接着执行 printf("\n循环结束\n"); 这条语句。

continue 语句

continue 语句与 break 语句不同,它不会终止整个循环,而是跳过当前循环中 continue 语句之后的代码,直接开始下一次循环。例如,在一个 for 循环中,只打印奇数:

#include <stdio.h>

int main() {
    for (int i = 1; i <= 10; i++) {
        if (i % 2 == 0) {
            continue;
        }
        printf("%d ", i);
    }
    printf("\n循环结束\n");

    return 0;
}

这里当 i 是偶数时,执行 continue 语句,跳过 printf("%d ", i); 这条语句,直接开始下一次循环,所以最终只会打印出 1 到 10 中的奇数。

goto 语句

goto 语句是一种无条件跳转语句,它可以使程序跳转到指定的标号处继续执行。虽然 goto 语句在一些复杂的代码逻辑中可能会导致代码可读性变差,但在某些特定场景下还是有用的。其语法为:

goto 标号;
...
标号:
    // 跳转到此处执行的代码

例如,使用 goto 语句实现一个简单的循环:

#include <stdio.h>

int main() {
    int i = 1;
    int sum = 0;

start:
    if (i <= 10) {
        sum += i;
        i++;
        goto start;
    }

    printf("1 到 10 的累加和为: %d\n", sum);

    return 0;
}

在这个例子中,goto start; 语句会使程序跳转到 start: 标号处继续执行,从而实现类似于循环的效果。不过,在实际编程中,应尽量避免过度使用 goto 语句,以免造成代码逻辑混乱。

条件运算符与控制结构的关系

条件运算符 ? : 是 C 语言中唯一的三目运算符,它可以根据一个条件表达式的值来选择两个表达式中的一个进行求值。其语法为:

条件表达式? 表达式1 : 表达式2

如果条件表达式为真(非 0),则整个条件表达式的值为表达式 1 的值;否则为表达式 2 的值。例如,求两个数中的较大值:

#include <stdio.h>

int main() {
    int a = 5;
    int b = 8;
    int max = (a > b)? a : b;

    printf("较大值为: %d\n", max);

    return 0;
}

从某种程度上来说,条件运算符可以实现一些简单的 if - else 语句的功能。但它更简洁,适用于一些简单的条件判断场景。而 if - else 语句则更适合处理复杂的条件判断和包含多个语句的代码块。

在实际编程中,要根据具体的需求和代码逻辑来选择使用条件运算符还是 if - else 语句。对于只需要根据条件选择一个简单值的情况,条件运算符可以使代码更加简洁;而对于需要执行不同代码逻辑块的复杂条件判断,if - else 语句则更为合适。

控制结构的实际应用场景

  1. 数据验证:在获取用户输入时,常常需要使用选择结构(如 if - else 语句)来验证输入的数据是否符合要求。例如,验证用户输入的年龄是否在合理范围内:
#include <stdio.h>

int main() {
    int age;
    printf("请输入你的年龄: ");
    scanf("%d", &age);

    if (age >= 0 && age <= 120) {
        printf("年龄输入有效\n");
    } else {
        printf("年龄输入无效\n");
    }

    return 0;
}
  1. 循环计算:循环结构在进行重复计算时非常有用。比如计算阶乘,就可以使用 for 循环:
#include <stdio.h>

int main() {
    int n = 5;
    int factorial = 1;

    for (int i = 1; i <= n; i++) {
        factorial *= i;
    }

    printf("%d 的阶乘为: %d\n", n, factorial);

    return 0;
}
  1. 菜单驱动程序:在开发一些控制台应用程序时,常使用选择结构和循环结构来实现菜单驱动。用户通过选择不同的菜单选项来执行不同的功能,并且可以通过循环让用户不断进行选择,直到选择退出选项。例如:
#include <stdio.h>

int main() {
    int choice;

    while (1) {
        printf("1. 加法运算\n");
        printf("2. 减法运算\n");
        printf("3. 退出\n");
        printf("请选择: ");
        scanf("%d", &choice);

        if (choice == 1) {
            int a, b;
            printf("请输入两个数: ");
            scanf("%d %d", &a, &b);
            printf("两数之和为: %d\n", a + b);
        } else if (choice == 2) {
            int a, b;
            printf("请输入两个数: ");
            scanf("%d %d", &a, &b);
            printf("两数之差为: %d\n", a - b);
        } else if (choice == 3) {
            break;
        } else {
            printf("无效选择,请重新输入\n");
        }
    }

    return 0;
}

在这个例子中,通过 while (1) 创建了一个无限循环,用户可以不断选择菜单选项。if - else if 结构用于根据用户的选择执行相应的操作,当用户选择 3 时,使用 break 语句跳出循环,结束程序。

控制结构优化与注意事项

  1. 避免不必要的嵌套:虽然嵌套控制结构在很多情况下是必要的,但过多的嵌套会使代码的可读性和维护性变差。例如,尽量将复杂的条件判断逻辑进行拆分和简化,避免多层 if - else 嵌套。
  2. 合理选择循环结构:根据具体的需求选择合适的循环结构。如果需要先执行一次操作再判断条件,do - while 循环比较合适;如果明确知道循环次数,for 循环通常是较好的选择;而 while 循环则适用于在条件满足时不断重复执行的场景。
  3. 注意循环变量的更新:在循环中,一定要确保循环变量能够正确更新,否则可能会导致死循环。例如,在 for 循环中忘记写更新表达式,或者在 while 循环中没有改变影响条件表达式的变量值。
  4. 使用 breakcontinue 要谨慎:虽然 breakcontinue 可以方便地控制循环流程,但过度使用可能会使代码逻辑变得不清晰。在使用它们时,要确保代码的可读性和可维护性。

通过深入理解和合理运用 C 语言的控制结构,我们可以编写出逻辑清晰、高效运行的程序。无论是简单的顺序执行,还是复杂的条件判断和循环操作,控制结构都是实现程序功能的关键组成部分。在实际编程中,不断积累经验,根据具体问题选择最合适的控制结构,是成为优秀 C 语言程序员的重要一步。