循环结构:
通过反复多次执行某一段代码,达到解决问题的目的。
循环语句:
do while 先执行循环体,后判断循环条件,循环体至少执行一次,相同条件下do while会比for和while多执行一次循环体。
for、while 先判断循环条件,再执行循环体,循环体可能一次都不执行。
for 适合解决循环次数确定的问题,可以使用循环变量清楚表示循环的次数。
while 适合解决只知道循环条件但不知道具体循环次数的问题(开始条件、结束条件)。
do while 适合解决 先处理 后检查的问题。
for、while 的小括号后面不能跟分号,否则下面的代码就不属于它们的循环体。
do while 的小括号后面必须有分号,它的这个特点适合定义宏函数。
for循环语句:
for([1]; [2]; [3];)
{
[4];
}
执行流程:
模块1:为for循环做好准备工作,只执行一次。
模块2:判断执行条件,条件为真时执行4,为假时结束。
模块4:被反复多次执行的代码,也叫循环体。
模块3:改变循环条件,防止变成死循环。
1 2 4 3 2 4 3 2 4 3 ... 2
由于for非常灵活所以一般使用个循环变量(index->i)来引导它的运行:
顺序:
模块1:为循环变量赋值初值,在C99语法标准中才可以在此处定义变量,我们ubuntu系统默认使用的是C99标准,dev开发环境默认的是C89,在此处理定义的变量只能在for循环内存使用。
模块2:检查循环变量的值,是否到达边界。
模块4:执行循环体。
模块3:循环变量加1或减1。
for(int i=0; i<10; i++)
{
printf("%d\n",i);
}
练习1:输入一个整数,判断是否是完美数=因子之和,例如:6=1+2+3。
#include <stdio.h>
int main(int argc,const char* argv[])
{
int num , sum = 0;
printf("请输入一个整数:");
scanf("%d",&num);
for(int i=1; i<num; i++)
{
if(0 == num%i)
{
sum += i;
}
}
if(sum == num)
{
printf("是完美数\n");
}
else
{
printf("不是完美数\n");
}
return 0;
}
练习2:输入一个年份,计算该年到2022年之间有多个闰年。
#include <stdio.h>
int main(int argc,const char* argv[])
{
short year1 = 2022 , year2 , cnt = 0;
printf("请输入一个年份:");
scanf("%hd",&year2);
if(year2 < year1)
{
year1 = year2;
year2 = 2022;
}
for(int i=year1; i<=year2; i++)
{
cnt += 0==i%4 && 0!=i%100 || 0==i%400;
}
printf("%hd年到%hd年之间一共有%hd个闰年\n",year1,year2,cnt);
return 0;
}
for循环的特殊写法:
for(;;) // 死循环
{
}
--------------------------------
int i=0;
for(; i<10; i++)
{
}
--------------------------------
int i=0;
for(;i<10;)
{
i++;
}
while循环语句:
while(条件)
{
// 循环体
}
执行流程:先判断条件,当条件为真时执行循环体,条件为假时结束while循环。
它与省略的[1][3]部分的for语句功能一样,可以看作是精简版的for语句。
for语句用于解决循环次确定的问题,while用于解决只知道循环条件但不知道具体循环次数的问题。
练习3:输入一个正整数倒序显示,例如:输入1234,显示4321。
#include <stdio.h>
int main(int argc,const char* argv[])
{
long long num;
printf("请输入一个正整数:");
scanf("%lld",&num);
while(num)
{
printf("%lld",num%10);
num /= 10;
}
return 0;
}
练习4:假如小明买了10万元的股票,股市大跌亏的还剩2万元,如果接下来股市好转,每个交易日上涨一个百分点,多少天以后小明能回本。
#include <stdio.h>
int main(int argc,const char* argv[])
{
int day = 0;
float capital = 20000;
while(capital < 100000)
{
capital = capital + capital/100;
day++;
}
printf("小明在%d个交易日后可以回本\n",day);
return 0;
}
do while循环语句:
do{
// 循环体
}while(条件);
执行流程:先执行循环体,再判断循环条件,条件为真时继续执行循环休,条件为假时结束do while循环(先干活后检查)。
与for和while相比,do while会至少执行一次循环体,而for和while可能一次都不执行,相同条件下do while会比它们多执行一次循环体。
int i;
do{
// 在此处定义的变量出了大括号就不能使用
}while(i<10);
练习5:密码验证(123466):
1、当输入正确密码时,显示登录成功。
2、密码错误时,显示还有多少次机会。
3、密码错误超过三次,显示帐号锁定。
#include <stdio.h>
int main(int argc,const char* argv[])
{
int passwd,cnt = 0;
printf("请输入密码:");
do{
if(cnt > 0)
printf("密码错误,请重新输入(你还有%d次机会):",3-cnt);
scanf("%d",&passwd);
}while(++cnt<3 && 123466!=passwd);
if(123466!=passwd)
printf("账号锁定!\n");
else
printf("登录成功!\n");
return 0;
}
break语句:
功能1:在switch语句使用,可以关闭执行开关。
功能2:在循环语句使用,可以跳出循环语句,但只能跳一层,它是解决死循环的方法之一。
int i = 0;
for(;;)
{
printf("%d\n",i++);
if(i>=10)
break;
}
printf("循环结束了!");
continue语句:
只能在循环语句中使用,它可以提前结束本次循环,执行一次循环。
continue是用于终止本次循环的,也就是本次循环中continue后边的代码都不会再执行,而是直接跳转到while语句的判断部分,进行下一次循环的入口判断。
for(int i=0; i<10; i++)
{
if(i%2)
continue;
printf("i=%d\n",i);
}
goto语句:
它能跳转到函数内的任意位置,但只能在函数内跳转,既能向上跳转也能向下跳转,它通过标签来确定代码的位置。
定义标签的方法:
标签名: // 标签的取名规则与变量一样
跳转方法:
goto 标签名;
// 向上跳转可以构成死循环
int i = 0;
loop:
printf("%d\n",i++);
goto loop;
// 循环10次,用goto构成的循环体不能使用break和continue
int i = 0;
loop:
printf("%d\n",i++);
if(i<10)
goto loop;
// 可以向下跳转,让某些代码不执行
goto l3;
l1:
printf("----------1\n");
l2:
printf("----------2\n");
l3:
printf("----------3\n");
l4:
printf("----------4\n");
l5:
printf("----------5\n");
注意:goto语句过度自由,可能会破坏设计好的分支、开关、循环等语句,很多编程语言去掉了goto语句,很多使用C语言开发的公司禁止使用goto语句,C语言中之所以还保留着是因为它在驱动开发中非常适合用来处理异常、释放资源。
循环嵌套:
就是在循环语句中包含循环语句,外层循环执行一次,内层循环执行一遍。
for(int i=0; i<10; i++)
{
for(int j=0; j<10; j++)
{
printf("j");
}
printf("i\n");
}
// 还可以让外层循环控制内存循环执行的次数
for(int i=0; i<10; i++)
{
for(int j=i; j<10; j++)
{
printf("j");
}
printf("i\n");
}
for(int i=0; i<10; i++)
{
for(int j=0; j<=i; j++)
{
printf("j");
}
printf("i\n");
}
练习6、打印九九乘法表。
#include <stdio.h>
int main(int argc,const char* argv[])
{
for(int i=1; i<10; i++)
{
for(int j=1; j<=i; j++)
{
printf("%d*%d=%2d ",j,i,i*j);
}
printf("\n");
}
return 0;
}
练习7、计算出[n,m]范围内所有的完美数。
#include <stdio.h>
int main(int argc,const char* argv[])
{
int n,m;
printf("请输入一个范围:");
scanf("%d%d",&n,&m);
printf("[%d,%d]范围内的完美数有:",n,m);
for(int i=n; i<=m; i++)
{
int sum = 0;
for(int j=1; j<i; j++)
{
if(0 == i%j)
sum += j;
}
if(i == sum)
printf("%d ",i);
}
return 0;
}
练习8、使用printf打开以下图形,要求printf一次只能打印一个字符。
*
***
*****
*******
*********
*******
*****
***
*
#include <stdio.h>
#include <stdlib.h>
int main(int argc,const char* argv[])
{
/*
// i表示每行空格的数量
for(int i=4; i>=0; i--)
{
// 打印每行的空格
for(int j=0; j<i; j++)
printf(" ");
// (5减掉空格的数量)*2-1就是每一行*的数量
for(int j=0; j<(5-i)*2-1; j++)
printf("*");
printf("\n");
}
for(int i=1; i<=4; i++)
{
for(int j=0; j<i; j++)
printf(" ");
for(int j=0; j<(5-i)*2-1; j++)
printf("*");
printf("\n");
}
*/
// 每行空格的数量 4 3 2 1 0 1 2 3 4 <=> abs([-4,4])
for(int i=-4; i<=4; i++)
{
for(int j=0; j<abs(i); j++)
printf(" ");
for(int j=0; j<(5-abs(i))*2-1; j++)
printf("*");
printf("\n");
}
return 0;
}
附加题、使用printf打开以下图形,要求printf一次只能打印一个字符。
*
* *
* *
* *
* *
* *
* *
* *
*