循环应用
Suzhou 530 0
求和

循环应用 上述表达式的起点1和终点n比较明确,使用for循环更合适。

#include <stdio.h>

int main()
{
    int a = 1;
    int n;
    double sum;
    scanf("%d",&n);
    for(a;a <= n;a++)
    {
        sum += 1.0/a;
    }
    printf("f(%d)=%f",n,sum);
    return 0;
}
3
f(3)=1.833333
--------------------------------
Process exited after 1.677 seconds with return value 0

在除号两边放一个浮点数,会把另一个数字也变成浮点数。


循环应用

#include <stdio.h>

int main()
{
    int a = 1;
    int n;
    double sum;
    int sign = 1;
    scanf("%d",&n);
    for(a;a <= n;a++)
    {
        sum += sign * 1.0/a;
        sign = -sign;
    }
    printf("f(%d)=%f",n,sum);
    return 0;
}
3
f(3)=0.833333
--------------------------------
Process exited after 1.119 seconds with return value 0

上述程序可以将变量sign定义为double类型并赋值1.0,在12行中将分子的1去掉,变为sign / a。


最大公约数

输入两个数字求最大公约数

  1. 枚举: 如果两个数都能被同一个数a整除,这个数字就是两个数的公约数记为i,数字a每次加1,再用两个数整除,如果余数为0,就赋值给i,直到数字a和两个数中的某一个相等,此时i 的值为两个数字的最大公约数。
    #include <stdio.h>
    

int main() { int a,b; scanf("%d %d",&a,&b); int min; if(a < b){ min = a; }else{ min = b; } int i; int ret; for(i = 1;i < min;i++){ if (a % i == 0){ if (b % i == 0){ ret = i;
} } } printf("%d和%d的最大公约数是%d",a,b,ret); return 0; }

12 16 12和16的最大公约数是4


Process exited after 3.57 seconds with return value 0

上述程序的循环体,i为公约数,从1开始(两个质数的最大公约数为1),依次递增。debug for循环,发现程序在满足循环条件时执行16行第一个if循环语句,如果16行if语句成立,执行17行的if语句,如果不成立,回到for循环中继续执行for循环的动作并进入下一轮循环。
2.辗转相除法
**算法:求a和b的最大公约数,a除以b,余数记为t,然后使得a=b,b=t,继续计算a除以b,t为余数,a=b,b=t,直到b=0,计算结束,a的值为最大公约数。**

#include <stdio.h>

int main() { int a,b; int t = 0; scanf("%d %d",&a,&b); for(t = 0;b != 0;){ t = a % b; a = b; b = t; } printf("最大公约数为%d",a); return 0; }

12 18 最大公约数为6


Process exited after 4.289 seconds with return value 0

::: tip
  while循环可以和for循环等价互换,上述的for循环可以使用如下程序替代:

while(b != 0){ t = a % b; a = b; b = t; }

:::

------------------------------------
###### 整数分解
1.正序分解整数
要求:输入非负整数,正序输出每一位数字,中间加空格,末尾不加空格。
#include <stdio.h>

int main()
{
    int a;
    scanf("%d",&a);
    int d;
    while(a > 0){
        d = a % 10;
        printf("%d ",d); 
        a /= 10;
    }
    return 0;
}

15243 3 4 2 5 1


Process exited after 2.629 seconds with return value 0

部分编译器会输出如下信息:

15243 3 4 2 5 1 Program exited with status 0

如上图所示,输出结果1后面有空格,可以做如下的改动:
#include <stdio.h>

int main()
{
    int a;
    scanf("%d",&a);
    int d;
    while(a > 0){
        d = a % 10;
        printf("%d",d); 
        a /= 10;
        if(a >= 0){
            printf(" ",d);
        }
    }
    printf("\n");
    return 0;
}

265563 3 6 5 5 6 2Program exited with status 0

为方便观察输出最后一个数字后是否有空格,程序退出提示在输出结果一行,可以在return那一行之前加上“**printf("\n");**”
2.逆序分解整数
算法:逆序分解整数可以在正序的基础上,先执行一轮循环将整数倒过来写,然后再正序输出。该循环中先设逆序后的数字为t,每次提取出正序整数的最后一位记为d,然后使得t=t*10+d,最后使用a/=10丢掉a的最后一位数字。
#include <stdio.h>

int main()
{
    int a;
    scanf("%d",&a);
    int d;
    int t = 0;
    do{
        d = a % 10;
        t = t *10 + d;
        a /= 10;
    }while(a > 0);
    printf("%d\n",t);
    a = t;
    while(a > 0){
        d = a % 10;
        printf("%d",d); 
        if(a >= 10){
            printf(" ",d);
        }
        a /= 10;
    }
    printf("\n");
    return 0;
}

152634 436251 1 5 2 6 3 4


Process exited after 3.839 seconds with return value 0

在第一个do-while循环后,a的值已经为0,需要将逆序后的t重新赋值给a才可以使得a继续参与下面的while循环(也可以使用t的值代替逆序前的a参与循环)。
::: tip
  do-while循环和while循环都可以使用。
**在选择循环类型时,如果循环有固定次数,使用for循环,如果循环必须进行一次,使用do while循环,其他情况都用while循环。**
:::
**上述程序只适用于末尾不为0的情况。**
#include <stdio.h>

int main()
{
    /*
    13524 / 10000 -> 1
    13524 % 10000 -> 3524 
    10000 / 10 -> 1000
    3524 / 1000 -> 3
    3524 % 1000 -> 524
    1000 / 10 -> 100
    524 / 100 -> 5
    524 % 100 -> 24
    100 / 10 -> 10
    24 / 10 -> 2
    24 % 10 -> 4
    10 / 10 -> 1
    4 / 1 -> 4
    4 % 1 -> 0
    1 / 10 -> 0
    */
    int mask = 10000;
    int a;
    scanf("%d",&a);
    do{
        int d = a / mask;
        printf("%d",d);
        a %= mask;
        mask /= 10;
        if(a > 0){
            printf(" ");
        }
    }while(mask > 0);
    printf("\n");
    return 0;
}

13524 1 3 5 2 4


Process exited after 2.08 seconds with return value 0

在程序中适当位置添加printf模拟debug:
#include <stdio.h>

int main()
{

    int mask = 10000;
    int a;
    scanf("%d",&a);
    do{
        int d = a / mask;
        a %= mask;
        mask /= 10;
        printf("a=%d d=%d mask=%d",a,d,mask);
        printf("\n");
    }while(mask > 0);
    return 0;
}

15243 a=5243 d=1 mask=1000 a=243 d=5 mask=100 a=43 d=2 mask=10 a=3 d=4 mask=1 a=0 d=3 mask=0


Process exited after 2.144 seconds with return value 0

使用边界值再次执行程序:

50000 50000


Process exited after 2.467 seconds with return value 0

输入50000后,发现程序没有正确执行,在第一次执行a%mask时,50000%10000->0,此时a=0,原因可能是条件出现了问题,改进如下:
#include <stdio.h>

int main()
{
    int mask = 10000;
    int a;
    scanf("%d",&a);
    do{
        int d = a / mask;
        printf("%d",d);
        a %= mask;
        mask /= 10;
        if(mask > 0){
            printf(" ");
        }
    }while(mask > 0);
    printf("\n");
    return 0;
}

50000 5 0 0 0 0


Process exited after 1.996 seconds with return value 0

上述程序的mask都是早已知数字位数后指定的,设计一个程序自动读取判断数字位数:

#include <stdio.h>

int main() { int mask =1; int a; scanf("%d",&a); do{ a /= 10; mask *= 10; } while(a > 0); printf("mask=%d",mask); return 0; }

15243 mask=100000


Process exited after 2.513 seconds with return value 0

mask多了一位,表明循环多进行了一轮,可以通过控制循环条件来控制循环次数:

#include <stdio.h>

int main() { int mask =1; int a; scanf("%d",&a); do{ a /= 10; mask *= 10; } while(a > 9); printf("mask=%d",mask); return 0; }

15243 mask=10000


Process exited after 1.781 seconds with return value 0

数字位数正确,使用边界值进一步验证:

5 mask=10


Process exited after 0.8986 seconds with return value 0

当数字位数为1时,mask值应为1。
分析原因:do-while循环不论输入数字位数都会先执行一轮循环语句mask*=10,使得输出mask值最小也是10,只需要将程序从do-while循环变为while循环就可以:

#include <stdio.h>

int main() { int mask =1; int a; scanf("%d",&a); while(a > 9){ a /= 10; mask *= 10; } printf("mask=%d",mask); return 0; }

15423 mask=10000


Process exited after 2.596 seconds with return value 0

5 mask=1


Process exited after 1.142 seconds with return value 0

把mask判断的程序加进原程序:

#include <stdio.h>

int main() { int mask =1; int a; scanf("%d",&a); while(a > 9){ a /= 10; mask *= 10; } printf("mask=%d\n",mask); do{ int d = a / mask; printf("%d",d); a %= mask; mask /= 10; if(mask > 0){ printf(" "); } }while(mask > 0); printf("\n"); return 0; }

15423 mask=10000 0 0 0 0 1


Process exited after 1.751 seconds with return value 0

发现原程序的运算结果不正确,原因是在判断mask的循环中,输出数字a已经被使用,无法再以输入大小进行后面的循环,需要引入一个新的变量保证输入数字a不受影响:

#include <stdio.h>

int main() { int mask =1; int a; int b; scanf("%d",&a); b = a; while(b > 9){ b /= 10; mask *= 10; } printf("mask=%d\n",mask); do{ int d = a / mask; printf("%d",d); a %= mask; mask /= 10; if(mask > 0){ printf(" "); } }while(mask > 0); printf("\n"); return 0; }

5 mask=1 5


Process exited after 3.5 seconds with return value 0

50000 mask=10000 5 0 0 0 0


Process exited after 1.901 seconds with return value 0

15423 mask=10000 1 5 4 2 3


Process exited after 2.847 seconds with return value 0

``` ::: warning 需要注意语句添加的位置,上述程序中b=a需要在scanf输入a的值后,否则会将a的初始值0赋给b,不会把a的输入值赋予b,后续循环中b的值会一直为0。 :::

评论区

索引目录