第五课

for循环

1.阶乘

n!=1×2×3×4×5×…×n

输入n,输出n!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main()
{
int n;

scanf("%d", &n);
int fact = 1;

int i = 1;
while ( i<= n) {
fact *= i;
i++;
}

printf("%d!=%d\n", n, fact);

return 0;
}

等同于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

int main()
{
int n;

scanf("%d", &n);
int fact = 1;

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

printf("%d!=%d\n", n, fact);

return 0;
}

正着来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

int main()
{
int n;

scanf("%d", &n);
int fact = 1;

int i = 1;
for ( i=n; i>1; i-- ) {
fact *= i;
}

printf("%d!=%d\n", n, fact);

return 0;
}

反着来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

int main()
{
int n;

scanf("%d", &n);
int fact = 1;

int i = n;
for ( n=n; i>1; i-- ) {
fact *= n;
}

printf("%d!=%d\n", i, fact);

return 0;
}

for ( i=1; i<=n; i++ )

三个表达式:

①初始条件

②循环继续的条件

③循环每一轮要做的事情

for循环像一个计数循环,设定一个计数器,初始化它,然后在计数器到达某值之前,重复执行循环体,而每执行一轮循环,计数器值以一定步进进行调整,比如加1或者减1

结构

1
2
3
for ( i=a; i<b; i = i+c ) {
printf("%d", i)
}

读成:对于一开始的i=a,当i<b时,重复做循环体,每一轮循环在做完循环体内语句后,使得i=i+c。

※做求和的程序时,记录结果的变量应该初始化为0,而做求积的变量时,记录结果的变量应该初始化为1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

int main()
{
int n;

scanf("%d", &n);
int fact = 1;

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

printf("%d!=%d\n", n, fact);

return 0;
}

(只能在C99里)

2.循环次数

for ( i=0; i<n; i++ )

则循环的次数是n,而循环结束以后,i的值是n。循环的控制变量i,是选择从0开始还是从1开始,是判断i<n还是判断i<=n,对循环的次数,循环结束后变量的值都有影响。

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

int main()
{
int 1;

for ( i=0; i<n; i++ ) {
printf("i=%d", i);
}
printf("\n最后i=%d", i);

return 0;
}

输出:

i=0 i=1 i=2 i=3 i=4 … i=n-1

最后i=n

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

int main()
{
int 1;

for ( i=1; i<=n; i++ ) {
printf("i=%d", i);
}
printf("\n最后i=%d", i);

return 0;
}

输出:

i=1 i=2 i=3 i=4 … i=n

最后i=n+1

for==while

1
2
3
for ( int i=1; i<=n; i++ ) {
fact *= i;
}

等同于

1
2
3
4
5
int i=1;
while ( i<=n ) {
fact *= i;
i++;
}

任何一个for循环都可以改写成一个while循环

1
2
3
for (初始动作; 条件; 每轮的动作) {

}

for (;条件;) == while (条件)

①如果有固定次数,用for

②如果必须执行一次,用do-while

③其他情况用while

二、循环控制

1.素数

只能被1和自己整除的数,不包括1的数是素数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>

int main()
{
int x;

scanf("%d", &x);

int i;
int isPrime = 1;
for ( i=2; i<x; i++ ) {
if ( x % i == 0 ) {
isPrime = 0;
break;
}
}
if ( isPrime == 1 ) {
printf("是素数\n");
} else {
printf("不是素数\n");
}

return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

int main()
{
int x;

scanf("%d", &x);

int i;
int isPrime = 1;
for ( i=2; i<x; i++ ) {
if ( x % i == 0 ) {
break;
}
}
if ( i < x ) {
printf("不是素数\n");
} else {
printf("是素数\n");
}

return 0;
}

break:跳出循环

continue:跳过循环这一轮剩下的语句进入下一轮

2.循环的嵌套

循环里面的还是循环

n以内的素数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>

int main()
{
int x;

for ( x=1; x<=n; x++ ) {
int i;
int isPrime = 1;
for ( i=2; i<x; i++ ) {
if ( x % i == 0 ) {
isPrime = 0;
break;
}
}
if ( isPrime == 1 ) {
printf("%d ", x);
}
}

return 0;
}

前n的素数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>

int main()
{
int x;
int cnt = 0;

for ( x=1; cnt<n; x++ ) {
int i;
int isPrime = 1;
for ( i=2; i<x; i++ ) {
if ( x % i == 0 ) {
isPrime = 0;
break;
}
}
if ( isPrime == 1 ) {
cnt ++;
printf("%d ", x);
}
}

return 0;
}

等同于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>

int main()
{
int x;
int cnt = 0;

x = 1;
while ( cnt < 50 ) {
int i;
int isPrime = 1;
for ( i=2; i<x; i++ ) {
if ( x % i == 0 ) {
isPrime = 0;
break;
}
}
if ( isPrime == 1 ) {
cnt ++;
printf("%d ", x);
}
x++;
}

return 0;
}

排一排不舒服

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>

int main()
{
int x;
int cnt = 0;

x = 1;
while ( cnt < 50 ) {
int i;
int isPrime = 1;
for ( i=2; i<x; i++ ) {
if ( x % i == 0 ) {
isPrime = 0;
break;
}
}
if ( isPrime == 1 ) {
cnt ++;
printf("%d ", x);
if ( cnt %5 == 0 ) {
printf("\n");
}
}
x++;
}

return 0;
}

每5个一行

没对齐不舒服

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <stdio.h>

int main()
{
int x;
int cnt = 0;

x = 1;
while ( cnt < 50 ) {
int i;
int isPrime = 1;
for ( i=2; i<x; i++ ) {
if ( x % i == 0 ) {
isPrime = 0;
break;
}
}
if ( isPrime == 1 ) {
cnt ++;
printf("%d\t", x);
if ( cnt %5 == 0 ) {
printf("\n");
}
}
x++;
}

return 0;
}

对齐

3.从嵌套循环跳出

凑硬币

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>

int main()
{
int x;
int one, two, five;

scanf("%d", &x);
for ( one = 1; one < x*10; one++ ) {
for ( two = 1; two < x*10/2; two++ ) {
for ( five = 1; five < x*10/5; five++ ) {
if( one + two*2 + five*5 == x*10 ) {
printf("可以用%d个1角加%d个2角加%d个5角得到%d元\n", one, two, five, x);
}
}
}
}

return 0;
}

得到一种结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>

int main()
{
int x;
int one, two, five;
int exit = 0;

scanf("%d", &x);
for ( one = 1; one < x*10; one++ ) {
for ( two = 1; two < x*10/2; two++ ) {
for ( five = 1; five < x*10/5; five++ ) {
if( one + two*2 + five*5 == x*10 ) {
printf("可以用%d个1角加%d个2角加%d个5角得到%d元\n", one, two, five, x);
exit = 1;
break;
}
}
if ( exit == 1 ) break;
}
if ( exit == 1 ) break;
}

return 0;
}

等同于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>

int main()
{
int x;
int one, two, five;

scanf("%d", &x);
for ( one = 1; one < x*10; one++ ) {
for ( two = 1; two < x*10/2; two++ ) {
for ( five = 1; five < x*10/5; five++ ) {
if( one + two*2 + five*5 == x*10 ) {
printf("可以用%d个1角加%d个2角加%d个5角得到%d元\n", one, two, five, x);
goto out;

}
}
}
}
out:

return 0;
}

三、应用

1.前n项求和

f(n) = 1+1/2+1/3+1/4+…+1/n

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main()
{
int n;
int i;
double sum = 0.0;

scanf("%d", &n);
for ( i = 1; i<=n; i++ ) {
sum += 1.0/i;
}

printf("f(%d)=%f\n", n, sum);

return 0;
}

f(n) = 1-1/2+1/3-1/4+…+1/n

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main()
{
int n;
int i;
double sum = 0.0;
int sign = 1;

scanf("%d", &n);
for ( i = 1; i<=n; i++ ) {
sum += sign*1.0/i;
sign = -sign;
}

printf("f(%d)=%f\n", n, sum);

return 0;
}

或者

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main()
{
int n;
int i;
double sum = 0.0;
double sign = 1;

scanf("%d", &n);
for ( i = 1; i<=n; i++ ) {
sum += sign/i;
sign = -sign;
}

printf("f(%d)=%f\n", n, sum);

return 0;
}

2.最大公约数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>

int main()
{
int a,b;
int min;

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

return 0;
}

等同于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
int main()
{
int a,b;
int t;
scanf("%d %d", &a, &b);

while ( b!=0 ) {
t = a%b;
a=b;
b=t;
}
print("gcd=%d\n", a);

return 0;
}

3.整数分解

反向输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main()
{
int x;
scanf("%d", &x);

do {
int d = x % 10;
printf("%d", d);
if ( x > 9 ) {
printf(" ");
}
x /= 10;
} while ( x > 0 );
printf("\n");

return 0;
}

正向输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>

int main()
{
int x;
scanf("%d", &x);

int t=0;
do {
int d = x%10;
t = t*10+d;
x /= 10;
} while ( x>0 );
x = t;
do {
int d = x % 10;
printf("%d", d);
if ( x > 9 ) {
printf(" ");
}
x /= 10;
} while ( x > 0 );
printf("\n");

return 0;
}

(末尾不能有0)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include <stdio.h>

int main()
{
int x;
scanf("%d", &x);

int cnt = 0;
int mask = 1;
while ( x>9 ) {
x/=10;
mask *= 10;
}

do {
int d = x / mask;
printf("%d", d);
if ( mask > 9 ) {
printf(" ");
}
x %= mask;
mask /= 10;
} while ( mask>0 );

printf("\n");

return 0;
}

(末尾为0)