13 跳转控制语句(break、continue、goto),循环的加强练习

news2025/1/15 13:08:12

目录

1 break

1.1 介绍

1.2 流程图

1.3 在循环中使用 break

1.4 注意事项

1.5 案例:判断质数

2 continue

2.1 介绍

2.2 流程图

2.3 在循环中使用 continue

2.4 案例:逢七过游戏

3 goto 语句

3.1 介绍

3.2 基本语法

3.3 流程图

3.4 基本使用

3.5 死循环

3.6 案例:实现循环

4 编程综合练习

4.1 整数范围判断

4.1.1 scanf 的返回值

4.1.2 清除缓冲区

4.2 闰年判断

4.3 水仙花数判断

4.4 月份天数计算与闰年识别

4.5 星期判断与输出

4.6 遍历并打印指定范围内的闰年

4.7 字符序列打印

4.8 计算交错序列的和

4.9 判断整数的对称性(回文数)

4.10 计算 n 的阶乘 n!

4.11 人民币换零钱组合问题

5 测试题


1 break

1.1 介绍

        break 语句用于终止某个语句块的执行,只能用于 switch 语句或者循环语句中。

        在循环语句中break 语句用于立即退出循环体(在嵌套循环中,break 只会退出最近的封闭循环,不管循环条件是否满足。一旦执行到 break 语句,循环就会终止,控制权会传递给循环之后的下一条语句。

        在 switch 语句中break 语句用于退出 switch 语句块。在 switch 语句中,break 通常用于防止代码自动地继续执行到下一个 case 标签,这是因为在 C 语言中,switch 语句的 case 分支是 “穿透” 的,即如果没有 break 语句,程序会继续执行下一个 case 分支的代码,直到遇到 break 或 switch 语句的末尾。

1.2 流程图

1.3 在循环中使用 break

        目的:主要用于在满足特定条件时提前终止循环

        效果:当 break 语句被执行时,它会导致最近的封闭循环被立即终止,控制流跳转到循环之后的语句

#include <stdio.h>

int main()
{
    for (int i = 0; i < 10; i++)
    {
        // 检查 i 是否等于 3
        if (i == 3)
        {
            // 如果 i 等于 3,则跳出循环
            break;
        }
        // 如果 i 不等于 3,打印 i 的值
        printf("%d \t", i); // 0       1       2
    }

    return 0;
}

        在上面的示例代码中,break 语句用于在 i 等于 3 时退出 for 循环。因此,循环将只打印 i 的值从 0 到 2,当 i 达到 3 时,循环将不会继续执行,而是跳转到 return 0; 语句。

1.4 注意事项

        break 语句只能用于循环或 switch 语句中。如果尝试在循环或 switch 之外使用 break,编译器将报错。

        在 switch 语句中,break 用于防止代码自动 “落入” 下一个 case 语句(即,避免执行不需要的 case 分支)。

        在嵌套循环中,break 只会退出最近的封闭循环。如果需要从多层嵌套的循环中退出,可以使用多个 break 或者考虑使用其他控制流语句(如标志变量、goto 语句,尽管 goto 通常不被推荐)。如下代码所示:

#include <stdio.h>

int main()
{
    int i, j;

    // 外层循环
    for (i = 1; i <= 3; i++)
    {
        printf("外层循环:i = %d\n", i);

        // 内层循环
        for (j = 1; j <= 5; j++)
        {
            // 当 j 等于 4 时,退出内层循环
            if (j == 4)
            {
                break; // 这里只会退出内层循环
            }
            printf("  内层循环:j = %d\n", j);
        }

        // 注意:这里外层循环的迭代会继续进行
        // 因为 break 只退出了内层循环
    }

    return 0;
}

         在上面的示例代码中,外层循环遍历 i 的值从 1 到 3,而内层循环遍历 j 的值从 1 到 5。在内层循环中,有一个条件检查 j 是否等于 4。如果等于 4,则执行 break 语句,这会立即退出内层循环,但外层循环的迭代会继续进行。因此,输出将显示 j 的值从 1 到  3,然后当 j 达到 4 时,内层循环被退出,但外层循环会继续,并且内层循环会再次开始,从 j = 1 重新开始,直到外层循环也完成其所有迭代。

        输出结果如下所示:

1.5 案例:判断质数

        编写程序,要求输入一个数字,判断该数字是否是质数。

        质数(Prime number)是大于 1 的自然数,除了 1 和它本身以外不再有其他因数的数。换句话说,一个大于 1 的自然数,如果只能被 1 和它本身整除,那么这个数就是质数。

#include <stdio.h>
#include <stdbool.h> // 引入布尔类型支持
/* 
    本程序使用了 _Bool 类型来表示布尔值,这是 C99 标准引入的。
    在 C99 之前的版本中,通常使用 int 类型,并通过 0 和非 0 值来表示 false 和 true。
*/

int main()
{
    // 获取输入的数字
    int num;
    printf("输入一个数字:");
    scanf("%d", &num);

    // 定义变量,用于标记是否为质数
    // 大于 1 的数字先标记为真,再通过循环看是否推翻;小于 1 的数字直接标记为假
    _Bool isPrime = num > 1 ? 1 : 0;

    // 循环判断 num 是否为质数
    // 从 2 遍历到 num 的一半(包含),如果 num 能被其中任何一个数整除,则不是质数
    for (int i = 2; i <= num / 2; i++)  // 可以优化到 num 的算术平方根
    {
        if (num % i == 0) // 如果 num 能被 i 整除
        {
            isPrime = 0; // 标记 num 不是质数
            break;       // 退出循环,因为已经找到了一个除数,无需继续检查
        }
    }

    // 根据 isPrime 的值输出结果
    if (isPrime)
    {
        printf("%d 是质数!", num);
    }
    else
    {
        printf("%d 不是质数!", num);
    }

    return 0;
}

        如果不想使用 _Bool 类型(尽管它在 C99 及以后的版本中是完全有效的),可以使用普通的 int 类型来作为标志变量,并通过 0(表示 false)和非 0(通常使用 1 来表示 true)来管理这个标志。以下是修改后的代码,它使用了 int 类型的标志变量来替代 _Bool:

#include <stdio.h>

int main()
{
    // 获取输入的数字
    int num;
    printf("输入一个数字:");
    scanf("%d", &num);

    // 定义变量,用于标记是否为质数
    // 大于 1 的数字先标记为真(1),再通过循环看是否推翻;小于 1 的数字直接标记为假(0)
    int isPrime = num > 1 ? 1 : 0;

    // 循环判断 num 是否为质数
    // 从 2 遍历到 num 的一半(包含),如果 num 能被其中任何一个数整除,则不是质数
    for (int i = 2; i * i <= num; i++) // 优化:只需检查到 sqrt(num) 即可
    {
        if (num % i == 0) // 如果 num 能被 i 整除
        {
            isPrime = 0; // 标记 num 不是质数
            break;       // 退出循环,因为已经找到了一个除数,无需继续检查
        }
    }

    // 根据 isPrime 的值输出结果
    if (isPrime)
    {
        printf("%d 是质数!", num);
    }
    else
    {
        printf("%d 不是质数!", num);
    }

    return 0;
}

        在这个修改后的版本中,isPrime 被声明为一个 int 类型的变量,并且通过 1(表示 true)和 0(表示 false)来设置其值。

        此外,我还对质数检查的逻辑进行了一个小优化,即将循环的上限从 num / 2 改为 sqrt(num)。不过,由于 C 语言标准库中并没有直接计算平方根的函数返回整数类型,所以在这里我保留了 i * i <= num 作为条件,它等价于检查 i 是否小于或等于 num 的平方根。这样做可以避免浮点运算,同时保持逻辑的正确性。

        如果确实需要调用平方根函数,可以使用 <math.h> 头文件中的 sqrt() 函数,但请注意,这将引入浮点数的精度问题,并且可能需要将 i 声明为 double 类型。然而,在这个特定的情况下,使用 i * i <= num 是一种更简洁且高效的方法。 

        注意:在检查质数时,我们实际上可以只遍历到 sqrt(num) 而不是 num/2,因为如果 num 有一个大于 sqrt(num) 的因数,那么它必定还有一个小于或等于 sqrt(num) 的因数。这个优化可以显著提高对于大数的质数检查的效率。


2 continue

2.1 介绍

        continue 只能用在 for、while 或 do-while 循环中。

        continue 用于跳过当前循环的剩余部分,并强制开始下一次循环的迭代

        continue 语句只影响它所在的那一层循环,如果在一个嵌套的循环中使用 continue,它将只跳过当前循环的剩余部分,并继续执行外层循环的下一次迭代。

        与 break 的区别:continue 和 break 都用于控制循环的流程,但它们的作用不同。continue 跳过当前迭代的剩余部分,而 break 则完全退出循环

2.2 流程图

2.3 在循环中使用 continue

        目的:在某些条件下,可能不希望执行循环体中的全部代码。使用 continue 可以跳过当前迭代中 continue 之后的代码,直接开始下一次迭代;当知道某些情况下继续执行循环体的剩余部分将是徒劳的,使用 continue 可以避免这些无用的计算或操作,从而提高程序的执行效率。

        效果:一旦 continue 语句被执行,循环体中 continue 之后的任何代码都将被忽略,循环控制将直接跳转到下一次迭代的开始;虽然 continue 不会改变循环的总迭代次数(除非它与循环条件或修改循环控制变量的代码结合使用),但它可以减少循环体中某些代码块的执行次数。

#include <stdio.h>

int main()
{
    // 使用 for 循环遍历从 0 到 9 的数字
    for (int i = 0; i < 10; i++)
    {
        // 判断当前数字是否等于 3
        if (i == 3)
        {
            // 如果是 3,则执行 continue 语句,跳过当前循环的剩余部分,直接进入下一次循环迭代
            continue;
        }
        // 如果 i 不等于3,则执行以下语句,打印当前数字并换行
        printf("%d \t", i);
        // 输出: 0       1       2       4       5       6       7       8       9
    }

    return 0;
}

       在上面的示例代码中,for 循环从 0 开始,直到 9 结束,循环变量 i 每次循环都会增加 1。在循环体内,首先通过一个 if 语句检查i的值是否等于 3。如果等于 3,则执行 continue 语句,这将导致循环体中的剩余部分(即 printf 函数调用)被跳过,并立即开始下一次循环迭代。如果 i 的值不等于 3,则执行 printf 函数,打印出当前的 i 值并换行。因此,这个程序将打印出 0 到 9 之间的所有数字,但会跳过数字 3 的打印。

2.4 案例:逢七过游戏

        输出 100 以内(包括100)的数字,跳过那些 7 的倍数或包含 7 的数字。

#include <stdio.h>

int main()
{
    // 初始化一个 for 循环,从 1 遍历到 100(包含1 和 100)
    for (int i = 1; i <= 100; i++)
    {
        // 逻辑判断部分
        // i % 7 == 0 判断当前数字 i 是否是 7 的倍数
        // i % 10 == 7 判断当前数字 i 的个位上是否带 7
        // i / 10 == 7 判断当前数字 i 的十位上是否带 7
        // 如果上述三个条件中的任意一个为真,则执行 continue 语句
        if (i % 7 == 0 || i % 10 == 7 || i / 10 == 7)
        {
            // 当满足上述任一条件时,使用 continue 语句跳过当前循环的剩余部分
            // 即跳过 printf 语句,直接开始下一次循环迭代
            continue;
        }
        // 如果不满足上述条件,则执行 printf 语句,打印出当前数字 i
        printf("%d ", i);
    }

    return 0;
}

        输出结果如下所示:

        注意:在循环的最后一行之前使用 continue 是多余的,因为它会立即导致循环进入下一次迭代,而循环的末尾代码(如果有的话)将不会被执行。


3 goto 语句

3.1 介绍

        goto 语句是一个跳转语句它允许程序无条件地跳转到同一函数内的另一个标签(label)处继续执行,标签(label)的名称可以自行设置,需要满足标识符规范。

        goto 语句通常被认为是一种不良的编程实践,因为它可能导致代码难以理解和维护,特别是当程序变得复杂时。在开发中不建议使用 goto 语句,但我们需要掌握 goto 语句的执行流程,以能够看懂其他开发者的代码中可能出现的 goto 语句。

3.2 基本语法

goto 标签名  // 跳转到指定的标签(label)处
...
标签名:      // 定义一个标签(label)
语句;        // 跳转到这里

        goto 后面如果引用了没有定义的标签,编译器会报错!

3.3 流程图

3.4 基本使用

#include <stdio.h>

int main()
{
    printf("start \n");

    // 使用 goto 语句跳转到标签 label1 处执行
    goto label1; // label1 是标签名,这里会跳过下面的两条打印语句

    // 下面的两条打印语句由于 goto 的存在,将不会被执行
    printf("ok1 \n");
    printf("ok2 \n");

label1:
    // 跳转到这里执行
    printf("ok3 \n");
    printf("ok4 \n");

    return 0;
}

        输出结果如下所示:

3.5 死循环

        在 C 语言中,使用 goto 语句可以很容易地创建一个死循环。死循环是指程序中的一段代码无限次地重复执行,而没有明确的退出条件。

        在下面这个例子中,goto start; 语句将程序的控制流无条件地跳转到标签 start: 处,这导致 printf 语句无限次地重复执行,形成了一个死循环。 

#include <stdio.h>  
  
int main() {  
    start: // 定义一个标签名为 start  
    printf("这是一个死循环\n");  
    goto start; // 跳转到标签start处,形成死循环  
  
    // 注意:由于goto语句的存在,下面的代码将永远不会被执行  
    return 0;  
}

        下面是一个使用 goto 语句创建死循环的另一个例子,其中涉及两个标签互相跳转,形成一个无限循环。

#include <stdio.h>

int main()
{
// 定义两个标签
label1:
    printf("正在跳转到 label2...\n");
    goto label2; // 跳转到 label2

label2:
    printf("已经到达 label2,准备跳回 label1...\n");
    // 注意:这里没有使用任何条件来判断何时停止循环
    // 因此,这将是一个无限循环
    goto label1; // 跳回 label1

    // 下面的代码由于无限循环的存在,将永远不会被执行
    printf("这条语句永远不会被执行。\n");

    return 0;
}

        在实际编程中,我们应该避免创建无限循环,除非我们确实需要程序持续运行(例如,等待用户输入或监听网络事件)。如果确实需要无限循环,并且编译器发出警告,我们可以考虑使用 while(1) 循环或其他方法来明确表达我们的意图,而不是使用 goto 语句。

        另外,请记得在需要的时候提供适当的退出机制,比如通过用户输入、特定条件或错误处理来跳出循环。

3.6 案例:实现循环

        使用 goto 语句实现循环输出数字 1 ~ 5。

#include <stdio.h>

int main()
{
    int i = 1; // 初始化计数器 i 为 1

start:          // 定义一个标签 start,用于 goto 语句跳转
    if (i <= 5) // 判断 i 是否小于或等于 5
    {
        printf("%d ", i); // 打印当前 i 的值
        i++;              // 将 i 的值增加 1
        goto start;       // 如果 i 仍然小于或等于 5,则跳转到标签 start 处继续执行
    }

    // 如果 i 大于 5,则不执行 goto 语句,程序继续向下执行到 return 语句
    return 0;
}

        注意:虽然 goto 语句在某些特定情况下(如错误处理和复杂的条件跳转)可能有用,但通常建议避免使用它,特别是用于创建循环结构。在大多数情况下,使用 for、while 或 do-while 循环是更清晰、更可维护的选择。 


4 编程综合练习

4.1 整数范围判断

        编写一个 C 语言程序,该程序要求用户输入一个整数,并根据输入的整数值判断它属于哪个范围:大于 0、小于 0 还是等于 0。然后,程序应该输出相应的信息来告知用户他们的输入属于哪个范围。

#include <stdio.h>

int main()
{
    int number;
    int scanResult; // 用于存储 scanf 的返回值,返回读取成功的个数

    printf("请输入一个整数:");

    // 尝试读取一个整数
    // 将读取操作放在 while 循环中,可以一直读取数据
    while ((scanResult = scanf("%d", &number)) != 1)
    {
        // 如果 scanf 没有读取到一个整数(即返回值不是 1 )
        // 清除输入缓冲区中的残留输入
        while (getchar() != '\n')
            ;

        // 提示用户重新输入
        printf("输入错误,请输入一个整数:");
    }

    // 现在我们已经成功读取了一个整数
    if (number > 0)
    {
        printf("输入的整数大于0。\n");
    }
    else if (number < 0)
    {
        printf("输入的整数小于0。\n");
    }
    else
    {
        printf("输入的整数等于0。\n");
    }

    return 0;
}

        输出结果如下所示:

4.1.1 scanf 的返回值

        当 scanf 用于读取一个整数(例如,使用 "%d" 格式说明符)时,它会尝试从输入缓冲区中解析一个整数如果成功,它会返回成功读取的项目数。如果失败(比如因为输入的不是一个整数),它会返回一个小于请求的项目数的值(在这个情况下是 0,因为请求的是 1 个整数但没有成功读取到)。

4.1.2 清除缓冲区

// 如果 scanf 没有读取到一个整数(即返回值不是 1 )  
while (getchar() != '\n')  
    ;

        上面这段代码的目的是在 scanf 未能读取到一个整数时,清除输入缓冲区中残留的、导致 scanf 失败的非整数输入,以便程序可以重新尝试读取有效的整数输入。

        下面是代码的详细解释:

        while (getchar() != '\n'):这个循环会一直执行,直到 getchar() 函数读取到换行符(\n)为止。getchar() 函数从输入缓冲区中读取下一个可用的字符,并返回它。如果缓冲区中没有字符可供读取,程序将等待用户输入。

        ;:循环体是空的,这意味着每次循环迭代时实际上什么也不做,只是调用 getchar() 函数并丢弃它的返回值,直到遇到换行符。这样做是为了消耗掉输入缓冲区中所有导致 scanf 失败的字符,包括可能的非数字字符、空格、制表符等,直到用户按下回车键(此时换行符 \n 被放入输入缓冲区)。

        通过这种方式,程序能够清除输入缓冲区中残留的无效输入,并准备好接收新的输入尝试。这通常是在需要循环读取用户输入直到获得有效输入时使用的技术之一。

4.2 闰年判断

        编写一个 C 语言程序,该程序要求用户输入一个年份,并判断该年份是否为闰年。根据用户输入的年份,输出相应的判断结果,即告知用户该年份是闰年还是非闰年。

        根据闰年的定义,一个年份如果满足以下条件之一,则被认为是闰年:

  • 该年份能被 4 整除,但不能被 100 整除。
  • 该年份能被 400 整除。
#include <stdio.h>

int main()
{
    int year;
    printf("请输入一个年份:");
    scanf("%d", &year);

    // 省略对年份的合法性判断

    // 判断年份是否为闰年
    if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
    {
        printf("%d 是闰年。\n", year);
    }
    else
    {
        printf("%d 不是闰年。\n", year);
    }

    return 0;
}

4.3 水仙花数判断

        编写一个 C 语言程序,该程序直接在 main 函数中实现判断一个整数是否为水仙花数的功能。水仙花数是一个三位数,其各位数字的立方和等于该数本身。例如,153 是一个水仙花数,因为 1^3 + 5^3 + 3^3 = 153。

#include <stdio.h>

int main()
{
    int number, ge, si, bai, sum;

    printf("请输入一个整数(三位数):");
    scanf("%d", &number);

    // 确保是三位数
    if (number < 100 || number > 999)
    {
        printf("输入的不是一个三位数。\n");
        return 1; // 返回一个非零值表示程序异常退出
    }

    // 分解数字
    ge = number % 10;        // 个位数
    si = (number / 10) % 10; // 十位数
    bai = number / 100;      // 百位数

    // 计算立方和
    sum = ge * ge * ge + si * si * si + bai * bai * bai;

    // 判断是否为水仙花数
    if (sum == number)
    {
        printf("%d 是水仙花数。\n", number);
    }
    else
    {
        printf("%d 不是水仙花数。\n", number);
    }

    return 0;
}

4.4 月份天数计算与闰年识别

        编写一个 C 语言程序,该程序能够接收用户输入的月份和年份,然后根据这些信息计算出该月份在指定年份中的天数。程序需要特别考虑闰年的情况,因为闰年的 2 月份有 29 天,而平年的 2 月份只有 28 天。

#include <stdio.h>

int main()
{
    int month, year;
    printf("请输入月份(1-12):");
    scanf("%d", &month);
    printf("请输入年份:");
    scanf("%d", &year);

    // 检查月份是否合法
    if (month < 1 || month > 12)
    {
        printf("输入的月份不合法。\n");
        return 1; // 非零返回值表示异常结束
    }

    // 初始化天数,默认为 31 天
    int days = 31;

    // 使用 switch 语句来判断月份并可能地修改天数
    switch (month)
    {
    case 2: // 2月需要特别判断是否为闰年
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
        {
            days = 29;
        }
        else
        {
            days = 28;
        }
        break;
    case 4:
    case 6:
    case 9:
    case 11:
        days = 30; // 4、6、9、11 月为 30 天
        break;
        // 1、3、5、7、8、10、12 月保持默认的 31 天
    }

    printf("%d年%d月有%d天。\n", year, month, days);

    return 0;
}

4.5 星期判断与输出

        编写一个 C 语言程序,该程序能够接收用户输入的星期几(以数字形式表示,其中 1 代表星期一,7 代表星期日),然后根据输入的星期数字打印出相应的信息。具体要求如下:

  • 如果用户输入的星期数字是 1 到 3(包含 1 和 3),则打印出 “AAA”。
  • 如果用户输入的星期数字是 4 到 5(包含 4 和 5),则打印出 “BBB”。
  • 如果用户输入的星期数字是 6 或 7,则打印出 “CCC”。
  • 如果用户输入的星期数字不是 1 到 7 之间的整数,则打印出 “输入错误”。
#include <stdio.h>

int main()
{
    int day;
    printf("请输入星期几(1-7):");
    scanf("%d", &day);

    // 对输入进行合法性检查
    if (day < 1 || day > 7)
    {
        printf("输入错误。\n");
    }
    else
    {
        switch (day)
        {
        case 1:
        case 2:
        case 3:
            printf("AAA\n");
            break;
        case 4:
        case 5:
            printf("BBB\n");
            break;
        case 6:
        case 7:
            printf("CCC\n");
            break;
            // 注意:这里的 default 实际上是不需要的,因为所有可能的输入值都已经被覆盖
        }
    }

    return 0;
}

4.6 遍历并打印指定范围内的闰年

        编写一个 C 语言程序,该程序需要遍历从 1000 年到 999 9年(包含 1000 年和 9999 年)的所有年份,并判断每个年份是否为闰年。如果是闰年,则将该年份打印到控制台上。闰年的判断规则是:一个年份如果能被 4 整除且不能被 100 整除,或者能被 400 整除,则该年份是闰年。分别使用 for 循环、while 循环和 do-while 循环实现上述功能

#include <stdio.h>  
  
int main() {  
    int year;  
    for (year = 1000; year <= 9999; year++) {  
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {  
            printf("%d\n", year);  
        }  
    }  
    return 0;  
}
#include <stdio.h>  
  
int main() {  
    int year = 1000;  
    while (year <= 9999) {  
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {  
            printf("%d\n", year);  
        }  
        year++;  
    }  
    return 0;  
}
#include <stdio.h>  
  
int main() {  
    int year = 1000;  
    do {  
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {  
            printf("%d\n", year);  
        }  
        year++;  
    } while (year <= 9999);  
    return 0;  
}

4.7 字符序列打印

        编写一个 C 语言程序,该程序需要完成以下任务:

  • 打印小写字母:首先,程序需要按顺序打印出所有的小写英文字母(a 到 z)。
  • 打印大写字母逆序:接着,程序需要以逆序的方式(即从 Z 到 A)打印出所有的大写英文字母。
#include <stdio.h>  
  
int main() {  
    // 输出小写字母 a-z  
    for(char c = 'a'; c <= 'z'; c++) {  
        printf("%c ", c);  
    }  
    printf("\n"); // 换行  
  
    // 输出大写字母 Z-A  
    for(char c = 'Z'; c >= 'A'; c--) {  
        printf("%c ", c);  
    }  
    printf("\n"); // 换行  
  
    return 0;  
}

4.8 计算交错序列的和

        编写一个 C 语言程序,该程序需要计算并输出序列 1 - 1/2 + 1/3 - 1/4 + ... + 1/n 的和,其中 n 是一个用户指定的正整数(例如,n = 100)。序列中的每一项的符号交替出现,即第一项为正,第二项为负,第三项为正,以此类推。

#include <stdio.h>  
  
int main() {  
    double sum = 0.0; // 用来存储序列的和  
    int sign = 1;     // 用来表示当前的符号,初始化为正(1)  

    for (int i = 1; i <= 100; i++) {  
        // 将当前项加到总和中,注意将 1 转换为 1.0 以避免整数除法
        sum += sign * 1.0 / i;   

        // 改变符号,为下一次迭代做准备
        sign = -sign;            
    }  
    printf("The sum of the series is: %f\n", sum);  

    return 0;  
}

4.9 判断整数的对称性(回文数)

        输入一个整型数,判断是否是对称数,如果是,输出 yes,否则输出 no,不用考虑这个整型数过大,int 类型存不下,不用考虑负值;例如 12321 是对称数,输出 yes,124421 是对称数,输出 yes,1231 不是对称数,输出 no。

#include <stdio.h>

int main()
{
    // inputNumber : 用于存储输入的数字
    // reversedNumber : 用于存储反转后的数字,必须初始化,后需要对其做乘 10 处理
    // tempNumber : 临时存储输入的数字,用于后续比较
    int inputNumber, reversedNumber = 0, tempNumber;

    // 从用户处获取输入的数字
    printf("请输入一个整数:");
    scanf("%d", &inputNumber);

    // 保存原始数字,以便后续比较
    tempNumber = inputNumber;

    // 反转数字
    while (inputNumber != 0)
    {
        // // 将当前数字的个位添加到反转数字中,并乘以 10 为下一位做准备
        reversedNumber = reversedNumber * 10 + inputNumber % 10;
        // 去除当前数字的个位
        inputNumber /= 10;
    }

    // 判断输入的数字是否与反转后的数字相等
    if (tempNumber == reversedNumber)
    {
        printf("yes"); // 是对称数,输出"yes"
    }
    else
    {
        printf("no"); // 不是对称数,输出"no"
    }

    return 0;
}

4.10 计算 n 的阶乘 n!

        利用 while 或者 for 循环计算 n! 的值。

#include <stdio.h>
 
int main() {
    int number,factorial = 1; // 初始化阶乘结果为 1  
 
    // 读取用户输入的数
    scanf("%d", &number);
 
    // 使用 for 循环计算阶乘  
    for(int i = 1; i <= number; i++) {
        factorial *= i; // 累乘计算阶乘  
    }
 
    // 输出结果  
    printf("%d\n", factorial);
 
    return 0;
}

4.11 人民币换零钱组合问题

题目描述:

        某人想将手中的一张面值 100 元的人民币换成 10 元、5 元、2 元和 1 元面值的票子,要求换正好 40 张,并且每种票子至少各有一张。请问有多少种不同的换法?

题目分析:

        为了更高效地解决这个问题,我们需要考虑每种面额纸币的数量范围,并据此设置循环的边界条件。具体地,我们可以这样设定:

  • 10 元纸币:由于至少要有 1 张,且最多不能超过 9 张(否则总金额会超过 100元),所以循环范围从 1 到 9。
  • 5 元纸币:在剩余金额和剩余张数(40 减去已选的10元纸币数量)的限制下,最多可以选取(100 - 10*已选10元数 - 2 - 1) / 5 张,但至少要有 1 张,所以循环范围需要根据已选的 10 元纸币数量动态计算。
  • 2 元纸币:同样地,其数量也需要在剩余金额和剩余张数的限制下确定,但至少要有 1 张。
  • 1 元纸币:最后,剩余的张数和金额将全部用于 1 元纸币,但也需要至少 1 张。
#include <stdio.h>
 
int main() {
    int counter = 0; // 用于计数满足条件的换法
    
    // 外层循环:10 元纸币的数量,从 1 到 9 张
    for (int i = 1; i <= 9; ++i) {
        // 注释:10 元纸币的数量不能为 0(至少 1 张),且不能超过 9 张(否则总金额会超过 100 元)
        
        // 第二层循环:5 元纸币的数量,从 1 到 17 张
        for (int j = 1; j <= 17; ++j) {
            // 注释:5 元纸币的数量也不能为 0(至少 1 张),(100-10-2-1)/5=17
            
            // 第三层循环:2 元纸币的数量,从 1 到 37 张
            for (int k = 1; k <= 37; ++k) {
                // 注释:2 元纸币的数量也不能为 0(至少 1张),最多 37 张
                
                // 第四层循环:1 元纸币的数量,从 1 到 37 张
                for (int l = 1; l <= 37; ++l) {
                    // 注释:1 元纸币的数量也不能为 0(至少 1 张),最多 37 张
                    
                    // 检查当前组合是否满足总金额为 100 元和总张数为 40 张的条件
                    if (100 == i * 10 + j * 5 + k * 2 + l * 1 && 40 == i + j + k + l) {
                        counter++; // 如果满足条件,则计数器加 1
                    }
                }
            }
        }
    }
    // 输出满足条件的换法总数
    printf("%d\n", counter);
    
    return 0;
}

        上面代码可以通过减少不必要的循环来优化。关键在于,一旦选择了 10 元、5 元和 2 元纸币的数量后,1 元纸币的数量就可以直接计算出来,而不需要额外的循环。此外,5 元和 2 元纸币的最大数量也需要根据已经选择的 10 元纸币数量以及剩余需要填补的金额和张数来动态调整。

        下面是一个优化后的版本:

#include <stdio.h>

int main()
{
    int counter = 0; // 用于计数满足条件的换法

    // 外层循环:10 元纸币的数量,从 1 到 9 张
    for (int i = 1; i <= 9; ++i)
    {
        // 剩余金额和剩余张数
        int remaining_amount = 100 - i * 10;
        int remaining_count = 40 - i;

        // 第二层循环:5 元纸币的数量
        for (int j = 1; j <= remaining_amount / 5 && j <= remaining_count - 2; ++j)
        {
            // 剩余金额和剩余张数
            remaining_amount -= j * 5;
            remaining_count -= j;

            // 第三层循环:2 元纸币的数量
            for (int k = 1; k <= remaining_amount / 2 && k <= remaining_count - 1; ++k)
            {
                // 剩余金额和剩余张数
                remaining_amount -= k * 2;
                remaining_count -= k;

                // 计算 1 元纸币的数量
                int l = remaining_amount; // 剩余金额即为 1 元纸币的数量
                if (remaining_count == l)
                {              // 检查剩余张数是否与1元纸币数量相等
                    counter++; // 如果满足条件,则计数器加 1
                }

                remaining_amount += k * 2; // 恢复剩余金额
                remaining_count += k;      // 恢复剩余张数
            }

            remaining_amount += j * 5; // 恢复剩余金额
            remaining_count += j;      // 恢复剩余张数
        }
    }

    // 输出满足条件的换法总数
    printf("%d\n", counter);

    return 0;
}

        注意:在进行数据处理之前,进行详尽且准确的数据验证是至关重要的,以确保数据的质量、完整性和准确性,从而支持更可靠的分析和决策过程。如上面编程练习中对用户输入的数据基本上都进行了正确性校验。


5 测试题

1. 请写出下面程序的运行结果:

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

【答案】7

【解析】
        (1)当 i 等于 1 时,sum 变为 1。
        (2)当 i 等于 2 时,sum 变为 1 + 2 = 3。
        (3)当 i 等于 3 时,由 于continue 语句,循环体内的 sum += i; 不会执行,所以 sum 保持不变为 3。
        (4)当 i 等于 4 时,sum 变为 3 + 4 = 7。

        因此,最终的输出是:7

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2062779.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开学必备清单来啦!大学好物合集推荐!每一个都能帮你提升幸福感

随着开学季的到来&#xff0c;好多学生都在忙着准备各类学习与生活必需品&#xff0c;以迎接新的大学生活到来。以下是一些开学季必备的好物推荐&#xff0c;每一个都很实用&#xff0c;可以帮你提升学习和生活的幸福感&#xff01; 1、西圣电容笔 一句话推荐&#xff1a;公认…

Windows 11 24H2 终于允许多个应用程序同时使用摄像头

Windows 11&#xff08;以及任何旧版本的 Windows&#xff09;均不允许多个摄像头应用程序访问网络摄像头硬件&#xff0c;除非使用第三方应用程序创建虚拟摄像头设置。这种情况将在未来发布的 Windows 11 版本 24H2 中得到改变&#xff0c;该版本将增加一项可选功能&#xff0…

nginx 添加第三方nginx_upstream_check_module 模块实现健康状态检测

安装插件 下载 链接&#xff1a;https://pan.baidu.com/s/1iTPEmu_hCHYhDyaVDDTsVg?pwdvaw8 提取码&#xff1a;vaw8 安装依赖 yum install pcre pcre-devel yum -y install make gcc-c gcc编译安装 $ nginx -V #此处省略了很多模块&#xff0c;只是为了看清而已 ... co…

轻松掌握LLM三角原则:简化大模型应用开发流程的理解指南

不少朋友偷偷问我&#xff1a;“什么是LLM的三角原则&#xff1f;”今天就给大家仔细讲讲构建LLM应用的三角原则。这套原则其实不复杂&#xff0c;由“31”(一范式三原则)个基础组成&#xff0c;适合任何团队来实践。 说到以LLM为核心的应用&#xff0c;有不少人以为是高大上的…

【考研数学】二战能不看课,直接刷1000题或者李林880吗?

二战数学&#xff0c;刷题的时间肯定要大于看课的时间&#xff0c;同时听课要注意&#xff1a; 1、针对问题听课&#xff0c;听课的时候你要带有目的性&#xff0c;如果毫无目的&#xff0c;那么这节课你能获得的东西就十分优先&#xff0c;你的精力也不会集中&#xff08;提高…

JS SyntaxError: Unexpected token 报错解决

JS SyntaxError: Unexpected token 报错解决 在JavaScript开发中&#xff0c;SyntaxError: Unexpected token 是一个常见的错误&#xff0c;它通常表示JavaScript引擎在解析代码时遇到了意料之外的符号。这个错误可能由多种原因引起&#xff0c;包括拼写错误、缺少括号、引号不…

MySQ分库分表与MyCat安装配置

目录 介绍 拆分策略 垂直拆分 1. 垂直分库 2. 垂直分表 水平拆分 1. 水平分库‘ 2. 水平分表 实现技术 MyCat概述 安装 概念介绍 MyCat入门 需求 环境准备 分片配置 启动服务 连接测试 执行SQL语句测试 MyCat配置 1. schema.xml 1. schema标签 2. dat…

观测云产品更新 | 异常追踪、数据保存策略、BPF 日志、管理优化等

观测云更新 Breaking Changes OpenAPI&#xff1a;【事件】未恢复事件数据源从 UE 变更为 E 。 新增功能 管理&#xff1a;新增 Client Token 统一管理入口&#xff0c;用户使用公网 DataWay 接入 RUM 应用时&#xff0c;可更换系统默认生成的 Token&#xff0c;使用自定义…

重生奇迹 MU热血与激情的战斗岁月

这里&#xff0c;是一个充满神秘与奇幻色彩的大陆。古老的城堡诉说着往昔的荣耀&#xff0c;广袤的荒野等待着勇敢者的探索。长春的勇士们&#xff0c;准备好迎接挑战了吗&#xff1f; 绚丽的画面&#xff0c;每一帧都如同精美的画卷。从神秘的魔法森林到雄伟的龙巢&#xff0…

看看镭速传输中如何处理Mysql超时配置问题的

Mysql作为一个广泛使用的开源关系型数据库管理系统&#xff0c;以快速、可靠、易于使用、开源的特色闻名&#xff0c;使用 MySQL 来存储和管理数据&#xff0c;已经广泛应用于各个领域、各类大小型应用中。 使用 MySQL 来存储和管理数据的应用中&#xff0c;与数据库之间的连接…

程序员如何利用AI大模型逆袭

随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;尤其是大规模预训练模型&#xff08;如GPT-4、BERT等&#xff09;的出现&#xff0c;程序员迎来了一个前所未有的机会窗口。AI不仅能提高开发效率&#xff0c;还能为程序员提供创新创业的机会。本文将探讨程序…

pytorch, torch_tesnsorrt安装各版本匹配

python -m pip install torch2.3.0 torchvision0.18.0 torch-tensorrt2.3.0 tensorrt10.0.1 --extra-index-url https://download.pytorch.org/whl/cu118 如果import tensorrt失败&#xff0c;则从官网下载再安装 https://developer.nvidia.com/tensorrt/download/10x 下载10.0…

四、Docker使用

1. 快速入门 1.1. Docker背景介绍 Docker是一个开源的平台&#xff0c;用于开发、交付和运行应用程序。它能够在Windows&#xff0c;macOS&#xff0c;Linux计算机上运行&#xff0c;并将某一应用程序及其依赖项打包至一个容器中&#xff0c;这些容器可以在任何支持Docker的环…

Aigtek电压放大器电路的特点是什么

电压放大器是一种电路&#xff0c;用于将低电压信号放大为高电压信号。它在电子、通信、音频和视频等领域广泛应用。下面是电压放大器电路的一些特点。 放大倍数高&#xff1a;电压放大器的主要功能是将输入信号的幅度放大到所需的输出电压。因此&#xff0c;电压放大器的一个重…

AI绘画工具 Stable Diffusion【插画转绘】:建筑 | 风景| 人像照片的插画转绘制作教程,照片秒变插画风格图片!

大家好&#xff0c;我是画画的小强 关于Stable Diffusion 的插画转绘&#xff0c;今天给大家分享一种制作方法。我们先看一下效果图。 一. 图片转插画的制作方法 本期教程我们将使用AI绘画工具Stable Diffusion&#xff0c;关于SD的安装和入门使用可以看看我的往期入门教程…

如何用Java SpringBoot+Vue搭建太原学院商铺管理系统?

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

解锁未来财富密码:AI自动化副业创收班——终身财富加速器

副业创收已经成为行业趋势&#xff0c;在当前经济形势下&#xff0c;许多人面临着行业裁员的不确定性。为了增强个人的抗风险能力&#xff0c;寻求一份副业已经成为一种重要的趋势。这不仅是经济上的补充&#xff0c;更是对自由与独立的一种追求——它应让你自主掌控&#xff0…

AI预测福彩3D采取888=3策略+和值012路或胆码测试8月22日新模型预测第64弹

经过60多期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率非常高&#xff0c;60多期一共只错了6次&#xff0c;这给喜欢打私房菜的朋友提供了极高价值的预测结果~当然了&#xff0c…

chapter1_数制和码制

文章目录 1.简介2.常用的数制2.1 十进制2.2 二进制2.3 八进制2.4 十六进制 3.不同进制之间的转换3.1 二—十进制3.2 十—二进制3.3 十六—二进制3.4 二—十六进制3.5 八进制数与二进制数的转换3.6 十六进制数与十进制数的转换 4.二进制算数运算4.1 反码、补码和补码运算 5.几种…

源代码一定要加密!10款超级好用的源代码加密软件排行榜

在当今高度竞争的商业环境中&#xff0c;源代码不仅是软件产品的基础&#xff0c;更是企业的核心资产之一。保护源代码免受未经授权的访问和盗窃至关重要。为此&#xff0c;许多企业采用源代码加密软件来为这一重要资产增加额外的安全层。以下是2024年企业通用的十大源代码加密…