🎯每日努力一点点,技术进步看得见
🏠专栏介绍:【C语言步行梯】专栏用于介绍C语言相关内容,每篇文章将通过图片+代码片段+网络相关题目的方式编写,欢迎订阅~~
循环语句
while语句
我有一个一夜暴富的梦想,如果我只要彩票没中奖,我就一直买彩票,直到中奖为止。这就是一个典型的重复行为了。如果我们想重复执行一些语句,此时该怎么办呢?
C语言中给我提供了3种循环语句,包括while、for、do…while循环,在这篇博客中,将一一介绍它们。首先先让我们来看一下while循环通用格式。
while()//括号里填写重复执行的条件
{
//被重复执行的语句
}
这段代码具体是怎么执行的呢?让我来看一下程序的执行流程图↓↓↓
也就是说,只要满足while循环括号内的条件,它就不断执行循环体语句,知道while括号内条件不满足为止。下面,我们来试着使用while语句实现在屏幕上打印1到100。
#include <stdio.h>
int main()
{
int i = 1;
while(i <= 100)
{
printf("%d ". i);
i++;
}
printf("\n");
return 0;
}
break与continue
下面,我们再来谈谈一谈break。首先我们来看一段代码↓↓↓
#include <stdio.h>
int main()
{
int i = 10;
while(i >= 0)
{
if(i == 5)
break;
printf("%d ", i);
i--;
}
printf("\n");
return 0;
}
我们将这段代码丢给Visual Studio跑一下,它给出的结果是10 9 8 7 6
。5到0这几个数字都不再打印了,为什么呢?
当循环体中执行到break语句时,将跳出整个循环。上面的代码中,i == 5
这个条件满足时,程序将退出整个while循环,因此5到0之后的数字不再打印。
总结:break在while中的作用
在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。 所以:while中的break是用于永久终止循环的。
下面我们再看一段代码↓↓↓
#include <stdio.h>
int main()
{
int i = 10;
while(i >= 0)
{
i--;
if(i == 5)
continue;//Attention!!
printf("%d ", i);
}
printf("\n");
return 0;
}
这段代码和上一个没有多大变化,只是将break换成了continue。它的执行结果如下:9 8 7 6 4 3 2 1 0
(没有5)。在while循环体中if语句满足条件时,将会执行continue语句。一旦执行continue语句,循环体中余下的语句将不再执行,程序将返回到while循环的判断条件处,再重新向下执行。
总结:continue在while中的作用
continue是用于终止本次循环的,也就是本次循环中continue后边的代码不会再执行,而是直接跳转到while语句的判断部分。进行下一次循环的入口判断。
学完while、break和continue了,那下面就让我们来小试牛刀吧( ̄︶ ̄)↗
🐂test1:看一下这段代码在做什么
#include <stdio.h>
int main()
{
char ch = 0;
while((ch = getchar()) != EOF)
{
putchar(ch);
}
return 0;
}
★ps:getchar用于接收用户输入的字符,每次读入一个字符;若读入失败则返回EOF。putchar用于在屏幕上打印一个字符。
揭晓答案的时刻:这段代码执行时,用户输入什么,程序就会打印什么。
🐂test2:再看一下这段代码在做什么
#include <stdio.h>
int main()
{
char ch = 0;
while((ch = getchar()) != EOF)
{
if(ch < '0' || ch > '9')
continue;
putchar(ch);
}
return 0;
}
★ps:字符在C语言中,存储的是它的ASCII码。例如:字符’0’的ASCII码的数值48,字符’9’的ASCII码的数值是57。
揭晓答案的时刻:ch < '0' || ch > '9'
用于判断ch不是0到9这10个字符的情况,如果不是数字,则continue,继续执行循环体的判断条件。如果是数字,则不会执行continue,而是打印出来。所以,这段代码实现:用户输入数字则打印,输入其他字符不打印。
for语句
既然我们已经有了while循环语句了,那为什么我们还要学习for循环呢?那我们就得先来看看for循环的语法了↓↓↓
for(表达式1; 表达式2; 表达式3)
{
//循环语句
}
表达式1为初始化部分,用于初始化循环变量的。表达式2为条件判断部分,用于判断
循环时候终止。表达式3为调整部分,用于循环条件的调整。
我们实现使用for循环打印1到100试试看↓↓↓
#include <stdio.h>
int main()
{
for(int i = 1; i <= 100; i++)
{
printf("%d ", i);
}
printf("\n");
return 0;
}
通过这段代码我们可以来分析一下for循环的执行顺序:首先它会执行表达式1,即int i = 1
,且表达式1只执行1次。依次重复执行表达式2、表达式3、表达式4,知道表达式2的判断条件不再满足。
下面我们来对比一下while和for循环↓↓↓
#include <stdio.h>
int main()
{
int i = 0;
while(i <= 10)
{
printf("jammingpro\n");
//这里可能还要很多很多代码
i++;//导致调整条件和其他部分偏离较远
}
for(int j = 0; j <= 10; j++)
{
printf("xiaoming\n");
}
return 0;
}
可以发现在while循环中依然存在循环的三个必须条件(初始化,循环判断条件,调整条件),但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹。 for循环使用的频率也最高。
学习完for循环,我们也要小测一下( ̄︶ ̄)↗
( ఠൠఠ )ノ测试1:下面代码将输出什么?
#include <stdio.h>
int main()
{
for(int i = 0; i <= 10; i++)
{
if(i == 5)
continue;
if(i == 8)
break;
printf("%d ", i);
}
printf("\n");
return 0;
}
揭晓答案:0 1 2 3 4 6 7
。当i==5
时,将不会执行循环体的后序语句,将执行表达式i++
及i<=10
,再进入循环体。当i==8
时,执行了break语句后,将跳出整个for循环。
( ఠൠఠ )ノ测试2:下面代码将会怎么样
#include <stdio.h>
int main()
{
for(;;)
{
printf("running......\n");
}
return 0;
}
揭晓答案:这段代码将无限次打印"running…"。当for循环的判断条件不写时,则循环条件永远为真,会一直执行循环体。
( ఠൠఠ )ノ测试3:下面代码将输出什么?
#include <stdio.h>
int main()
{
int m = 0;
int n = 0;
for(m = 1, n = 2; m <= 2 && n <= 2; m++, n++)
{
printf("hahaha!!\n");
}
return 0;
}
揭晓答案:打印一行hahaha!!
。for循环先执行表达式1,即m = 1, n = 2
;再执行表达式2,即m <= 2 && n <= 2
,因为表达式成立,所以进入循环体,打印"hahaha!!";再执行表达式3,即m++, n++
,此时m变为2,n变为3;最后执行表达式2时,条件不再满足,故退出循环。
( ఠൠఠ )ノ测试4:下面代码的循环,将循环多少次?
#include <stdio.h>
int main()
{
for(int k = 0; k = 8; k++)
{
printf("running......\n");
}
return 0;
}
揭晓答案:将会无限次循环。k = 8
是一条赋值语句,返回值等于k被赋值的结果,也就是8。因为8不是0,判断条件恒为真,故循环不会停止。
do…while语句
do…while语句和while、for语句的区别是:do…while语句都会先执行1次循环体,再判断循环条件是否成立。
以下面代码为例,虽然循环条件不成立,但还是会执行一次循环体,打印一行“good offer”。↓↓↓
#include <stdio.h>
int main()
{
int i = -1;
do
{
printf("good offer\n");
}while(i > 0);
return 0;
}
所以,我们可以总结出do…while语句的特点:循环至少执行一次,使用的场景有限,所以不是经常使用。
goto语句
C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。
从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。
但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程,例如一次跳出两层或多层循环。
这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。
下面是使用goto语句的一个例子:
#include <stdio.h>
int main()
{
for(int i = 0; i < 100; i++)
{
for(int j = 0; j < 100; j++)
{
for(int k = 0; k < 100; k++)
{
//执行的语句
goto endcir;
}
}
}
endcir:
printf("退出循环");
}
上面代码中,当执行到goto endcir
语句时,程序将自动跳转到endcir
所在行,再继续向下执行。
我们也可以使用goto语句实现循环,下面是一个关机程序,当用户在60秒内输入"Jammingpro"才能取消关机。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char ch[100] = {0};
system("shutdown -s -t 60");
again:
printf("请输入Jammingpro,否则程序将在启动后60秒后关机>");
scanf("%s", ch);
if(strcmp("Jammingpro", ch) == 0)
{
printf("程序终止\n");
}
else
{
printf("输入有误\n");
goto again;
}
return 0;
}
循环应用案例
猜数字游戏
需求是这样的:程序生成1到100的随机数,用户输入数字进行猜测,如果猜大了,则提示用户猜大了;如果猜小了,则提示用户猜小了;如果猜对了,则提示用户猜对了,并询问是否再来一轮。
首先,我们可以先实现一个菜单函数
void menu()
{
printf("***************************************************\n");
printf("**************** 1.play 0.exit ****************\n");
printf("***************************************************\n");
}
下面,我们实现一下主函数,用于接收用户选择开始游戏,还是退出游戏。
int main()
{
int input = 0;
do
{
menu();
printf("请输入选择>");
scanf("%d", &input);
switch(input)
{
case 1:
game();//这个函数稍后实现
break;
case 0:
printf("成功退出\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
}while(input);
return 0;
}
最后就是要实现,猜数字了。
★ps:rand()函数位于stdlib库中,用于生成随机数。它可以生成0到32767的随机数。如果我们要生成1到100,我们可以使用rand()%100,则它会生成0到99;rand()%100+1,就可以生成1到100的随机数了。
void game()
{
int guess = rand() % 100 + 1;
int input = 0;
while(1)
{
printf("请输入你的猜测>");
scanf("%d", &input);
if(input > guess)
{
printf("猜大了\n");
}
else if(input < guess)
{
printf("猜小了\n");
}
else
{
printf("恭喜你猜对了\n");
break;
}
}
}
但是,rand()每次生成的随机数都是一样,每次生成的随机数都是42、68、35…。应该怎么解决呢?我们需要在main函数中添加srand((unsigned int)time(NULL));
,就可以实现真正产生随机数了。
★ps:rand()函数通过自己的一套数学公式,借助随机数种子(随机数种子就是一个数值)计算出一个随机数。只有随机数种子不同,才会产生不同的随机数。我们可以通过给它传入时间,这样随机数的数值就不会重复了。(unsigned int)time(NULL)
就表示时间,这个时间是从1970年1月1日0时到当前经过的秒数。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void game()
{
int guess = rand() % 100 + 1;
int input = 0;
while(1)
{
printf("请输入你的猜测>");
scanf("%d", &input);
if(input > guess)
{
printf("猜大了\n");
}
else if(input < guess)
{
printf("猜小了\n");
}
else
{
printf("恭喜你猜对了\n");
break;
}
}
}
void menu()
{
printf("***************************************************\n");
printf("**************** 1.play 0.exit ****************\n");
printf("***************************************************\n");
}
int main()
{
srand((unsigned int)time(NULL));
int input = 0;
do
{
menu();
printf("请输入选择>");
scanf("%d", &input);
switch(input)
{
case 1:
game();//这个函数稍后实现
break;
case 0:
printf("成功退出\n");
break;
default:
printf("输入有误,请重新输入\n");
break;
}
}while(input);
return 0;
}
折半查找
从上面的猜数字中,我们猜数字时总会选择从中间开始猜,先猜50,如果猜小了,我们会猜75,依次类推…
当我们面对一个有序的数组时,我们也可以采用这种思想来查找一个数值。下面,我是用一个1到10的有序数组,演示如何查找数字7。
其中,我们定义一个left = 0,right = len - 1。因为数组有序,则left所在数值是最小值,right所在位置为最大值。通过mid=(left + right) / 2,计算出中间数值,如果该数值大于待查找数值,则待查找数值位于mid所在位置的左侧;如果该数值小于待查找数值,则待查找数值位于mid所在位置的右侧。当right<left时,说明待查找数值不存在。
下面我们来看一下实现代码↓↓↓
#include <stdio.h>
int binarySearch(int arr[], int len, int k)
{
int left = 0;
int right = len - 1;
int mid = 0;
while(left <= right)
{
mid = (left + right) / 2;
if(arr[mid] < k)
{
left = mid + 1;
}
else if(arr[mid] > k)
{
right = mid - 1;
}
else
{
return mid;//找到了,返回下标
}
}
return -1;//没有找到
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int len = sizeof(arr) / sizeof(arr[0]);
int index = binarySearch(arr, len, 7);
if(index != -1)
{
printf("找到了!7位于下标%d\n", index);
}
else
{
printf("没找到\n");
}
return 0;
}
🚩这篇文章结束了~~
如果文章中出现了错误,欢迎私信或留言。(๑•̀ㅂ•́)و✧
有任何疑问请评论或私信哦~~o( ̄▽ ̄)ブ