程序设计入门——C语言(翁凯版)第五周

5.1 循环控制

5.1.1 循环控制

写一段程序判断一个数是不是素数

int x;

scanf("%d", &x);

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

return 0;

程序可以正确判断一个数是否是素数。但是存在问题。假设输入的x是6,当i=2时,6%2=0,已经可以判断6不是素数,但是循环还会继续进行下去,直到i=6结束循环,所以可以对程序做出改动,增添一个break。

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:跳过循环这一轮剩下的语句进入下一轮。
    程序设计入门——C语言(翁凯版)第五周_第1张图片
    还有一种方法
int x;

scanf("%d", &x);

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

return 0;

程序可以正确判断一个数是否是素数。但是存在问题。假设输入的x是6,当i=2时,6%2=0,已经可以判断6不是素数,但是循环还会继续进行下去,直到i=6结束循环,所以可以对程序做出改动,增添一个break。

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){
if(i<x){
	printf("不是素数\n");
}else{
	printf("是素数\n");
}

return 0;

这种方法是有害的(?)

5.2 多重循环

5.2.1 嵌套循环

写一段程序,输出100以内的素数

int x;

scanf("%d", &x);

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

return 0;

程序可以正确判断一个数是否是素数。但是存在问题。假设输入的x是6,当i=2时,6%2=0,已经可以判断6不是素数,但是循环还会继续进行下去,直到i=6结束循环,所以可以对程序做出改动,增添一个break。

int 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\n", x);
	}
}
printf("\")
return 0;

在这段程序中, 循环中出现了循环。要注意的是,外层循环和内层循环的变量不要搞混。
再写一段程序可以输出前50个素数。

int x;

int x=2;
int cnt=50;
//while(cnt<50)
for(x=2;cnt<50;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\n", x);
		cnt++;
	}
	//x++;
}
printf("\n")
return 0;

5.2.2 跳出嵌套循环

用代码求出如何用一角、两角和五角硬币凑成十元以下的金额。

	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个一角加%d个两角加%d个五角得到%d元\n",
					one, two, five, x);
				}
			}
		}
	}

输出

2
可以用1个一角加2个两角加3个五角得到2元
可以用1个一角加7个两角加1个五角得到2元
可以用2个一角加4个两角加2个五角得到2元
可以用3个一角加1个两角加3个五角得到2元
可以用3个一角加6个两角加1个五角得到2元
可以用4个一角加3个两角加2个五角得到2元
可以用5个一角加5个两角加1个五角得到2元
可以用6个一角加2个两角加2个五角得到2元
可以用7个一角加4个两角加1个五角得到2元
可以用8个一角加1个两角加2个五角得到2元
可以用9个一角加3个两角加1个五角得到2元
可以用11个一角加2个两角加1个五角得到2元
可以用13个一角加1个两角加1个五角得到2

如果我们想得到一个结果就足够,那么该如何修改代码呢?
如果这样修改

	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个一角加%d个两角加%d个五角得到%d元\n",
					one, two, five, x);
					break;
				}
			}
		}
	}

这样得到的结果和上一条一样。因为当进入第三层循环后break会跳出第三层循环,进行下一次第二层循环,而即使第三层循环执行到底也不会有多余的输出,因为前两层一定固定第三层如果有解一定唯一,所以直接进行下一次二层循环不会漏解。

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

这样修改呢?

	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个一角加%d个两角加%d个五角得到%d元\n",
					one, two, five, x);
					break;
				}
			}
			break;
		}
		break;
	}

这样也不行,因为这样就会导致不论以怎样的方式跳出第三层循环,第二层第一层都会依次跳出。
正确的代码是这样的

	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个一角加%d个两角加%d个五角得到%d元\n",
					one, two, five, x);
					exit=1;
					break;
				}
			}
			if(exit==1) break;
		}
		if (exit==1 )break;
	}

这种情况叫做接力break。
还有另一种正确的方式

	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个一角加%d个两角加%d个五角得到%d元\n",
					one, two, five, x);
					goto out;
				}
			}
		}
	}
out:

goto一般只用在跳出多层循环的情况,它被认为会破坏程序的结构性。

5.3 循环应用

5.3.1 前n项求和

求和1+1/2+1/3+···1/n

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, sum);

求和1-1/2-1/3+···1/n

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

5.3.2 求最大公约数

输入两个数a和b,输出最大公约数
算法一:枚举

  1. 设t=2;
  2. 如果u和v都能被t整除,则记下这个t;
  3. t加1后重复第2步,直到t等于u或v;
  4. 曾经记下最大的可以同时整除u和v的t就是最大公约数。

代码如下

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);

算法二:辗转相除法

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

代码如下

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);

5.3.3 整数分解

输入一个非负整数,正序输出它的每一位数字
例:

  • 输入:12345
  • 输出:1 2 3 4 5

代码如下

Int x;
scanf("%d", &x);

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

你可能感兴趣的:(c语言,算法,开发语言)