C语言循环结构细讲

Posted on 2019-07-07 19:31  不叫柒桓叶  阅读(1742)  评论(0编辑  收藏  举报

1.

y = 1+2+3+4+5...+100的值

 

int i = 1;//加数

int sum = 0;//

0 + 1 = 1

 

1 + 2 = 3;

 

1 + 2 + 3 = 6;

 

1 + 2 + 3 + 4 = 10;

。。。

 

 

sum = sum + i;

i++;

 

sum = sum + i;

i++;

 

sum = sum + i;

i++;

。。

 

=》循环结构

循环的本质就是重复

 

C语言中可以达到循环效果的语句

1goto语句与if构成的

2while

3do while

4for

 

1goto语句

goto  目标地点(在C语言中,某条指令的地址)

“指令地址” :语句标号 (它下面那条指令的地址)

 

“语句标号”:名字

语句标号前面只允许有空白字符

名字必须符合C语言中标识符的规定

 

loop:

i++;

 

 

goto loop;

 

语法形式:

goto 语句标号;

 

eg:

把求1~100的和用goto语句实现

int i = 1;//加数

int sum = 0;//

 

loop:

sum = sum+i;

i++;

 

if(i < 100)

{

goto loop;

}

 

 

注意:

主张限制使用goto语句

如果乱用goto语句,会使程序的可读性很差

 

 

(2)while循环

语法形式:

while(表达式)

循环体语句

 

“表达式”的值为真(非0),就执行“循环体语句”

然后,在判断“表达式”的值,如果为真(非0),就继续执行“循环体语句”

.....

 

直到“表达式”的值为假(0)为止(循环结束)

 

“表达式” :C语言中任意合法的表达式

 

“循环体语句”:

单语句 :只有有一个;语句

复合语句

{}/if/switch/for/while/do_while

 

eg:

while(i < 100)

{

i++;

sum = sum +i;

}

 

=>编程建议

不管while后面有没有语句,先打一对{}

表示他的“管辖范围”

 

练习:

输入一个整数,以逆序的顺序输出

12345

=>54321

 

n = 12345;

 

x = 12345%10

printf("%d",x);

 

....

step1:

求取个位数

 

step2:

打印

 

========

step1:

求取个位数

 

step2:

打印

 

step3:

把个位数拿到

 

while(n != 0)

{

//step1:求取个位数

x = n%10;

 

//step2:打印

printf("%d",x);

 

//step3:把个位数拿掉

n = n/10;

}

 

(3)do while

语法形式:

do

循环体语句

while(表达式);

 

先执行“循环体语句”,然后在判断“表达式”的值,

当表达式的值为真(非0),返回去执行上面的“循环体语句”,然后再一次

判断“表达式”的值,如果为真,返回去执行上面的“循环体语句”,

直到“表达式”的值为假(0),循环结束

 

“表达式” :C语言中任意合法的表达式

 

“循环体语句”:

单语句 :只有有一个;语句

复合语句

{}/if/switch/for/while/do_while

 

eg:

do

i++;

sum = sum+i;

while(I < 100);

 

这个代码是有语句错误

 

=>编程建议

不管do后面有没有语句,先打一对{}

表示他的“管辖范围”

 

do

{

循环体语句

}while(表达式);

 

练习:

n! (n由用户输入)

4

4*3*2*1

 

类乘

 

int i = 1;

int s = 1;

 

do

{

s = s*i;

i++;

}while(i <= n);

 

 

(4)for循环

语法形式:

for(表达式1;表达式2;表达式3)

循环体语句

 

先做“表达式1”(仅仅执行一次),然后再去判断“表达式2”的值

如果为真(非0),则执行“循环体语句”,

执行完“循环体语句”,在执行“表达式3

在判断“表达式2”的值,如果为真(非0),则执行“循环体语句”,

执行完“循环体语句”,在执行“表达式3

....如此重复

直到“表达式2”的值为假(0) 循环结束

 

“表达式1”,“表达式2”,“表达式3

任意C语言合法的表达式都可以

 

“表达式1” :一个循环只做一次,初始化条件,可一个,可多个,用逗号隔开

“表达式2”:判断表达式,它的值直接决定for循环是执行还是不执行

“表达式3”:改变循环条件的地方,每当循环体语句做完之后,执行表达式3

 

“表达式1”,“表达式2”,“表达式3”都可以为空

但是;一个都不能少

 

表达式2为空,则表示循环判断条件永远为真

 

for(;;)    while(1);

{

 

}

 

=>编程建议

不管for后面有没有语句,先打一对{}

表示他的“管辖范围”

 

 

练习:

1.求出所有的“水仙花数” 1.c

“水仙花数”是一个三位数,并且它的个,十,百位上的数字的立方和等于它本身

 

[100,999]

 

100 ?

if(0*0*0+0*0*0+1*1*1 == 100)

{

print 100

}

 

101 ?

if(1*1*1+0*0*0+1*1*1 == 101)

{

print 101

}

。。。。

999

 

num : [100,999]

x,y,z

if(x*x*x+y*y*y+z*z*z == num)

{

 

}

=============

 

for(num = 100;num<=999;num++)

{

//求取num的个,十,百

x=

y=

z=

if(x*x*x+y*y*y+z*z*z == num)

{

 

}

}

 

2.判断一个整数x,是否为质数(素数) 2.c

质数?

除了1和它本身以外没有其他的因数,这样的数就称为质数

 

6  :1 2 3 6

 

x

 

[2,x-1]

 

2 是不是x的因子

3 是不是x的因子

。。。

x-1 是不是x的因子

 

=>

for(i = 2;i < x;i++)

{

if(x % i == 0)//只要发现一个因子,不需要往下判断

{

printf("no\n");

break; //提前结束循环

}

}

if(i== x)

{

printf("yes\n");

}

 

一个循环结束有两种情况

1)判断条件满足

因为break跳出循环   =》提前结束 非正常死亡

2)判断条件不满足

“判断表达式”的值为0

 

 

(5)breakcontinue

break C语言中有两个作用

1breakswitch中,用来跳出它所属的switch语句

2break用在循环语句(while/do_while/for)中,用来跳出它所属的循环

 

for()

{

while()

{

if()

{

break;//跳出while

}

}

}

 

/*

test1.c: In function main:

test1.c:9:3: error: break statement not within loop or switch

break;

   ^

 

*/

if()

{

break;

} //有语法错误

 

 

continue

continue只能用于循环体内(while/do_while/for

用于提前执行下一次循环(结束本次循环,继续下一次循环)

 

作业:

1、求1000以内所有的“完数”

“完数”:如果一个数除了它本身以外其他因子之和等于其本身,这个数就是完数

 

6 1 2 3 6

 

m % n == 0;

=mn的倍数 ,nm的因子(因数)

 

num [1,1000]

int sum = 0;

for(num = 1;num <=1000;num++)

{

sum = 0;

//判断num是不是一个完数

 

for(x = 1; x <num;x++)

{

if(num % x == 0)

{

sum += x;

}

}

if(sum == num)

{

printf("%d\n",num);

}

}

 

2.求两个数(a,b)的最大公约数和最小公倍数

 

a % m == 0 =>am的倍数,ma的约数

b  % m == 0 =>bm的倍数,mb的约数

 

=>mab的公约数

 

15 45

 

算法一:

“穷举法”

 

a % x == 0 && b % x == 0

 

[1,min(a,b)] 区间里面找

 

找最大的公约数绝对不会大于min(a,b)

 

=> min = a <b ? a : b;

for(;min >0;min--)

{

if(a % min== 0 && b % min == 0)

{

min就是最大公约数

break;

}

}

 

======

算法二:

欧几里德算法

 

GCD(a,b)

假设a >= b

GCD(b,a mod b)

 

r = a mod b = a%b

证明

a,b的公约数集合 == b,a mod b的公约数的集合

 

A ==  B

AB的子集,BA的子集

 

AB的子集 :

GCD(a,b)

xGCD(a,b)中任意一个元素

a = K1 x (K1为整数)

b = K2 x (K2为整数)

 

r = a mod b

=>a = K*b +r (K为整数)

=> K1x = kK2x +r

=>r = (K1-KK2)x

=>xr的约数

xb的约数

x属于b,r的公约数 =x 属于 GCD(b,r)

 

GCD(15,10) => GCD(10,5) =>GCD(5,0)  =>5就是最大公约数

GCD(125,64) =>(64,61) =>(61,3) =>(3,1) =>(1,0) =>1

 

int a,b;

scanf("%d%d",&a,&b);

 

//确保 a>= b

 

 

while(a % b != 0)

{

r = a%b;

 

a = b;

b = r;

}

 

//最大公约数为a

 

优化:

while(b)

{

r = a%b;

 

a = b;

b = r;

}

 

 

3.连续的正整数之和。一个正整数有可能可以被表示为nn>=2)个连续的正整数之和

 

x = 15

15 = 1+2+3+4+5

15 = 4+5+6

15 = 7+8

 

 

"穷举法"

i :1~x/2

sum = i;

if(sum == x)

{

 

}

 

i++;

sum += i;

if(sum == x)

{

 

}

 

===========

int i,x,num,sum;

scanf("%d",&num);

 

for(i = 1;i < num/2+1;i++)

{

sum = i;

for(x = i+1;;x++)

{

sum += x;

if(sum == num)

{

//输出处理

 

break;

}

else if(sum > num)

{

break;

}

}

}

 

 

算法二:

[L,R]

sum = [l,r]区间各元素之和

 

1:从1开始   1+ 2 +3 + 4+5+6

 

if sum < num //往右边扩展区间

r++;

sum += r;

 

if sum >num//

sum -= l;

l++;

 

if sum == num //找到这个区间

//输出处理

r++;

sum += r;

 

15

 

1+2+3+4+5...15

 

4 +5 +6 +7

 

=====

for(l = 1,r = 1,sum = 1;l <= num/2;)

{

if(sum < num) //往右边扩展区间

{

r++;

sum += r;

}

else if(sum >num)//把区间最左边的那个数拿掉

{

sum -= l;

l++;

}

else

{

int i;

//输出处理

//15 = 1+2+3+4+5

printf("%d = ",num);

for(i = l;i<r;i++)

{

printf("%d+",i);

}

printf("%d\n",r);

 

r++;

sum += r;

}

 

}

 

Copyright © 2024 不叫柒桓叶
Powered by .NET 8.0 on Kubernetes