循环结构梳理
前言
循环结构是C语言中极为重要的一部分,今天小萌新打算来给大家梳理一下三种循环结构。不足之处,欢迎大家在评论区补充。
一、for循环
标准版for循环
标准型:
for(表达式1;表达式2;表达式3)
{表达式4;
表达式5;
表达式6;
…
}
其中,大括号内的内容可以是一条语句,也可以是由分号隔开的多条语句。如果只有一条语句,大括号可以省略。
运行顺序:
先执行表达式1(初始化语句),再判断表达式2,如果成立,执行{}内的语句,之后再执行表达式3(修正语句),如果不成立,循环结束。(如下图)
比如,我们现在有一个数组{1,2,3,4,5},我们希望依次输出它的五个元素。(由于循环体内只有一个表达式,故省略了大括号)
int a[5]={1,2,3,4,5};
int i;
for(i=0;i<5;i++)
printf("%d ",a[i]);
输出如下:
也可以写成:
int a[5]={1,2,3,4,5};
for(int i=0;i<5;i++)
printf("%d ",a[i]);
C99标准允许程序员在for的小括号内定义变量,该变量只在for循环里有效,在循环结束时失效。
int a[5]={1,2,3,4,5};
int i=3;//这个i在整个main函数里有效
printf("i的值是%d\n",i);
for(int i=0;i<5;i++)//这个i只在for循环里面生效
printf("a[%d]=%d\n",i,a[i]);
printf("i的值是%d",i);
如果采用的是C90,编译器会报错:
[Error] ‘for’ loop initial declarations are only allowed in C99 or C11 mode
省略版for循环
对于for循环而言,
没有任何一个表达式是必须的。
但是,没有一个分号是可以省略的!
对于刚刚的例子,我们可以省略表达式1,写成:
int a[5]={1,2,3,4,5};
int i=0;
for(;i<5;i++)
printf("%d ",a[i]);
也可以省略表达式2,写成:
int a[5]={1,2,3,4,5};
int i;
for(i=0;;i++)
if(i<5)//if语句虽然占了四行,但是一个if...else...算一个语句,故此处不需要大括号
printf("%d ",a[i]);
else
break;//break函数,指跳出该循环
也可以省略表达式3,写成:
int a[5]={1,2,3,4,5};
int i;
for(i=0;i<5;){//循环体内有两个语句,必须要大括号!
printf("%d ",a[i]);
i++;
}
或者:
int a[5]={1,2,3,4,5};
int i;
for(i=0;i<5;)
printf("%d ",a[i++]);
表达式4也同样可以省略,比如我们希望找出比n小的完全平方数中最大的那个:(暂且让我们令n=99)
int n=99;
int i;
for(i=0;i*i<n;i++);//请不要省略这个分号!
printf("%d",(i-1)*(i-1));
为什么输出i-1的平方而不是i的平方?
因为当i=9时,i的平方小于n,(表达式2成立)循环会再次进行,但循环体内没有任何语句,故直接执行表达式3,使i自增,此时i=10,表达式2不再成立,循环退出。循环结束时i=10,i的平方大于n。
二、while循环
标准版while循环
标准型:
while(表达式1){
表达式2;
…
}
运行顺序:先判断表达式1是否成立,如果不成立,结束循环;如果成立,执行大括号里的内容,然后再次判断表达式1。同样的,如果大括号里只有一条语句,大括号可以省略。
再用刚刚的例子,我们希望依次输出数组{1,2,3,4,5} 的五个元素。那么可以写成:
int a[5]={1,2,3,4,5};
int i=0;
while(i<5)//只有一个语句,大括号省略
printf("%d ",a[i++]);
不难发现:
for(表达式1;表达式2;表达式3){表达式4}
等价于:
表达式1;while(表达式2){表达式4;表达式3}
和for循环一样,while循环也可以省略其中任何一个表达式。
但在此之前,先介绍一下break语句和continue语句:
break语句
break指立刻跳出该循环,例子:
int a[5]={1,2,3,4,5};
int b[5]={1,2,2,4,5};
int i;
for(i=0;i<5;i++)
if(a[i]!=b[i])
break;
if(i==5) printf("a与b相同\n");
else printf("a与b不相同\n");
如果系统执行到break语句(即if判断成立)会立刻结束for循环,开始执行第八行语句,而不会进行i++运算。因此我们可以通过判断for循环结束时 i 的值来判断是否有中途break。(需要注意的是不能写成for(int i=0;…),不然for循环退出之后,变量 i 将不复存在,无法判断。)
注意:break只能跳出一个for循环,或者跳出一个while循环,如果有双层的for循环嵌套,是不能用一个break完全跳出的。只能用goto语句,或者别的方式实现。
continue语句
continue指立刻结束当前循环,开始下一个循环,例子:
int a[5]={1,2,3,4,5};
int b[5]={1,2,2,4,5};
int i;
for(i=0;i<5;i++){
if(a[i]!=b[i])
continue;
printf("a[%d]与b[%d]相等\n",i,i);
}
运行结果:
当 i =2时,if判断成立,执行continue语句,跳过后面的print语句,直接执行i++语句,然后开始下一个循环;
但是,不可以写成:
int a[5]={1,2,3,4,5};
int b[5]={1,2,2,4,5};
int i;
while(i<5){
if(a[i]!=b[i])
continue;
printf("a[%d]与b[%d]相等\n",i,i);
i++;
}
点击运行,系统死机:
这是因为当 i =2时,执行了continue,由于此处的while循环里没有修正语句,会直接开始下一个循环( i 依然等于2)。故系统会在 i 始终等于2的情况下无限循环。
省略版while循环
对于我们刚刚的例子,
可以省略表达式1,写成:
int a[5]={1,2,3,4,5};
int b[5]={1,2,2,4,5};
int i;
while(1){
if(a[i]==b[i])
printf("a[%d]与b[%d]相等\n",i,i);
i++;
if(i>=5) break;
}
表达式1即使省略,也要写一个“1”在小括号里。由于while会先判断小括号里表达式是否成立,再选择是否执行接下来大括号里的内容。而判断表达式是否成立,指的是计算它的值,非0为真,0为假。比如当a的值为5时,表达式a== 5的值为1(真),表达式a==1的值为0(假)。
而表达式“ 1 ”的值显然为1,因此这个式子必然为真。while会不断执行大括号里的内容,为了防止出现死循环,我们需要用break函数,goto函数或者return来跳出循环。
对于省略表达式2的情况,在这里介绍一种特殊用法:
while((c=getchar())!='\n');
最后的分号表示该while循环的循环体内没有任何东西,当系统执行到这一行时,会首先getchar一个字符,赋值给c,然后与换行符判断,如果结果为真(即获得的字符不是换行符),那么就执行循环(实际上什么也不做)然后再次获取一个字符,赋值,判断,,,
借此可以删除所有之前输入的字符(即清空缓冲区),以便于后面的输入。例子:
int a;
printf("请输入a的值:\n");
scanf("%d",&a);
char c;
while((c=getchar())!='\n');
char b;
printf("请输入b的值:\n");
scanf("%c",&b);
printf("a=%d,b=%c",a,b);
运行结果:
但如果去掉4,5两行语句:
int a;
printf("请输入a的值:\n");
scanf("%d",&a);
//char c;
//while((c=getchar())!='\n');
char b;
printf("请输入b的值:\n");
scanf("%c",&b);
printf("a=%d,b=%c",a,b);
运行结果:
此时b为换行符。这是因为再输入213后键人了一个换行符(\n),这个换行符没有被前一个scanf语句拿走,留在了缓冲区。后一个scanf取走了这个换行符,赋值给了b。
goto语句
另外还有一个语句,像break与continue一样,能够帮助我们跳出循环,即goto语句,例子:
int a[5]={1,2,3,4,5};
int i=0;
while(1){
printf("%d",a[i++]);
if(i==5) goto end;
}
end:
printf("\n输出完毕\n");
当i=5时,第五行的判断成立,执行goto语句,程序立刻跳至语句标号end处(即第七行)从而做到了退出while循环。
当然,goto也可以往前跳,即语句标号在goto之前,但是,goto不可以跳到其它函数内,即如果goto语句在main函数里,语句标号也必须在main函数里。并且紧接着语句标号的语句不能定义变量。
三、do…while循环
do{
表达式1;
}
while(表达式2);
do…while循环与while循环类似,区别之处在于,无论表达式2是否成立,do…while都会先执行一次循环体。
比如我们想要求最大的n,使得数列An的前n项和小于sum。
int a[5]={1,2,3,4,5};
int sum=12;
int s=0;
int n=0;
do{//这个大括号是可以省略的
s+=a[n++];
}while(s<sum);
printf("n最大是%d",n-1);
输出:n最大是4
do…while循环与while循较为相似,但仍然需要注意的是,即使条件不成立,do…while循环也会执行一次循环体内的语句,而while则会直接跳过循环体。
比如:
int i=8;
while(i<7)
i++;
printf("i的值为%d",i);
输出:i的值为8
int i=8;
do
i++;
while(i<7);//不要漏掉这个分号!!!
printf("i的值为%d",i);
输出:i的值为9
结尾
这次小萌新主要为大家梳理了一下for,while,do…while三个循环。希望对大家能够有所帮助。如果有任何讲错的或者表述不当的地方,劳烦大家在评论区指出。每一条评论小萌新都会看呢。
//求一个点赞好不好