if语句可以判断条件是否满足,条件满足则执行相应动作;循环语句可以在满足条件时,不断地重复执行某些动作。 ::: tip 循环语句可以多次执行其他语句,它会检查一个逻辑条件是否满足,只在满足的时候执行它的循环体。 ::: while语句是一个循环语句,它会首先判断一个条件是否满足,如果条件满足,则执行后面紧跟着的语句或语句括号,然后再次判断条件是否满足,如果条件满足则再次执行,直到条件不满足为止。后面紧跟的语句或语句括号,就是循环体。
do-while循环和while循环很像,唯一的区别是我们在循环体执行结束的时候才来判断条件。也就是说,无论如何,循环都会执行至少一遍,然后再来判断条件。与while循环相同的是,条件满足时执行循环,条件不满足时结束循环。
while循环
编写一个判断数字位数的程序:
#include <stdio.h>
int main()
{
int n = 0;
int x;
printf("输入要判断的数字");
scanf("%d",&x);
n++;
x /= 10;
while(x > 0){
n++;
x /= 10;
}
printf("%d",n);
return 0;
}
::: warning 上述程序最大支持查询10位数字的位数查询。 :::
::: tip
if(条件){语句}当括号内条件满足时执行语句。while语句只需要将if语句的关键字换成while即可。 if语句中是一次性的,while是需要反复执行的。 ::: while循环流程图: ::: tip 循环体内要有改变条件的机会,否则程序将一直在循环体中循环执行下去。 (防止语法正确逻辑错误的情况)。 ::: while循环的意思是:当条件满足时,不断重复执行循环体内的语句。 在进入while循环之前先判断条件,如果条件不满足,就不会进入循环体。
验证程序 列出程序中所有变量,通过模拟计算机程序运算,计算每一个步骤执行后各变量的值。
上述判断数字位数的程序中,是否可以将while语句之前的"n++"和"x /= 10"省略掉呢:
#include <stdio.h>
int main()
{
int n = 0;
int x;
printf("输入要判断的数字");
scanf("%d",&x);
while(x > 0){
n++;
x /= 10;
}
printf("%d",n);
return 0;
}
通过计算运行可以得出结论,可以省略掉while语句前和循环体中相同的语句。 但是两段程序都不能有效解决x的值为0时的情况。即给x赋值0,0应该是1位数,但程序输出值为0。
#include <stdio.h>
int main()
{
int n = 0;
int x;
printf("输入要判断的数字");
scanf("%d",&x);
if (x > 0) {
while(x > 0){
n++;
x /= 10;
}
}else{
n=1;
}
printf("%d",n);
}
当x输入0时,输出结果为1。 可以在程序的适当位置插入printf输出一些变量的值,模拟debugging的过程。(某些复杂程序交互中debugging不一定能开出来)
#include <stdio.h>
int main()
{
int n = 0;
int x;
printf("输入要判断的数字");
scanf("%d",&x);
if (x > 0) {
while(x > 0){
n++;
x /= 10;
printf("n的值为%d x的值为%d\n",n,x);
}
}else{
n=1;
}
printf("%d",n);
}
输入要判断的数字2541264
n的值为1 x的值为254126
n的值为2 x的值为25412
n的值为3 x的值为2541
n的值为4 x的值为254
n的值为5 x的值为25
n的值为6 x的值为2
n的值为7 x的值为0
7
输入要判断的数字4
n的值为1 x的值为0
1
也可以在程序中插入一些变量以及printf输出该变量值以便于观察到程序运行到的位置
#include <stdio.h>
int main()
{
int n = 0;
int x;
printf("输入要判断的数字");
scanf("%d",&x);
int hr = 0;
if (x > 0) {
while(x > 0){
hr++;
printf("hr%d\n",hr);
n++;
x /= 10;
printf("n的值为%d x的值为%d\n",n,x);
}
}else{
n=1;
}
printf("%d",n);
}
输入要判断的数字952
hr1
n的值为1 x的值为95
hr2
n的值为2 x的值为9
hr3
n的值为3 x的值为0
3
::: tip 也可直接printf("hr\n"),起到观察程序运行位置的作用即可。 :::
do while循环
计算数字位数的算法: 1.用户输入要判断的数字x; 2.初始化n=0; 3.x=x/10,去掉个位数; 4.n++; 5.如果x>0,回到3; 6.否则,输出n。 在计算数字位数的程序中,曾将while语句之前的"n++"和"x /= 10"省略,发现省略掉后在某些情况下不适用,结合上述算法,可以判断出省略掉while语句之前的"n++"和"x /= 10",相当于将将第五步判断“x>0”放在了第三步,先执行判断再做运算。实际上保留"n++"和"x /= 10"是正确的,需要先执行一遍"x /= 10"再进行判断是否需要循环执行。do while循环可以满足以上条件。 do while循环:在进入循环时候不做判断,在执行一轮循环体的代码后再判断循环条件是否满足,如果满足则进入循环,如果不满足则结束循环。 do while 循环结构: do { 循环体语句<> }while(<循环条件>); ::: tip do while循环的while语句后的()后必须以“;”结尾表示结束。 (结束语句用大括号“{}”和分号“;”做结尾。) ::: 两种循环: 左边是do while循环,右边是while循环。 ::: warning while和do while循环的区别仅仅是执行判断的先后。 while先执行判断再进入循环(进入循环体时判断),do while先执行一遍循环再进入判断(离开循环体时判断),条件满足继续执行循环,条件不满足退出循环。即无论条件满足与否,do while循环至少执行一遍循环体内代码,而while循环可能一遍也不执行。 ::: 使用do while循环优化后的判断数字位数的程序:
#include <stdio.h>
int main()
{
int x;
int n = 0;
scanf("%d",&x);
do
{
x /= 10;
n++;
}while (x>0);
printf("%d",n);
return 0;
}
for循环
计算一个数的阶乘的步骤如下: n!=1×2×3×4×...×n 转换成程序需要三个变量,分别是接收用户输入的int变量n,计算结果n!的int变量fact,计算中从1逐渐递增到n的变量i。 使用while循环编写的程序如下:
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact = 1;
int i = 1;
while(i <= n){
fact *= i;
i++;
}
printf("%d!=%d\n",n,fact);
return 0;
}
使用for循环编写的程序如下:
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact = 1;
int i = 1;
for(i = 1; i <= n; i++){
fact *= i;
}
printf("%d!=%d\n",n,fact);
return 0;
}
上述程序中,for语句后的()内,第一个表达式是初始条件,第二个表达式是循环条件,第三个表达式是循环动作。 ::: warning for循环内的表达式的执行顺序是先执行初始条件,再执行循环条件判断,判断成立后执行循环体,最后执行()内最后一个分号后的循环动作的表达式。 ::: ::: tip for循环像一个计数循环:设定计数器并初始化,在计数器达到某个值之前重复执行循环体,每执行一轮循环,计数器值以一定的步进进行调整,即+1或-1或其他内容。如下:
for(i=0;i<5;i=i+1){
printf("%d,"i);
}
::: 上述程序中,循环控制变量i只在循环里面被使用,可以把变量i的定义写在for语句内,如下:
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact = 1;
//int i = 1;
for(int i = 1; i <= n; i++){
fact *= i;
}
printf("%d!=%d\n",n,fact);
return 0;
}
上述将变量i的定义写在for语句内的方式,有时会有报错提示:在该函数中for循环初始化声明只可以在C99的模式下用,需要在编译代码时加上一个编译选项-std=c99。
for可以认为是“对于”的意思,即对于(初始条件)...下,当(满足循环条件)...时,重复执行循环体,每一轮执行完毕时候,使得(循环动作)...。 ::: warning 做求和运算的程序时,记录结果的变量初始化应该为0,做求积的运算程序时,记录结果的变量应该初始化为1。 :::
两种尝试 1.可以尝试修改程序,使得程序的i的值从2开始(在fact = 1时,i如果从1开始,1*1=1),如下:
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact = 1;
int i = 1;
for(i = 2; i <= n; i++){
fact *= i;
}
printf("%d!=%d\n",n,fact);
return 0;
}
在n >= 2时候,程序满足i <= 2,正常执行i++的动作,当n = 1时,不满足循环条件,不执行循环的动作(for循环和while循环类似,先进行判断,再执行动作),此时fact仍然为1,即1!=1,计算仍然成立。 2.除了从1乘到n,还可以选择从n乘到1。如下:
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
int fact = 1;
int i = 1;
for(i = n; i > 1; i--){
fact *= i;
}
printf("%d!=%d\n",n,fact);
return 0;
}
在上述的程序中,for循环中第一个表达式i = n,可以直接使用n即n = n,从而在循环过程中不使用变量i,让n自己每次进行-1的运算,但因为要输出n的阶乘,所以变量i可以用来暂存n的值,即在for循环外需要有int i = n 。因为n = n并没有任何意义,可以在for循环中省略这个表达式,变为for(;循环条件;循环动作)。 for循环的()中每一个表达式都可以省略,for(;判断条件;) == while(判断条件)
循环计算和选择
循环次数: 对于for循环for(i=0;i<n;i++)来说,循环次数为n,当循环结束时,i = n,受限循环条件,在循环内部,i的值不可能等于n。
#include <stdio.h>
int main()
{
int i;
for(i=0;i<5;i++){
printf("i=%d ",i);
}
printf("\n最终i=%d",i);
return 0;
}
$ cpp main.c -o main.ii
$ cc main.ii -o main
$ ./main
i=0 i=1 i=2 i=3 i=4
最终i=5
Program exited with status 0
将初始条件下的i = 0改为i = 1:
#include <stdio.h>
int main()
{
int i;
for(i=1;i<=5;i++){
printf("i=%d ",i);
}
printf("\n最终i=%d",i);
return 0;
}
$ cpp main.c -o main.ii
$ cc main.ii -o main
$ ./main
i=1 i=2 i=3 i=4 i=5
最终i=6
Program exited with status 0
通过对比之前的while循环和for循环可以发现,for == while。
for(int i=1;i<=n;i++){
fact *= i;
}
等价于
int i = 1;
while(i <= n){
fact *= i;
i++;
}
在流程图上while循环和for循环是一样的,任何一个for循环都可以改写成while循环。 将for循环中的初始条件放在while循环外,for的条件判断放在while的条件判断中,要做的循环动作按照顺序放在循环体内原有的表达式后。
三种循环分别是for循环、while循环、do while循环 在选择循环类型时,如果循环有固定次数,使用for循环,如果循环必须进行一次,使用do while循环,其他情况都用while循环。