?一、循环控制
素数:只能被1和自己整除的数,不包括1。(2、3、5、7、11、13、17、19...)
写一个程序:读入一个用户输入的数x,然后判断这个数是不是素数。
思路:拿除1和它以外的数除它,若它能被那些数整除,那么他就不是素数,反之,则是素数。因为是在递增,所以用for循环(for循环适合:次数是确值的或范围是确值的)。??
#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 vs continue
break:跳出循环
continue:跳过循环这一轮剩下的语句进入下一轮。
二、多重循环
1.嵌套的循环:循环里面还是循环。
如何写程序输出100以内的素数?
思路:需要构造一个循环,循环可以让x从2走到100。用上一题的方法,让其进入循环体,来判断是否是素数,再输出。在循环体内,若是素数,则输出该素数,若不是则不用输出该数。
#include<stdio.h>
int main()
{
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",x);
}
}
printf("\n");
return 0;
}
嵌套的循环:循环里面还是循环。
输出前50个素数?
思路:用不了for循环(因为没有确切的范围和循环次数)。
需要一个计数器:int cnt=0;? 每次找到一个素数,需要计数器递增一次:cnt++;? ? 。
则循环条件就变成:只要计数器是小于50,那么继续做循环:while(cnt<50)? ?{? }? (相当于把for循环改成while循环,换了一个条件)x初始值为应2,并且有x++;? ? ? ?。
用for循环也可以:for(x=2;cnt<50;x++)? {? }
#include<stdio.h>
int main()
{
int x;
x=2;
int cnt=0;
//for(x=2;x<100;x++)
while(cnt<50)
{
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 ++;
}
x++;
}
printf("\n");
return 0;
}
用for循环也可以:for(x=2;cnt<50;x++)? ? {? }
#include<stdio.h>
int main()
{
int x;
x=2;
int cnt=0;
//for(x=2;x<100;x++)
//while(cnt<50)
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);
cnt ++;
}
//x++;
}
printf("\n");
return 0;
}
2.从嵌套的循环中跳出:break只能对它所在的那层循环做。
凑硬币:
如何用1角、2角和5角的硬币凑出10元以下的金额呢?
程序如下:
#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角加%个2角加个5角得到元\n",one,two,five,x);
}//if
}//five
}//two
}//one
return 0;
}
若想要找到第一组能凑出金额的后就退出
程序的思路如下:
错误情况①:不可以只在一个循环语句后面单独的加一个break,因为break只能对它所在的那层循环做。
错误情况②:不可以简单的在每个循环语句后面放break,则无论是什么样的情况离开这个for循环,那么这个break总会跳出外面的一层for循环。应该是,当某种条件下,当这个break发生时,下面的break才会发生,下下面的break才会发生。
那么如何做到,当某种条件下,完成这一系列的事情呢?(用if)。
需要用到一个变量:? ①int exit=0;? ?②在第一个break做之前:break=1;? ?③第二、三个break做的条件为:if(exit==1)break;(即:如果exit==1的话,那么就break)。
此方法为:接力break(①:需要一个变量来表达这个事情。②:当我们要break的时候,让该变量等于1。③:在循环外面判断该变量是否等于1,来接力break。④:再接力break,使得从循环中跳出来。)
break和continue:都只能对它所在的那层循环做。
错误情况①:不可以只在一个循环语句后面单独的加一个break,因为break只能对它所在的那层循环做。
#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角加%个2角加个5角得到元\n",one,two,five,x);
break;//(不可以在这里只单独的加一个break,因为break只能对它所在的那层循环做.)
}//if
}//five
}//two
}//one
return 0;
}
错误情况②:?不可以简单的在每个循环语句后面放break,则无论是什么样的情况离开这个for循环,那么这个break总会跳出外面的一层for循环。应该是,当某种条件下,当这个break发生时,下面的break才会发生,下下面的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角加%个2角加个5角得到元\n",one,two,five,x);
break;//(不可以直接简单的加break;)
}//if
}//five
break;//(不可以直接简单的加break;)
}//two
break;//(不可以直接简单的加break;)
}//one
return 0;
}
正确方式:
那么如何做到,当某种条件下,完成这一系列的事情呢?(用if)。
需要用到一个变量:? ①int exit=0;? ?②在第一个break做之前:break=1;? ?③第二、三个break做的条件为:if(exit==1)break;(即:如果exit==1的话,那么就break)。
此方法为:接力break(①:需要一个变量来表达这个事情。②:当我们要break的时候,让该变量等于1。③:在循环外面判断该变量是否等于1,来接力break。④:再接力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角加%个2角加个5角得到元\n",one,two,five,x);
//(不可以在这里只单独的加一个break,因为break只能对它所在的那层循环做。)
//(不可以直接简单的加break;)
exit=1;//*
break;
}//if
}//five
//(不可以直接简单的加break;)
if(exit==1)break;//*
}//two
//(不可以直接简单的加break;)
if(exit==1)break;//*
}//one
return 0;
}
?方法2:
当然,也可以使用goto的方式
goto out;? ? ? ?out:
在需要离开循环的地方,放入goto语句。、
goto语句后面需要有标号,这个标号是在程序中自己写的,(如goto out;? ? ?out:? ? ? )goto要跳到out所指的地方去。
在需要从多层循环、嵌套的循环的内层,跳到最外面的时候,可以使用goto。
#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角加%个2角加个5角得到元\n",one,two,five,x);
goto out;//*
}//if
}//five
}//two
}//one
out://*
return 0;
}
三、循环应用?
1.求和
/1:求f(n)=1+?+?+?+...+1/n
思路:用for循环(因为起点1,终点n,范围明确)注意浮点数。
#include<stdio.h>
int main()
{
int n;
int i;
double sum=0.0;// 1除以i的值带有小数点
scanf("%d",&n);
for(i=1;i<=n;i++)
{
sum+=1.0/i;// 1除以i,i一定比1大,在除号的两边有一个是浮点数,那么另一个就会是浮点数,结果就会是浮点数的运算结果。
}
printf("f(%d)=%f\n",n,sum);
return 0;
}
/2:求f(n)=1-?+?-?+...+1/n
思路:和上一题思路一样,用for循环(因为起点1,终点n,范围明确)注意浮点数。只是多了一个正负号的变化,可以另设一个变量,来做符号的变化。
#include<stdio.h>
int main()
{
int n;
int i;
double sum=0.0;
int sign=1;//方法2:double sign=1.0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
sum+=sign*1.0/i;//方法2:sum+=sign/i;
sign=-sign;//方法2:sign=-sign;相当于用分子在来变换正负。
}
printf("f(%d)=%f\n",n,sum);
return 0;
}
2.求最大公约数
输入两个数a和b。输出它们的最大公约数:输入12 18;输出:6。
思路:1.枚举法(效率不高)? ?2.辗转相除法?
1)枚举法?
int a,b;
int min;
scanf("%d %d",&a,&b);
if(a<b)
{min=0;}
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);
2)辗转相除法?
1)如果b等于0,计算结束,a就是最大公约数;
2)否则,计算a除以b的余数,让a等于b,而b等于那个余数;
3)回到第一步
若求12与18的最大公约数:输入12 18;输出:6。
a? ? ? ? ? b? ? ? ? ? t(余数)
12? ? ? ?18? ? ? ? ?12
18? ? ?? 12? ? ? ? ? 6
12? ? ? ? 6? ? ? ? ? ?0
?6? ? ? ? ?0
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);
3.整数分解?
正序分解整数
输入一个非负整数,正序输出它的每一位数字。输入:13425;输出:1 3 4 2 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");
(这个对我来说有点绕T^T)
|