零基础学C语言(5):循环控制的应用案例

素数

只能被1和自己整除的数,不包括1, 如2,3,5,7,11,13,15,17,19…

#include <stdio.h>

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


break:跳出循环
continue:跳过循环这一轮剩下的语句进入下一轮,可以使用断点-调试-下一步来看。

#include <stdio.h>

int main()
{
	int x;
	
	//scanf("%d",&x);
	x=9;
	int i;
	int isPrime = 1; //x是素数
	for (i=2;i<x;i++){
		if(x%i==0){
			isPrime = 0;
			continue;
		}
		printf("%d\n",i);
	} 
	if (isPrime == 1){
		printf("是素数\n");
	}	else{
		printf("不是素数\n");
	}
	return 0;
}


也可以不用isPrime变量,循环结束后,i=x就是素数,i<x就不是素数。但不可取,在没有显著提升程序运行效率的同时让程序变得不易理解。

输出100以内的素数

前面是给定一个数,判断是不是素数。现在需要输出100以内的所有素数。

嵌套的循环

#include <stdio.h>

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

	for (x=2;x<100;x++)
	{
		int i;
		int isPrime = 1; //x是素数
		for (i=2;i<x;i++){
			if(x%i==0){
				isPrime = 0;
				break;
			}
		} 
		if (isPrime == 1){
			printf("%d ",x);
		}
	}
	printf("\n");
	
	return 0;
}


2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

输出前50个素数

那么for循环就不合适了,只适用于次数或范围是确定值的。
需要计数器,找到一个素数就要记一个,只要计数器小于50,就要继续循环。

#include <stdio.h>

int main()
{
	int x;
	
	//scanf("%d",&x);
	x = 2;
	int cnt =0; //计数器 

	while (cnt<50)
	//for (x=2;x<1000;x++)
	{
		int i;
		int isPrime = 1; //x是素数
		for (i=2;i<x;i++){
			if(x%i==0){
				isPrime = 0;
				break;
			}
		} 
		if (isPrime == 1){
			printf("%d ",x);
			cnt ++; //找到素数计数器 +1
		}
		x++;
		//for语句省略x++; 
	}
	printf("\n");
	
	return 0;
}
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 101 103 107 109 113 127 131 137 139 149 151 157 163 167 173 179 181 191 193 197 199 211 223 227 229

多重循环

凑硬币

如何用1角、2角和5角的硬币凑出I0元以下的金额呢?——枚举

#include <stdio.h>

int main()
{
	int x;
	int one,two,five;
	
	//scanf("%d",&x);
	x = 2;
	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个1角加2个2角加3个5角得到2元
可以用1个1角加7个2角加1个5角得到2元
可以用2个1角加4个2角加2个5角得到2元
可以用3个1角加1个2角加3个5角得到2元
可以用3个1角加6个2角加1个5角得到2元
可以用4个1角加3个2角加2个5角得到2元
可以用5个1角加5个2角加1个5角得到2元
可以用6个1角加2个2角加2个5角得到2元
可以用7个1角加4个2角加1个5角得到2元
可以用8个1角加1个2角加2个5角得到2元
可以用9个1角加3个2角加1个5角得到2元
可以用11个1角加2个2角加1个5角得到2元
可以用13个1角加1个2角加1个5角得到2元

break和continue只能对它所在的那层循环做。

那如何跳出多重循环?

凑硬币题目中,就是给出一个答案就跳出循环。

法一:通过设置exit接力break

#include <stdio.h>

int main()
{
	int x;
	int one,two,five;
	int exit = 0; 
	//scanf("%d",&x);
	x = 2;
	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;
}
可以用11角加22角加35角得到2

法二: goto语句

使用gotoout语句,并设置要跳出的out地方。(建议只在最内层跳到最外层的时候使用)

#include <stdio.h>

int main()
{
	int x;
	int one,two,five;
	
	//scanf("%d",&x);
	x = 2;
	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个1角加2个2角加3个5角得到2元

循环应用

求和1+1/2+1/3+1/4+…+1/n.

起始值1,终点值n,均明确,所以用for循环是最好的。

#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;
}
10
f(10)=2.928968

求和1-1/2+1/3-1/4+…+1/n.

引入sign=1.0,再通过sign=-sign来翻转正负号。

#include <stdio.h>

int main()
{
	int n;
	int i;
	double sum = 0.0;
	//int sign=1;
	double sign=1.0;
	
	scanf("%d",&n);
	for (i=1; i<=n; i++){
		sum += sign/i;
		sign = -sign;
	}
	
	printf("f(%d)=%f\n",n,sum);
	
	return 0;
}

求最大公约数

输入两个数a和b,输出它们的最大公约数。
例:输入12和18,输出6。

法一:枚举法

法二:辗转相除法

1.如果b等于0,计算结束,a就是最大公约数;
2.否则,计算a除以b的余数,让a等于b,而b等于那个余数;
3.回到第一步。

#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;
	}
	printf("gcd=%d\n",a);
	return 0;
}

12和18的最大公约数是6.

12 18
gcd=6

正序分解整数

  • 输入一个非负整数,正序输出它的每一位数字
  • 输入:13425
  • 输出:1,3,4,2,5
#include <stdio.h>

int main()
{
	int x;
	
	//scanf("%d",&x);
	x = 13425;
	do{
		int d = x % 10;
		printf("%d ",d);
		x /= 10;
	} while( x > 0 );
	printf("\n");
	
	return 0;
}
5 2 4 3 1

解决最后一位多个空格的问题

#include <stdio.h>

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

先循环得出逆整数,把x最右边那位加到t

#include <stdio.h>

int main()
{
	int x;
	
	//scanf("%d",&x);
	x = 13425;
	int t = 0;
	do{
		int d = x%10;
		t = t*10+d;
		x/=10;
	} while(x>0);
	printf("x=%d,t=%d\n",x,t);
	x=t;
	do{
		int d = x % 10;
		printf("%d ",d);
		if ( x >= 10) {
			printf(" ");
		} 
		x /= 10;
	} while( x > 0 );
	printf("\n");
	
	return 0;
}
x=0,t=52431
1  3  4  2  5

但这种做法,对于末尾有0的数字不行,例如700,会输出7而不是007。

x=0,t=7
7

回想前面三位数求逆序,最高位是用x/100得到的。

#include <stdio.h>

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

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

	printf("\n");
	
	return 0;
}

输出

1 x=3425,mask=1000,d=1
3 x=425,mask=100,d=3
4 x=25,mask=10,d=4
2 x=5,mask=1,d=2
5 x=0,mask=0,d=5

输入70000怎么办?输出还是7!

第一轮x就等于0了,但mask还不是0,所以应该是mask为0。而且mask不应该是固定的,对于3位数应该是100,4位数应该是1000,所以要先计算整数的位数cnt然后用pow函数,也可以把mask从1开始乘10。

#include <stdio.h>

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

	printf("\n");
	
	return 0;
}

但也有问题,输入x=1的时候,我们希望我们的mask是1而不是10,因为我们用了do-while,个位数都乘了,所以换成while。

#include <stdio.h>

int main()
{
	int x;
	
	//scanf("%d",&x);
	x = 1;
	int mask = 1;
	int t=x; //存放初始x,防止x变掉了。 
	while (x>9){
		x/=10;
		mask *=10;
	}
	printf("x=%d,mask=%d\n",mask);
	
	do {
		int d = x / mask;
		printf("%d",d);
		if (mask>9){
			printf(" ");
		}
		x %= mask;
		mask /=10;
	}while(mask>0);	

	printf("\n");
	
	return 0;
}

更多推荐

零基础学浙大翁恺C语言(5):循环控制