循环语句 · while · for · do while
一、while 循环语句
我们已经掌握了 if 语句:
if (条件) {
语句;
}
当条件满足的时候,会执行 if 后面的代码,否则就不执行。但是这个 if 语句只会执行一次。
不过,我们生活中有很多事情是要重复很多次的。
那我们在代码中是如何实现的呢?C语言给我们引入了:while 语句,可以实现循环。。
1. while 语句的结构:
while (表达式) {
循环语句;
}
我们看 while 语句的结构是和 if 语句很相似的,相似但不是完全相似。
if 中的括号,如果判断为真就执行一次语句。
while括号中判断为真就执行一次语句,然后再判断括号中是否为真,如果为真就再执行一次。循环此操作直到判断括号中语句为假,就跳出 while 语句。
看不懂上面的丑图,就看段简单的代码吧,了解 while 的基本语法。
//打印 1-10 到屏幕上
#include <stdio.h>
int main() {
int i = 1; //定义个变量
while (i <= 10) { //while 语句的主体结构,括号选择范围
printf("%d\n", i); //简单的打印语句
i++; //让变量每次+1,实现下次打印下一位数字
}
return 0;
}
2. while 语句中的 break 和 continue:
break介绍
#include <stdio.h>
int main() {
int i = 1;
while (i <= 10) {
if (5==i) {
break;
}
printf("%d\n", i);
i++;
}
return 0;
}
这段代码输出什么结果?
输出到1,2,3,4就终止程序了。
没错,因为 break 是用于跳出循环的关键字,循环内遇到 break,后面的语句都不会执行。
continue介绍
#include <stdio.h>
int main() {
int i = 1;
while (i <= 10) {
if (i == 5) {
continue;
}
printf("%d\n", i);
i++;
}
return 0;
}
这段代码输出结果是什么?
输出1,2,3,4。但是这个程序并没有出现结束标志,说明该程序卡住在 4 这里了。
再看一段对比的代码:
#include <stdio.h>
int main() {
int i = 0;
while (i <= 9) {
i++;
if (i == 5) {
continue;
}
printf("%d\n", i);
}
return 0;
}
这段代码把i++,提到前面,程序就可以正常结束了。
因为 continue 关键字是用于终止本次循环,或者说是跳过本次循环,continue 后面的代码都不用执行。直接开始到下一次循环的判断入口。
至于前一段代码没有正常结束,就是因为进入 continue 的时候,i 的值是 5。
continue 跳过本次循环,没有让 i++,直接跳到下一次循环的判断入口,导致此时的 i 还是 5 就进入循环,又遇到 continue,又跳过本次循环 … … 算是死循环了。
3. getchar() 和 putchar() 方法
来看代码了解一下:
代码一
//代码一:
#include <stdio.h>
int main() {
int ch = 0;
while ((ch = getchar()) != EOF) {
putchar(ch);
}
return 0;
}
这两个方法,每次只能操作一个字符。
getchar方法:从键盘缓冲区读取一个字符,存放在一个变量里面。遇到 ctrl + z 就会退出循环。
putchar方法:将刚刚存放字符的变量输出到屏幕。
代码二
//代码二:
#include <stdio.h>
int main() {
int ch = 0;
while ((ch = getchar()) != EOF) {
if (ch < '0' || ch>'9') {
continue;
}
putchar(ch);
}
return 0;
}
可以用于筛选字符串中的字符,以后也可以用于判断登录账号或者密码。
代码三
用于清除数据缓冲区的数据。
//代码三
int password[20] = { 0 };
printf("请输入密码:>");
scanf("%d", password);
printf("请确认密码(Y/N):>");
//清理缓冲区数据
int tmp = 0;
while ((tmp = getchar()) != '\n') {
;
}
int ch = getchar();
if (ch == 'Y') {
printf("确认成功\n");
}
else if (ch == 'N') {
printf("确认失败\n");
}
else {
printf("输入有误!\n");
}
二、for 循环语句
我们了解了 while 循环语句,为什么还要学习 for 循环语句?
因为 while 语句有些缺点:
while 语句的初始化、判断部分和调整部分都是独立分开的。
后期开发会在三个部分中间加很多代码,导致这三个部分不好集中操作。
1. for 语句的结构,以及和 while 语句对比:
for ( 初始化;条件判断部分;调整部分 ) {
循环语句;
}
初始化: 初始化循环变量。
条件判断部分:判断循环结构终止。
调整部分:循环条件的调整。
试着写段代码理解一下:
使用 for 循环在屏幕上输出 1-10 的数字。
//5.使用 for 循环在屏幕上输出 1-10 的数字
int i = 0;
//初始化-> i=1
//条件判断部分-> i<=10
//调整部分-> i++
for (i = 1; i <= 10; i++) {
printf("%d\n", i); //循环体
}
再与 while 循环对比一下:
int i = 1; //初始化
while (i <= 10) { //循环条件判断
printf("%d\n", i); //循环体
i++; //调整部分
}
对比总结:
while 循环结构分布没有 for 循环紧凑,后续可能因为开发中加入过多代码,导致三个部分太分散了。建议使用 for 循环。
2. break 和 continue 在 for 循环中:
for 循环中也是可以使用 break 和 continue 的,但是有一些差异。
- break 的使用没有问题,就是跳出本次循环。
int i = 0;
for (i = 1; i < 10; i++) {
if (i == 5) {
break;
}
printf("%d\n", i);
}
- continue 的使用就有差异。
不会像 while 一样程序卡死,而是会跳过本次循环,进入 for 循环的调整部分 i++,准备下一次循环。
int i = 0;
for (i = 1; i < 10; i++) {
if (i == 5) {
continue;
}
printf("%d\n", i);
}
3. for 语句的一些建议:
- 不可在 for 语句中修改循环变量,防止 for 循环失去控制。
- 建议 for 语句的循环控制变量的取值采用 前闭后开 的写法。
4. 补充 for 语句的变种:
for (;;) { //无限循环的for
printf("haha!\n");
}
int x, y; //有两个初始化值,两个条件判断,两个调整部分。
for (x = 0, y = 0; x < 2 && x < 5; ++x, y++) {
printf("hehe!");
}
5. 一道面试题:
请问循环要循环多少次?
#include <stdio.h>
int main()
{
int i = 0;
int k = 0;
for(i =0,k=0; k=0; i++,k++)
k++;
return 0;
三、do…while 循环语句
1. do…while 语法:
do
循环语句;
while(表达式);
2. do…while 语句的特点:
不管条件是否成立,必须会执行一遍循环体。
#include <stdio.h>
int main()
{
int i = 10;
do
{
printf("%d\n", i);
}while(i<10);
return 0;
}
3. do…while 循环中的 break 和 continue
-
break:和之前 for 循环一样,跳出循环,终止循环。
-
continue:取决于调整部分放在哪里,在 continue 前面不会造成程序卡死。但是调整部分放在 continue 后面会导致程序卡死。
四、几道关于循环的题目:
1. 计算 n 的阶乘。
int n = 0;
int sum = 1;
int i = 0;
scanf("%d", &n);
for (i = 1; i <= n; i++) {
sum = i * sum;
}
printf("%d\n", sum);
2. 计算 “1!+2!+3!+……+10!”。
有两种方法
int n = 0;
int i = 0;
int num = 1;
int sum = 0;
//1.0
for (n = 1; n <= 3; n++) {
num = 1;
for (i = 1; i <= n; i++) {
num *= i;
}
sum += num;
}
//2.0
for (n = 1; n <= 3; n++) {
num *= n;
sum += num;
}
printf("%d", sum);
3. 在一个有序数组中查找具体的某个数字n。 编写int binsearch(int x, int v[], int n); 功能:在v[0]<=v[1]<=v[2]<= ….<=v[n-1]的数组中查找x。
就是在有序的数组中,找到要求的数字。
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 7;
int sz = sizeof(arr) / sizeof(arr[0]); //计算数组中元素的个数
int left = 0; //定义左
int right = sz - 1; //定义右
int mid = 0; //定义中间
while (left <= right) {
mid = (left + right) / 2;
if (k > arr[mid]) {
left = mid + 1;
}
else if (k < arr[mid]) {
right = mid - 1;
}
else {
printf("恭喜你找到了,下标为%d\n", mid);
break;
}
}
if (left > right) {
printf("很抱歉没有找到!\n");
}
4. 编写代码,演示多个字符从两端移动,向中间汇聚。
char arr1[] = "welcome to bit!!!!!!";
char arr2[] = "####################";
int left = 0;
int right = strlen(arr1) - 1; //字符串函数,计算字符串长度
while (left <= right) {
arr2[left] = arr1[left]; //两个数组依次替换
arr2[right] = arr1[right];
printf("%s\n", arr2);
Sleep(1000); //使程序睡眠 1 秒
system("cls"); //清空输出屏
left++; //替换后让数组向后移动
right--;
}
printf("%s\n", arr2);
5. 编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成功,如果三次均输入错误,则退出程序。
char password[20] = { 0 };
int i = 0;
int mistake = 0;
printf("请输入密码:>");
for (i = 0; i < 3; i++) {
scanf("%s", password);
if (strcmp(password, "123456") == 0) { //字符串对比函数,相等返回数值0
printf("登录成功\n");
break;
}
else if (mistake == 2) {
printf("三次均输入错误,退出程序\n");
break;
}
else {
printf("密码输入错误,请重新输入:>");
mistake++;
}
}
6. 写一个猜数字游戏。
- 自动产生一个1-100之间的随机数
- 猜数字
a. 猜对了,就恭喜你,游戏结束
b. 你猜错了,会告诉猜大了,还是猜小了,继续猜,直到猜对 - 游戏一个一直玩,除非退出游戏
void menu() { //只是个菜单功能代码,仅仅为了展示页面。
printf("**********************************\n");
printf("********** 1. play ***********\n");
printf("********** 0. exit ***********\n");
printf("**********************************\n");
}
void game() { //猜数字游戏功能代码。
//1.生成随机数,用ret存储
//rand函数返回了一个0-32767之间的数字
//%100的余数是0-99,然后+1,范围就是1-100
int ret = rand() % 100 + 1;
printf("%d\n", ret);
//2.猜数字,用guess接收用户输入数据,来进行对比
int guess = 0;
while (1) {
printf("开始猜数字:>");
scanf("%d", &guess);
if (guess > ret) {
printf("猜大了!\n");
}
else if (guess < ret) {
printf("猜小了!\n");
}
else {
printf("恭喜你,猜中了!\n");
break;
}
}
}
int main() {
int input = 0;
//设置随机值的时间戳作为起点,srand()
//因为随机值需要一个一直变化的数据作为起点,所以使用time()函数
//最后随机值是整数,所以这里强转成int类型
//time函数需要数据传入,但是我们没有就设置NULL
srand((unsigned int)time(NULL));
do { //不多bb,上来直接玩
menu();
printf("请选择:>");
scanf("%d", &input);
switch (input) {
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input); //因为input输入0,可以直接退出循环。
return 0;
}