文章目录
前言
本篇内容主要记录 循环语句:
包括while循环,for循环,do...while,goto循环详细讲解以及习题巩固练习
____________________________________________________________________________
****正文开始****
一、while 循环
在我们的日常生活中有很多实际的例子:
//while 语法结构
while(表达式)
循环语句;
Q : 比如我们实现:在屏幕上打印1-10的数字。
int main() {
int i = 0; // 初始化
while (i <= 10) {// 判断
printf("%d ", i);
i++; //调整部分
}
return 0;
}
(一)while语句中的break和continue
1>break在while循环中
Q : 我们看这段代码,它的执行结果是什么呢?
int main() {
int i = 1;
while (i <= 10) {
if (5 == i)
break;
printf("%d ", i);
i++;
}
return 0;
}
我们发现了break在while循环中的作用:
2>continue在while循环中
Q : 我们看这段代码,它的执行结果是什么呢?
int main() {
int i = 1;
while (i <= 10) {
if (5 == i)
/*break;*/
continue;// continue 会跳过后面的语句
printf("%d ", i);
i++;
}
return 0;
}
我们看运行结果:
Q : 我们再看这段代码,它的执行结果是什么呢?
int main() {
int i = 1;
while (i <= 10) {
i++;
if (5 == i)
continue;// continue 会跳过后面的语句
printf("%d ", i);
}
return 0;
}
我们看它的运行结果:
我们能够发现:第一段代码运行到4之后,当i==5的时候发生了死循环。这是因为continue起了作用,我们就要提到continue 的作用了。
(二)getchar 详解
Q : 我们在观察这段代码,他是什么意思?
int main() {
int ch = 0;
while ((ch = getchar())!= EOF) {
putchar(ch);
}
return 0;
}
这里的代码适当的修改是可以用来清理缓冲区的.
#include <stdio.h>
int main()
{
char ch = '\0';
while ((ch = getchar()) != EOF)
{
if (ch < ‘0’ || ch > ‘9’)
continue;
putchar(ch);
}
return 0; }
这个代码的作用是:只打印数字字符,跳过其他字符的
举例: 请观察这段代码?他会正常输出我们想要的结果吗?
int main() {
char input[20] = { 0 };
printf("请输入密码:>");
scanf("%s", input); // abcdef
getchar(); // 拿走 \n
printf("请输入密码(Y/N):>");
int ch = getchar();
if (ch == 'Y') {
printf("确认成功\n");
}
else {
printf("确认失败\n");
}
return 0;
}
查看运行结果:
我们发现如果连续的输入一段数字,程序会正常按照我们的意思输出,但是如果我们更改输入的方法,他还会正常吗?
我们观看这样的输入方式:
在这里我们输入的密码:123 456
我们在123和456之间加入一个空格,我们发现这就导致了我们直接略过了判断密码是否争取的那一步,并且输出了确认失败,这是为什么呢?
这是因为:
我们从键盘输入: 123 456
实际上是: 123 456\n
读取字符串的时候,遇到空格就结束了,所以getchar只都读走了123
缓冲区内部还有:_ (空格)456\n
所以一个getchar并不能解决问题,应该使用一种方法将缓冲区的所有字符带走,这时候就可以运用while循环,具体代码如下:
//清理缓冲区
int tmp = 0;
while ((tmp = getchar()) != '\n') {
; //空语句
}
通过清理缓冲区这时候就可以达到我们想要的结果:
整体代码如下:
int main() {
char input[20] = { 0 };
printf("请输入密码:>");
scanf("%s", input); // 123 456
//清理缓冲区
int tmp = 0;
while ((tmp = getchar()) != '\n') {
; //空语句
}
printf("请输入密码(Y/N):>");
int ch = getchar();
if (ch == 'Y') {
printf("确认成功\n");
}
else {
printf("确认失败\n");
}
return 0;
}
我们再看 演示结果:
我们发现解决了问题
二,for 循环
for(表达式1; 表达式2; 表达式3)
循环语句;
我们继续以实例的方式了解for循环语句:
int main() {
int i = 0;
//for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)
for (i = 1; i <= 10; i++){
printf("%d ", i);
}
return 0;
}
现在我们来对比一下while循环和for循环:
int i = 0;
//实现相同的功能,使用while
i = 1;//初始化部分
while (i <= 10)//判断部分
{
printf("hehe\n");
i = i + 1;//调整部分
}
//实现相同的功能,使用while
for (i = 1; i <= 10; i++) {
printf("hehe\n");
}
(一)break和continue在for循环中
1>break 在for循环中
//代码1
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
break;
printf("%d ", i);
}
return 0;
}
我们观察运行结果:
我们观察到输出的结果为:1 2 3 4
这是因为: 当 i == 5 进入 if 判断当中时,直接跳出 for 循环
到达 return 0;
因此打印出 : 1 2 3 4(和while 循环类似)
2>continue 在for循环中
#include <stdio.h>
int main()
{
int i = 0;
for (i = 1; i <= 10; i++)
{
if (i == 5)
continue;
printf("%d ", i);
}
return 0;
}
2. 中间的判断部分如果省略,意味着判断恒为真,就构成了死循环
3. 如果条件允许,不建议省略for循环的3个表达式
for (;;) {
printf("hehe\n");// 死循环打印hehe
}
我们再来看这段代码:
int i = 0;
int j = 0;
for (i = 0; i < 3; i++){
for (j = 0; j < 3; j++) {
printf("hehe\n");
}
}
我们看运行结果:
我们发现这个程序打印了 9 行 hehe,这是因为当 i ==0 进入程序的时候 j 从0开始循环,当 j == 0 时, 打印一遍 hehe;当 j == 1 时, 打印第二遍 hehe ,d ;当 j == 2 ,打印第三遍 hehe;当 j ==3 不小于3的时候跳出 j 的循环 这时候 i++,此时 i == 1,同理,j 又从0开始打印 3遍hehe;i 再 i++;j 又打印3遍hehe,当 i==3 时 ,i < 3 不成立时,退出循环 ,这时候统计发现一共打印了9遍呵呵。
但是,如果我们省略表达式一(初始化),打印的结果会完全不同。
int main() {
int i = 0;
int j = 0;
for (; i < 3; i++) {
// j = 3 没再初始化了
for (; j < 3; j++) {
printf("hehe\n"); // 打印3个hehe
}
}
return 0;
}
我们观察运行结果:
//int main() {
// int i = 0;
// int k = 0;
// // k = 0 赋值0 结果是0 表示假 不进入循环
// for (i = 0, k = 0; k = 0; k++) {
// k++;
// }
// return 0;
//}
Q:问这段代码循环几次?
A : 通过代码我们发现 for循环中的表达式2 是k = 0,‘=’是赋值符号,因此是将数字0赋值给k,我们知道在C语言中0表示假,因此表达式2 判断为假,根本不会进入for循环,因此这段代码循环0次。
三,do while 循环
do
循环语句;
while(表达式);
#include <stdio.h>
int main()
{
int i = 1;
do
{
printf("%d\n", i);
i++;
} while (i < 10);
return 0;
}
这段代码是用while循环打印1-10。
(一)do while循环中的break和continue
1> break 在 do while 循环中
int main() {
int i = 1;
do {
if (i == 5)
break;//打印 1 2 3 4
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
道理同break在while和for循环中一样。
2> continue 在 do while 循环中
int main() {
int i = 1;
do {
if (i == 5)
continue;// 1 2 3 4死循环
printf("%d ", i);
i++;
} while (i <= 10);
return 0;
}
运行结果:
原因和while循环中的道里一致,因为continue是跳出本次循环,不会执行后面的i++,所以如果当i==5时就会一直死循环。
这时候我们如果将i++放到continue之前结果为:
int main() {
int i = 1;
do {
i++;
if (i == 5)
continue;// 1 2 3 4死循环
printf("%d ", i);
} while (i <= 10);
return 0;
}
我们发现和while循环中的将i++的第二种可能性一直,道理相同。
四,goto语句
// 多层循环这种情况使用break是达不到目的的,他只能从最内层循环退出上一层的循环
// 这时候 goto语句适合这种场景
for () {
for () {
for () {
if (disaster) {
goto error;
}
}
}
}
...
error:
if(disaster)
// 处理错误情况
goto again 用法(标签一致就行,但标签必须在同一个函数内)
int main() {
again:
printf("hehe\n");
printf("haha\n");
goto again; // 标签一致就行,标签必须在同一个函数内
return 0;
}
结果演示:
会死循环打印hehe和haha.
小游戏,小整蛊:
//例如: 写一个关机程序
//只要程序启动了,就倒计时60秒关机,如果60秒之内,输入:我是猪,就取消关机,如果不输入,时间到就关机
shutdown windows提供的关机命令
shutdown -s -t 60秒之后关机
shutdown -a 取消关机
int main() {
char input[20] = { 0 };
system("shutdown -s -t 60");
again:
printf("请注意,你的电脑在1分钟内关机,如果输入:我是猪,就取消关机\n");
scanf("%s", input); //input本来就是地址 不用取地址
//判断
if (strcmp(input,"我是猪") == 0) {
// 取消关机
system("shutdown -a");
}
else {
goto again;
}
return 0;
}
五,练习题巩固
1.计算n的阶乘
int main() {
int n = 0;
scanf("%d", &n);// 5
int i = 0;
int ret = 1;
for (i = 1; i <= n; i++) {
ret *= i;
}
printf("%d\n",ret);
return 0;
}
2.计算 1!+2!+3!+4!+.....n!
int main() {
int n = 0;//共n个数字
scanf("%d", &n);
int i = 0;// j 内部的第 i 个数字
int j = 0;// n 内部的第 j 个数字
int sum = 0;
for (j = 1; j <= n; j++) {//
int ret = 1;
for (i = 1; i <= j; i++) {
ret *= i;
}
sum += ret;
}
printf("%d\n", sum);
return 0;
}
当然这道题我们还有优化算法:
int main() {
int n = 0;
int i = 0;
int ret = 1;
int sum = 0;
for (n = 1; n <= 10; n++) {
ret = ret * n;
sum += ret;
}
printf("%d\n", sum);
return 0;
}
3.在一个有序数组中查找具体的某个数字n(二分查找)
这个是普通求法:
int main() {
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 7;
int i = 0;
for (i = 0; i < 10; i++) {
if (arr[i] == k) {
printf("找到了,下标是%d\n", i);
break;
}
else if (i == 10) {
printf("找不到\n");
}
}
return 0;
}
我们发现,如果说这个数组中定义了100甚至更多的数字时,这样的算法就会耗时耗力,因为有一种更简便的算法:
二分法 -- 折半查找
int main() {
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int sz = sizeof(arr) / sizeof(arr[0]);
// 40 / 4 = 10
int k = 7;
int left = 0;
int right = sz - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (arr[mid] < k) {
left = mid + 1;
}
else if (arr[mid] > k) {
right = mid - 1;
}
else {
printf("找到了,下标是%d \n", mid);
break;
}
}
if (left > right) {
printf("找不到\n");
}
return 0;
}
4:反向打印一个数字
int main() {
int n = 0;
scanf("%d", &n);
while (n!=0) {
printf("%d", n % 10);
n = n / 10;
}
return 0;
}
****正文结束****
———————————————————————————————————————————
总结
本篇文章的内容就记录完毕,由于本人技术水平有限,若各位读者发现错误,欢迎及时纠正。