<C语言>循环语句

循环

经过初识C语言(二)我们已经知道循环语句包含了

while

do…while

for

仔细想一想,在现实生活当中,我们每个人总要在同一件事情上反复完成很多次,比如睡觉前闭眼,早上醒来后第一件事情睁眼。

while

//while语法结构
while(表达式)
{
    语句;	//循环体
}

while流程图:

image-20230104124229059

执行while语句时,首先计算控制表达式的值,如果值为真,则执行语句(循环体),然后判定是否满足表达式。重复执行,直至控制表达式为零则停止循环。

在大学,每次到达指定教室后,在正式上课前,老师都会发起一个签到,来监督学生是否到达教室进行听课,以此记录学生的出勤率并将其纳入平时成绩。

假设该班共有十名同学,老师发起签到后,每个同学都到达课堂并签到。

#include <stdio.h>
int main()
{
	int stu = 1;
	while (10 >= stu)
	{
		printf("学生%d,签到成功!\n", stu);
		stu++;
	}
	return 0;
} 

运行结果:

image-20230104133446764

若控制表达式的值始终为真,则while语句将无限循环

突然老师有一天不下心将签到发到了她所任教的全部班课中,于是会出现这种情况。

#include <stdio.h>
int main()
{
	int stu = 1;
	while (1)
	{
		printf("学生%d,签到成功!\n", stu);
		stu++;
	}

运行结果:

while

while语句中的break和continue

通过上面的代码,已经了解了while语句的基本语法和使用

在分支语句中,已经浅浅的介绍过break语句在switch语句中的使用方法

在这里再介绍一下循环语句中break和continue在while中的使用方法

在课堂上,老师通常会选择一种抢答的方式来让学生主动回答问题。

break

那我们只选择前三名抢到的同学来回答问题,可以用如下代码:

#include <stdio.h>
int main()
{
	int i = 0;
	while (10 >= i)
	{
		i++;
		if (4 == i)
		{
			break;
		}
		printf("第 %d 个同学已抢答! \n", i);

	}
	return 0;
}

运行结果:

image-20230104163031292

其实在循环中只要遇到break,就停止后期的所有的循环,直接终止循环。所以:while中的break是用于永久终止循环

continue

其他同学因为上课抢不到前三很沮丧,老师为了能让他们也有参与感,于是就规定了抢到偶数前三名同学才可以回答问题

#include <stdio.h>
int main()
{
	int i = 0;
	int t = 0;
	while (10 >= i)
	{
		i++;
		if (i%2!=0)
		{
			t++;
			continue;
		}
		printf("第 %d 个同学已抢答! \n", i);
		if (t == 3)
		{
			break;
		}
	}
	return 0;
}

运行结果:

image-20230104163431777

continue是用于终止本次循环

也就是本次循环中,continue后边的代码不会再执行,而是直接跳转到while语句的判断部分。进行下一次循环的入口判断

输入一堆字符,只打印数字字符,跳过其他字符

#include <stdio.h>
int main()
{
	char ch = '\0';
	while ((ch = getchar()) != EOF)
	{
		if (ch < '0' || ch > '9')
			continue;
		putchar(ch);
	}
	return 0;
}

运行结果:

image-20230105104542304

do…while

do语句的本质就是while语句,其控制表达式是在每次执行完循环体之后进行判定。

while语句中的循环体可一次不执行,而do…while语句中的循环体最少执行一次

//do...while语法结构
do
{
    语句;	//循环体 可为一条语句或复合语句
}while(表达式);

do…while语句流程图:

image-20230105174656847

执行do…while语句时,先执行语句(循环体),再计算控制表达式的值。若表达式值非零,则再次执行语句(循环体),当表达式的值为零时,则终止do…while语句的循环。

do…while语句中的break和continue

do…while循环中也可以出现break和continue,他们的意义和在while循环中是一样的。沿用while循环中的例子,我们可以使用do…while循环这么写。

break
#include <stdio.h>
int main()
{
	int i = 0;
	do
	{
		i++;
		if (4 == i)
		{
			break;
		}
		printf("第 %d 个同学已抢答! \n", i);

	}while (10 >= i);
	return 0;

运行结果:

image-20230106125021014

continue
#include <stdio.h>
int main()
{
	int i = 0;
	int t = 0;
	do
	{
		i++;
		if (i % 2 != 0)
		{
			t++;
			continue;
		}
		printf("第 %d 个同学已抢答! \n", i);
		if (t == 3)
		{
			break;
		}
	} while (10 >= i);
	return 0;
}

运行结果:

image-20230106125217962

for

for循环与while相比更优渥

//for语句语法结构
for(表达式1; 表达式2; 表达式3)
{
    循环语句;
}

for语句流程图:

image-20230105175225609

表达式1为初始化部分,用于初始化循环变量的。

表达式2为条件判断部分,用于判断循环时候终止。

表达式3为调整部分,用于循环条件的调整 。

先计算表达式1,然后判断是否满足表达式2,若满足则执行循环语句,再计算表达式3,判断是否满足表达式2,若满足则继续,若不慢则表达式2则终止for循环。

//for循环可用等价的while循环替代
表达式1;
while(表达式2)
{
    语句;
    表达式3;
}

例如:

int i = 0;
//使用while
i=1;//初始化部分
while(i<=10)//判断部分
{
    printf("hehe\n");
    i = i+1;//调整部分
}
//使用for
for(i=1; i<=10; i++)
{
    printf("hehe\n");
}

for语句中的break和continue

for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。

break

沿用while循环中的例子,我们可以使用for循环这么写

#include <stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)
	{
		printf("第 %d 个同学已抢答! \n", i);
		if (i == 3) 
		{
			break;
		}
	}
	return 0;
}

运行结果:

image-20230105181019031

continue
#include <stdio.h>
int main()
{
	int i = 0;
	int t = 0;
	for (i = 1; i <= 10; i++)
	{
		if (i % 2 == 0)
		{
			if (t == 3)
			{
				continue;
			}
			printf("第 %d 个同学已抢答! \n", i);
			t++;
		}
	}	
	return 0;
}

运行结果:

image-20230105181916079

for语句变种

#include <stdio.h>
int main()
{
	//代码1(死循环)
	for (;;)
	{
		printf("hehe\n");
	}
	//for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问题。
	//代码2
	int i = 0;
	int j = 0;
	//这里打印多少个hehe?
	for (i = 0; i < 10; i++)
	{
		for (j = 0; j < 10; j++)
		{
			printf("hehe\n");
		}
	}
	//代码3
	int i = 0;
	int j = 0;
	//如果省略掉初始化部分,这里打印多少个hehe?
	for (; i < 10; i++)
	{
		for (; j < 10; j++)
		{
			printf("hehe\n");
		}
	}
	//代码4-使用多余一个变量控制循环
	int x, y;
	for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
	{
		printf("hehe\n");
	}
	return 0;
}

goto语句

C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。

从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。

但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过
程。

例如:一次跳出两层或多层循环。

多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环

C 语言中的 goto 语句允许把控制无条件转移到同一函数内的被标记的语句。

注意: 在任何编程语言中,都不建议使用 goto 语句。因为它使得程序的控制流难以跟踪,使程序难以理解和难以修改。任何使用 goto 语句的程序可以改写成不需要使用 goto 语句的写法。

//goto语句语法
goto label;
..
.
label: statement;
//label 可以是任何除 C 关键字以外的纯文本,它可以设置在 C 程序中 goto 语句的前面或者后面

goto语句流程图

C goto 语句

scanf

scanf 类型说明符:

类型合格的输入
%a、%A读入一个浮点值(仅 C99 有效)。
%c单个字符:读取下一个字符。如果指定了一个不为 1 的宽度 width,函数会读取 width 个字符,并通过参数传递,把它们存储在数组中连续位置。在末尾不会追加空字符。
%d十进制整数:数字前面的 + 或 - 号是可选的。
%e、%E、%f、%F、%g、%G浮点数:包含了一个小数点、一个可选的前置符号 + 或 -、一个可选的后置字符 e 或 E,以及一个十进制数字。两个有效的实例 -732.103 和 7.12e4
%i读入十进制,八进制,十六进制整数 。
%o八进制整数。
%s字符串。这将读取连续字符,直到遇到一个空格字符(空格字符可以是空白、换行和制表符)。
%u无符号的十进制整数。
%x、%X十六进制整数。
//%d %d是按十进值格式输入数值。输入时,在两个数据之间可以用一个或多个空格、tab 键、回车键分隔。
//&a,&b中的 & 是地址运算符,分别获得变量的内存地址。
//3,4
//3 4
//3
//4   
scanf("%d %d",&a,&b);

//如果使用 , 来分隔输入的 %d, 相应的输入时也需要添加,
//3,4
scanf("%d,%d",&a,&b);

//这里没有使用&是因为arr是一个数组,而数组的首元素就是地址
scanf("%s",arr);,

getchar

getchar(获取字符),存放在int类型内。

//getchar函数的基本原型

int ch = getchar(void);
  1. getchar返回字符的ASCII码值,ASCII码值是整数,存放在整型变量中。
  2. getchar函数读取失败的时候返回EOF,EOF的本质是-1,是一个整型值,在一个char类型的变量中,是无法存储的。
  3. 结合getchar函数的原型,getchar的返回类型被定义为int,那么返回的数据就应该存放在int变量中。

putchar

//putchar函数声明
int putchar(int char)

字符以其对应的 int 值进行传递

该函数将指定的表达式的值所对应的字符输出到标准输出终端上。表达式可以是字符型或整型,它每次只能输出一个字符

//putchar函数的基本格式为:
putchar(ch);

实例

//单个输入输出
#include <stdio.h>
int main()
{
	int	ch = getchar();	//接收字符
	putchar(ch);	//输出字符
	return 0;
}

运行结果:

image-20230104171535727

//循环输入输出
#include <stdio.h>
int main()
{
	int ch = 0;
    //EOF end of file 文件结束标志
	while ((ch = getchar()) != EOF)
	{
		putchar(ch);
	}
	return 0;
}

运行结果:

getchar

//getchar与scanf
#include <stdio.h>
int main()
{
	char password[20] = { 0 };
	printf("请输入密码:>");
	scanf("%s", password);
	printf("请确认密码(Y/N):");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("密码正确\n");
	}
	else
	{
		printf("密码错误\n");
	}
	return 0;
}

运行结果:

mima

???还没确认就没了???why???

mimaguoc

#include <stdio.h>
int main()
{
	char password[20] = { 0 };

	printf("请输入密码:>");
	scanf("%s", password);

	getchar();	//消除\n

	printf("请确认密码(Y/N):");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("密码正确\n");
	}
	else
	{
		printf("密码错误\n");
	}
	return 0;
}

运行结果1:

mimaguoch

运行结果2:多个字符便会失败

mimaguoch1

过程演示:

mimaguoch12

像这种该咋办?

#include <stdio.h>
int main()
{
	char password[20] = { 0 };

	printf("请输入密码:>");
	scanf("%s", password);
	int tmp = 0;
	while (tmp=getchar()!='\n')
	{
		;	//空语句
	}
	printf("请确认密码(Y/N):");
	int ch = getchar();
	if (ch == 'Y')
	{
		printf("密码正确\n");
	}
	else
	{
		printf("密码错误\n");
	}
	return 0;
}

运行结果:
在这里插入图片描述

可通过while循环实现多次读入字符

scanf() 可输入不包含空格的字符串,不读取回车,空格和回车表示输入完毕。

getchar() 只能读取用户输入缓存区的一个字符,包括回车。

实例补知识

  1. 计算 n 的阶乘。
#include <stdio.h>
int main()
{
	int n = 0, i;
	int sum = 1;
	scanf("%d", &n);
	for (i = 1; i <= n; i++)
	{
		sum = sum * i;	//1*2*3*4*5*...*n
	}
	printf("%d", sum);
	return 0;
}

运行结果:

image-20230106140140056

  1. 计算 1!+2!+3!+……+10!
#include <stdio.h>
int main()
{
	int n = 0, i = 0;
	int sum = 1;
	for (i = 1; i <= 10; i++)
	{
		sum = sum * i;
		n = n + sum;
	}
	printf("%d\n", n);
	return 0;
}

运行结果:

image-20230106140534466

  1. 在一个有序数组中查找具体的某个数字n。(二分查找/折半查找)

二分查找/折半查找,要求是有序数组

什么是二分查找/折半查找?

例如:我们要在1-10之间查找一个数字7

怎么找呢?

1.挨个找,从1开始往后挨个查找,最坏找10次

2.折半查找,每次取中间那个数比较,如下图

#include <stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);	//计算数组个数
	int left = 0;	//左下标
	int right = sz - 1;	//右下标
	int k = 7;	//要查找的数
	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;
}
  1. 编写代码,演示多个字符从两端移动,向中间汇聚
#include <stdio.h>
#include <string.h>
#include <Windows.h>
int main()
{
	char arr[] = "Happy New Year!";
	char brr[] = "###############";
	int left = 0;
	int right = strlen(arr) - 1;	//strlen 计算数组大小,是string.h头文件内命令
	while (left <= right)
	{
		brr[left] = arr[left];
		brr[right] = arr[right];
		printf("%s\n", brr);
		Sleep(1000);	//将目前动作延迟一段时间,是Windows.h头文件内命令
		left++;
		right--;
	}
	return 0;
}

运行结果:

shuangxiangbenfu

同一行多个字符从两端移动,向中间汇聚

#include <stdio.h>
#include <string.h>
#include <Windows.h>
#include <stdlib.h>
int main()
{
	char arr[] = "Happy New Year!";
	char brr[] = "###############";
	int left = 0;
	int right = strlen(arr) - 1;	//strlen 计算字符串长度.
	while (left <= right)
	{
		brr[left] = arr[left];
		brr[right] = arr[right];
		printf("%s\n", brr);
		Sleep(1000);	//将目前动作延迟一段时间,单位是毫米,是Windows.h头文件内命令
		system("cls");	//清理屏幕,是stdlib.h头文件内命令
		left++;
		right--;
	}
	printf("%s\n", brr);
	return 0;
}

strlen(str),是string.h头文件内命令

str – 要计算长度的字符串

该函数返回字符串的长度

直到空结束字符,但不包括空结束字符

运行结果:

shuangxiangbenfu155

  1. 编写代码实现,模拟用户登录情景,并且只能登录三次。(只允许输入三次密码,如果密码正确则提示登录成功,如果三次均输入错误,则退出程序)。
#include <stdio.h>
#include <string.h>
int main()
{
	//正确密码为ayw123456
	char password[20] = { 0 };
	int i = 0;
	for (i = 0; i < 3; i++)
	{
		scanf("%s", password);
		if (strcmp(password, "ayw123456") == 0)
		{
			printf("密码正确,登录成功!\n");
			break;
		}
		else
		{
			printf("密码错误,请重新输入!\n");
		}
	}
	if(i == 3)
	{
		printf("连续三次输入错误,登录失败!\n");
	}
	return 0;
}

strcmp(str1,str2),是string.h头文件内命令

str1 – 要进行比较的第一个字符串。

str2 – 要进行比较的第二个字符串。

该函数返回值如下:

如果返回值小于 0,则表示 str1 小于 str2。

如果返回值大于 0,则表示 str1 大于 str2。

如果返回值等于 0,则表示 str1 等于 str2。

只能比较字符串,即可用于比较两个字符串常量,或比较数组和字符串常量,不能比较数字等其他形式的参数。

  1. 猜数字小游戏
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void menu()
{
	printf("**********************************\n");
	printf("************* 1.play *************\n");
	printf("************* 0.exit *************\n");
	printf("**********************************\n");
}
//RAND_MAX--rand函数能返回随机数的最大值。
void game()
{
	int random_num = rand() % 100 + 1;
	int input = 0;
	while (1)
	{
		printf("请输入猜的数字>:");
		scanf("%d", &input);
		if (input > random_num)
		{
			printf("猜大了\n");
		}
		else if (input < random_num)
		{
			printf("猜小了\n");
		}
		else
		{
			printf("恭喜你,猜对了\n");
			break;
		}
	}
}
int main()
{
	int input = 0;
	srand((unsigned)time(NULL));
	do
	{
		menu();
		printf("请选择>:");
		scanf("%d", &input);
		switch (input)
		{
            case 1:
                game();
                break;
            case 0:
                break;
            default:
                printf("选择错误,请重新输入!\n");
                break;
		}
	} while (input);
	return 0;
}

rand( ),随机数发生器,所在头文件 stdlib.h

rand( ),该函数返回一个范围在 0 到 RAND_MAX 之间的整数值。

要取得 [a,b) 的随机整数,使用 (rand() % (b-a))+ a;

要取得 [a,b] 的随机整数,使用 (rand() % (b-a+1))+ a;

要取得 (a,b] 的随机整数,使用 (rand() % (b-a))+ a + 1;

通用公式: a + rand() % n;其中的 a 是起始值,n 是整数的范围。

要取得 a 到 b 之间的随机整数,另一种表示:a + (int)b * rand() / (RAND_MAX + 1)。

要取得 0~1 之间的浮点数,可以使用 rand() / double(RAND_MAX)。

srand( ),初始化随机数发生器,所在头文件 stdlib.h

srand( ) 用来设置 rand() 产生随机数时的随机数。参数 seed 必须是个整数,如果每次 seed 都设相同值,rand( ) 所产生的随机数值每次就会一样。

rand( ) 产生的随机数在每次运行的时候都是与上一次相同的。若要不同, 用函数 srand() 初始化它。可以利用 srand((unsigned int)(time(NULL)) 的方法,产生不同的随机数,因为每一次运行程序的时间是不同的。

给srand( )提供一个数,它是一个unsigned int类型;

以上rand与srand来源于 RUNOOB.com

运行结果:

image-20230106185435067

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾莜薇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值