写这篇文章,我深有感触,在写代码的过程中,我们经常会出现最后的结果达不到我们预期的效果的情况,我们一定一定要耐下心来,一步一步地去思考,是哪里出了问题,怎么能解决问题,这样的一个过程是十分重要的,是能让我们越来越接近真相的过程。学习编程的路肯定不是一帆风顺的,但我们要有能够克服任何苦难的决心,这是最重要的。
在这篇文章中,我们将会对循环语句有一个更加深入的了解
并且我们还能了解到getchar与putchar的相关知识
让我们开始吧!
目录
一.while循环
1.while循环语法
2.break和continue 在while循环中
(1).break
(2).continue
3.两个代码的练习
第一个代码
第二个代码
二.for循环
1.for循环语法
2. break和continue在for循环中
(1).break
(2).continue
continue在for循环和在while循环中有所不同
三.do...while()循环
1.do...while()循环的语法
2.break和continue在do...while循环中
(1).break
(2).continue
while语句又称当型循环语句,其语法为:
while (表达式)
循环语句;
(1)计算表达式的值。若为真,则转步骤(2),否则退出循环,执行while的下一条语句
(2)执行循环语句(即循环体),并返回步骤(1)
这里试着使用while循环打印1~10的数
#include
int main()
{
int i = 1;
while(i<=10)
{
printf("%d ", i);
i++;
}
return 0;
}
#i#include
int main()
{
int i = 1;
while(i<=10)
{
if(5 == i)
break;
printf("%d ", i);
i ++;
}
return 0;
}
运行的结果如图
总结:
break在while循环中的作用:
其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。
所以:while中的break是用于永久终止循环的。
如果将刚刚的break换成continue
那么运行的结果又会发生什么变化呢?
#include
int main()
{
int i = 1;
while(i<=10)
{
if(5 == i)
continue;
printf("%d ", i);
i ++;
}
return 0;
}
4后面的光标在闪动,说明此时程序进入了死循环
原因是,与break语句不同,
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接 跳转到while语句的判断部分。进行下一次循环的入口判断
如图中红色框框内的代码在continue的作用下会被跳过,i++不会被执行,所以i就一直为5,进去死循环
让我们再看两个跟while循环有关的代码,再看之前,我们需要先了解一下getchar和putchar
getchar
在msdn中,我们查找到getchar的解释
int ch = getchar() ; //获取字符
printf("%c\n",ch) ; //打印获取的字符
这里我们会有这样的疑问:我们的 ch 获取的是一个字符,为什么放到int整型里去?
原因有两个:
getchar - 获取(输入一个字符)
putchar - 输出一个字符
putchar
在msdn中的定义
int ch = getchar() ; //获取字符
putchar (ch);//输出一个字符
getchar 和 putchar 可以用scanf 和printf代替,且scanf和printf的功能更全,getchar和putchar只能操作字符
这个代码会将你输入的字符打印出来,如果想停止:ctrl+z 可以让getchar返回一个EOF
我们写这样的代码有什么意义呢?实际上是有意义的,我们这里再举一个例子
#include
int main()
{
char input[20] = { 0 };//创建一个数组
printf("请输入密码:>");
scanf("%s", input);
printf("请确认密码(Y/N):>");
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
看这个代码时,可能会有疑问,为什么scanf函数里的input没有取地址,
这样一个程序,我们的本意是输入密码后需要用户确认密码是否正确,可当程序走起来后我们发现,在我们还没有输入时,已经打印出了“确认失败”
下面我们就来分析一下程序出问题的原因 ,全部在这张图上了
解决方法 :把输入缓冲区里scanf没有拿走的\n拿走 ,改进如下
#include
int main()
{
char input[20] = { 0 };//创建一个数组
printf("请输入密码:>");
scanf("%s", input);
getchar(); //拿走\n
printf("请确认密码(Y/N):>");
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
}
我们成功了!!!
下面是还可能出现的错误的情况:如果密码当中有“ ”(空格)
当用户输入的密码中含有空格时,又出现了刚刚的错误的情况,我们再来分析
我们可以发现这时需要拿走更多的字符,所以我们使用while循环
while ((tmp = getchar()) != '\n') //只要不是/n,就说明没拿完,就进入循环
{
; //空语句(什么也不干)
}
#include
int main()
{
char input[20] = { 0 };//创建一个数组
printf("请输入密码:>");
scanf("%s", input);
int tmp = 0;
while ((tmp = getchar()) != '\n')//只要不是/n,就说明没拿完,就进入循环
{
;//空语句(什么也不干)
}
printf("请确认密码(Y/N):>");
int ch = getchar();
if (ch == 'Y')
{
printf("确认成功\n");
}
else
{
printf("确认失败\n");
}
return 0;
我们惊喜地发现,我们又通过改变代码使这个程序执行成功了!
#include
int main()
{
int ch=0;
while ((ch = getchar()) != EOF)
{
if (ch < ‘0’ || ch > ‘9’)
continue;
putchar(ch);
}
return 0;
}
这个代码就比较简单了 就是只打印0~9的数字
这个括号不能少((ch=getchar())!=EOF) 如果少了 ,就不是把获取的字符放进ch和EOF比较了,而是字符直接与EOF比较,不相等就为假,就为0,这时就把0赋给了ch
for循环的语法:
for (表达式1;表达式2;表达式3)
循环语句;
表达式1
表达式1为初始化部分,用于初始化循环变量的。
表达式2
表达式2为条件判断部分,用于判断循环时候终止。
表达式3
表达式3为调整部分,用于循环条件的调整。
这里我们同样也使用for循环来打印一下1~10的数来熟悉一下for循环
#include
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
printf("%d ", i);
}
return 0;
}
并且,我们用这个代码为例,来帮助我们理解for循环的流程图
现在我们对比一下for循环和while循环
int i = 0;
//实现相同的功能,使用while
i=1;//初始化部分
while(i<=10)//判断部分
{
printf("hehe\n");
i = i++;//调整部分
}
//实现相同的功能,使用while
for(i=1; i<=10; i++)
{
printf("hehe\n");
}
可以发现在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离 较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹。 for循环使用的频率也最高。
我们发现在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。
但是还是有些差异:
可见,break在for循环中与在while循环中类似,都是直接终止循环
#include
int main()
{
int i = 0;
for(i=1; i<=10; i++)
{
if(i == 5)
continue;
printf("%d ",i);
}
return 0;
}
这里执行起来并不是死循环了,而是跳过5打印了1 2 3 4 6 7 8 9 10
当i==5时,执行continue语句,跳过printf语句 ,执行 i++,之后 i为6,i==5为假,continue语句不再执行
for语句的循环控制变量 (作为补充)
一些建议:
int i = 0;
//前闭后开的写法
for(i=0; i<10; i++)
{}
//两边都是闭区间
for(i=0; i<=9; i++)
{}
第一种也就是前闭后开的写法很直观,这个循环要循环10次(但不是总是如此)
一些for循环的变种
#include
int main()
{
//变种1
for(;;)
{
printf("hehe\n");
}
//变种2
int x, y;
for (x = 0, y = 0; x<2 && y<5; ++x, y++)
{
printf("hehe\n");
}
return 0;
}
变种1
for的初始化,判断,调整三个部分都可以省略
中间的判断部分如果省略,意味着判断恒为真,就构成死循环
如果条件允许,不建议省略for循环的3个表达式
这里看一个嵌套的for循环 ,来比较一下
#include
int main()
{
int i = 0;
int j = 0;
for (i = 0;i < 3;i++)
{
for (j = 0;j < 3;j++)
{
printf("hehe\n");
}
}
return 0;
}
在正常情况下,这个程序会3次外循环,3次内循环,共9次 打印9次hehe
我们现在试一下省略for的第一个初始化语句
#include
int main()
{
int i = 0;
int j = 0;
for (;i < 3;i++)
{
for (;j < 3;j++)
{
printf("hehe\n");
}
}
return 0;
}
结果只打印了三次, 原因是 虽然外循环还是3次,但内循环由于 j 没有初始化,在内循环第3次后,j就变成了4,内循环不再执行
变种2
使用多于一个变量控制循环,这是允许的
for (x=0,y=0;x<2&&y<5,++x,y++)
这里,我们再拓展一道笔试题:
请问循环要循环多少次?
//请问循环要循环多少次?
#include
int main()
{
int i = 0;
int k = 0;
for(i =0,k=0; k=0; i++,k++)
k++;
return 0;
}
原因是这里的红色框中的 k=0是赋值,k被赋值为0,0为假,循环不执行
do
循环语句;
while (表达式);
我们再用do...while循环来试着打印1~10的数
#include
int main()
{
int i = 1;
do
{
printf("%d ", i);
i++;
} while (i <= 10);
}
do..while的特点是:循环至少执行一次,使用的场景有限,所以不是经常使用。
#include
int main()
{
int i = 1;
do
{
if (5 == i)
break;
printf("%d ", i);
i++;
} while (i <=10);
return 0;
}
可见,break在三个循环中较为类似,都是直接终止循环,但是值得注意的是: break只能终止一层循环,如果有刚刚那种嵌套式的循环,只能终止一层
#include
int main()
{
int i = 1;
do
{
if (5 == i)
continue;
printf("%d ", i);
i++;
} while (i <=10);
return 0;
}
运行的结果是1 2 3 4死循环