【C分支与循环】详解分支与循环

news2024/10/6 20:34:10

分支与循环

  • 前言
  • 一、什么是语句?
  • 二、分支语句(选择结构)
    • (一)概念
    • (二)if语句
      • 1.概念
      • 2.例子
        • (1)单分支
        • (2)双分支
        • (3)多分支
        • (4)小知识
      • 3.悬空else
      • 4.练习
        • (1)判断一个数是否为奇数
        • (2)输出1~100的奇数
    • (三)switch语句
      • 1.引例
      • 2.switch语句格式及case语句
      • 3. 在switch语句中的 break语句
      • 4.default子语句
      • 5.练习
  • 三、循环语句
    • (一)while循环语句
      • 1.语法
      • 2.流程图
      • 3.while语句中的break和continue
        • (1)break语句
          • (i)介绍
          • (ii)总结
        • (2)continue语句
          • (i)介绍
          • (ii)总结
      • 4.getchar()和putchar()
        • (1)简单介绍
        • (2)EOF
        • (3)scanf与getchar配合
        • (4)scanf与getchar配合升级版(while)
        • (4)练习
        • (5)scanf与printf
    • (二)for循环语句
      • 1.语法
      • 2.流程图
      • 3. break和continue在for循环中
      • 4. for语句的循环控制变量
      • 5.一些for循环的变种
        • (1)省略判断部分
        • (2)省略初始化部分
        • (3)使用多余一个变量控制循环
      • 6.练习题
    • (三)do……while循环语句
      • 1.do语句的语法
      • 2.do语句的特点
      • 3.do while循环中的break和continue
    • (四)区别
    • (五)练习
      • 1.计算n的阶乘
      • 2.计算 1!+2!+3!+……+n!
      • 3.在一个有序数组中查找具体的某个数字n
        • (1)二分查找的概念
        • (2)二分查找的思路和代码
      • 4.编写代码,演示多个字符从两端移动,向中间汇聚。
        • (1)解析及代码
        • (2)Sleep函数和system函数
      • 5.编写代码实现,模拟用户登录情景,并且只能登录三次。
      • 6.猜数字游戏
        • (1)思路
        • (2)rand函数
        • (3)srand种子函数
        • (4)time函数
        • (5)代码
  • 四、goto语句
    • (一)概念
    • (二)例子
  • 总结


前言

大家在学习C语言的前期,分支与循环是第一个接触的语句,分支与循环在C语言的学习中是很重要的,分支和循环是分开的概念,分支是有if和else两种语句,相当于一个很多选择的路,可以选择走哪条路。循环是进入这个条件以后只要在条件允许的范围内不断进行语句的重复。


一、什么是语句?

C语句可分为以下五类:

  1. 表达式语句
  2. 函数调用语句
  3. 控制语句
  4. 复合语句
  5. 空语句

今天要跟大家介绍的是控制语句。
控制语句用于控制程序的执行流程,以实现程序的各种结构方式(C语言支持三种结构:顺序结构、选择结构、循环结构),它们由特定的语句定义符组成。C语言的所有复杂程序都可以拆分开以下三种程序。
在这里插入图片描述

C语言有九种控制语句,可分成以下三类:

  1. 条件判断语句也叫分支语句:if语句、switch语句;
  2. 循环执行语句:do while语句、while语句、for语句;
  3. 转向语句:break语句、goto语句、continue语句、return语句。

二、分支语句(选择结构)

(一)概念

这就是一个很简单的分支语句;
在这里插入图片描述

(二)if语句

1.概念

有单分支,双分支和多分支三种概念,如下图所示:
在这里插入图片描述

括号很重要,一个花括号内部里面加语句块,放多少都可以,但一旦离开了这个花括号,离开的那个语句就不能受到维护,所以如果你想要在一个if语句内部加很多语句,那花括号是至关重要的,因为if语句默认维护一条语句。

2.例子

(1)单分支

#include<stdio.h>

int main() {
	int age = 0;
	scanf("%d", &age);

	if (age >= 18) {
		printf("成年\n");
	}
	
	return 0;
}

在这里插入图片描述

(2)双分支

#include<stdio.h>

int main() {
	int age = 0;
	scanf("%d", &age);

	if (age >= 18) {
		printf("成年\n");
	}
	else {
		printf("未成年\n");
	}
	return 0;
}

在这里插入图片描述

(3)多分支

#inclue<stdio.h>

int main() {
	int age = 0;
	scanf("%d", &age);

	if (age < 16) {
		printf("少年\n");
	}
	else if (age >= 16 && age < 30) {
		printf("青年\n");
	}
	else if (age >= 30 && age < 40) {
		printf("中年\n");
	}
	else if (age >= 40 && age < 56) {
		printf("壮年\n");
	}
	else if (age >= 56 && age < 80) {
		printf("老年\n");
	}
	else {
		printf("老寿星\n");
	}
	return 0;
}

在这里插入图片描述

(4)小知识

1.在C语言中,0表示假,非0表示真。
2.当我们在写if语句的时候,我们可以把常量放在==的左边,这样编译器会报错,而不是警告,因为常量不能被赋值。
3.关于函数返回值的问题,但是下面这串代码最好不要用,不规范。在这里插入图片描述

3.悬空else

else到底和谁匹配呢?else与离它最近的一个if匹配。

#include <stdio.h>

int main()
{
	int a = 0;
	int b = 2;
	if (a == 1)
		if (b == 2)
			printf("hehe\n");
	else
		printf("haha\n");
	return 0; //什么也输出不了
}
//else是与它最近的if匹配的
//所以代码风格很重要,而且适当地加{}是很重要的
//以下代码是标准代码
#include <stdio.h>

int main(){
	int a = 0;
	int b = 2;
	if (a == 1){
		if (b == 2){
			printf("hehe\n");
		}
	}
	else{
		printf("haha\n");
	}
	return 0;
}

在这里插入图片描述

4.练习

(1)判断一个数是否为奇数

//判断一个数是否为奇数
#include<stdio.h>

int main() {
	int a = 0;
	scanf("%d", &a);
	if (a % 2 == 0) {
		printf("不是奇数\n");
	}
	else {
		printf("是奇数\n");
	}
	return 0;
}

(2)输出1~100的奇数

#include<stdio.h>

int main() {
	//1.循环先产生1~100的数字
	//2.判断产生的数字是否为奇数
	//3。是奇数打印
	int i = 0;
	for (i = 1; i <= 100; i++) {
		if (i % 2 == 1) {
			printf("%d ", i);
		}
	}
	
	return 0;
}

在这里插入图片描述

(三)switch语句

**概念:**switch语句也是一种分支语句,常常用于多分支的情况。
格式:

1.引例

在这里插入图片描述
如果用if…else语句进行做也是可以的,但未免形式有点复杂。如下:

#include<stdio.h>

int main() {
	int d = 0;
	scanf("%d", &d);
	if (1 == d) {
		printf("星期1\n");
	}
	else if (2 == d) {
		printf("星期2\n");
	}
	else if (3 == d) {
		printf("星期3\n");
	}
	else if (4 == d) {
		printf("星期4\n");
	}
	else if (5 == d) {
		printf("星期5\n");
	}
	else if (6 == d) {
		printf("星期6\n");
	}
	else if (7 == d) {
		printf("星期7\n");
	}
	return 0;
}

这种方法有点麻烦,而这里我们引进了switch语句来解决这个问题。

2.switch语句格式及case语句

switch语句的格式是:
在这里插入图片描述
语句项:
在这里插入图片描述

如下代码:

#include<stdio.h>

int main() {
	int d = 0;
	scanf("%d", &d);
	switch (d) {
	case 1:
		printf("星期1\n");
	case 2:
		printf("星期2\n"); 
	case 3:
		printf("星期3\n");
	case 4:
		printf("星期4\n");
	case 5:
		printf("星期5\n");
	case 6:
		printf("星期6\n");
	case 7:
		printf("星期7\n");
	}
	
	return 0;
}

这个代码看起来很正常,但是我们通过打印试一下是什么:
在这里插入图片描述
这什么情况!?怎么打印了星期5,星期6和星期7呢?我们画图来分析一下:
在这里插入图片描述

3. 在switch语句中的 break语句

break语句就相当于一个出口,当case语句进入的时候,它没有出口出去,只能一直往下执行,就像你大中午在敲代码,敲呀敲呀一直没个头,只有你妈妈说:“吃饭了”,你才拔腿就去吃饭,因为是要有一个break出口和你说你可以输出了,可以进行打印了。代码如下:

#include<stdio.h>

int main() {
	int d = 0;
	scanf("%d", &d);
	switch (d) {
	case 1:
		printf("星期1\n");
		break;
	case 2:
		printf("星期2\n"); 
		break;
	case 3:
		printf("星期3\n");
		break;
	case 4:
		printf("星期4\n");
		break;
	case 5:
		printf("星期5\n");
		break;
	case 6:
		printf("星期6\n");
		break;
	case 7:
		printf("星期7\n");
		break;
	}
	return 0;
}

这下是不是可以正常输出了!
那当然了,如果你想把星期1,2,3,4,5输出为weekday,星期6,7输出为weekend,那同样可以使用switch来实现,此时的实现过程更加简洁,不用费老大心思去一个个敲了,而是相同类型的一项不需要重复打印,利用break出口语句即可,如果大家不理解,上代码和画图解释:

int main() {
	int d = 0;
	scanf("%d", &d);
	switch (d) {
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
		printf("weekday\n");
		break;
	case 6:
	case 7:
		printf("weekend\n");
		break;
	}
	return 0;
}

在这里插入图片描述
所以大家在未来使用break语句的时候可以根据实际情况进行更加简洁化的处理。

注意:所以大家在最后一个 case 语句的后面加上一条 break语句。

4.default子语句

1.如果表达的值与所有的case标签的值都不匹配怎么办?
结构就是所有的语句都被跳过而已。程序并不会终止,也不会报错,因为这种情况在C中并不认为是个错误。
2.如果你并不想忽略不匹配所有标签的表达式的值时该怎么办呢?
你可以在语句列表中增加一条default子句,把下面的标签default:写在任何一个 case 标签可以出现的位置。
当 switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。所以,每个switch语句中只能出现一条default子句。但是它可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句。

如下代码:

#include<stdio.h>

int main() {
	int d = 0;
	scanf("%d", &d);
	switch (d) {
	case 1:
		printf("星期1\n");
		break;
	case 2:
		printf("星期2\n"); 
		break;
	case 3:
		printf("星期3\n");
		break;
	case 4:
		printf("星期4\n");
		break;
	case 5:
		printf("星期5\n");
		break;
	case 6:
		printf("星期6\n");
		break;
	case 7:
		printf("星期7\n");
		break;
	default:
		printf("输错啦!\n");
		break;
	}
	return 0;
}

5.练习

大家可以看一下以下的这个代码思考一下m和n的值:

#include <stdio.h>
int main(){
	int n = 1;
	int m = 2;
	switch (n){
	case 1:
		m++;
	case 2:
		n++;
	case 3:
		switch (n){//switch允许嵌套使用
		case 1:
			n++;
		case 2:
			m++;
			n++;
			break;
		}
	case 4:
		m++;
		break;
	default:
		break;
	}
	printf("m = %d, n = %d\n", m, n);
	return 0;
}

在这里插入图片描述
所以答案为m=5,n=3。


三、循环语句

在这里插入图片描述

(一)while循环语句

1.语法

我们已经掌握了if语句,当条件满足的情况下,if语句后的语句执行,否则不执行。但是这个语句只会执行一次。由于我们发现其实生活中很多实际的例子是同一件事情我们需要完成很多次。那我们怎么做呢?C语言中给我们引入了: while 语句,可以实现循环。
在这里插入图片描述
while语句的三元素:
在这里插入图片描述

2.流程图

while语句的流程图:
在这里插入图片描述

大家可能很难理解这张图片,那我们往后来解释一下吧!

我们想打印1~10的数,代码如下:

在这里插入图片描述

3.while语句中的break和continue

(1)break语句

(i)介绍

在这里插入图片描述

(ii)总结

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

(2)continue语句

(i)介绍

大家可以想一下下面这个代码是多少。
在这里插入图片描述

相信大家大多数认为应该是1 2 3 4 6 7 8 9 10,但实际上不是这样的,我们进入调试窗口一看!
在这里插入图片描述

发现死循环了,i的值一直是5,不会发生增加和减少。这是为什么呢?continue是跳过本次之后的循环,直接跳到while循环判断部分,这串代码continue;后面的花括号之前是没有语句的,所以跳到iwhile语句进行判断,而此时语句还未运行到打印和i自增1这些语句,而i一直是5没变,所以就发生死循环了。

(ii)总结

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

4.getchar()和putchar()

(1)简单介绍

当我们想要读入数据的时候,相信大家常用的是scanf,那同样还有一对函数叫做getchar()和putchar()来进行读取字符和输出字符。
在这里插入图片描述
大家可以打开MSDN看一下getchar和putchar函数的具体内容:
在这里插入图片描述
在这里插入图片描述

(2)EOF

End Of File - 既是scanf未成功输入的返回值,又是getchar未成功输入的返回值。
如下代码:
在这里插入图片描述

(3)scanf与getchar配合

在这里插入图片描述
这是什么原因呢?看画图分析:
在这里插入图片描述
scanf很倔啊,只拿走它想要的字符串,\n是直接留下来了不拿走,所以这个\n是由后面的getchar拿走的。

正确代码:

#include<stdio.h>

//%c - 字符
//%s - 字符串
//%d - 整型
//%f - 浮点型
int main() {
	//数组名本来就是地址
	char password[10] = { 0 };
	int ch = 0;
	printf("请输入密码:>\n");
	scanf("%s", password);
	//消除\n - 清理输入缓存区
	getchar();
	printf("请确认密码(Y/N):>\n");
	ch = getchar();
	if (ch == 'Y') {
		printf("确认成功\n");
	}
	else {
		printf("确认失败\n");
	}
	return 0;
}

在这里插入图片描述

(4)scanf与getchar配合升级版(while)

在现实生活中,有没有一种情况,当我输入密码的时候,不小心后面多输入了一个空格,结果是连Y/N都没显示出来,编译器就立马说输入错误,这是因为在输入缓冲区里存放了很多无关紧要的元素,而一个getchar只能清除一个元素,所以,这时候需要一个循环来解决,上代码:

#include<stdio.h>

//%c - 字符
//%s - 字符串
//%d - 整型
//%f - 浮点型
int main() {
	//数组名本来就是地址
	char password[10] = { 0 };
	int ch = 0;
	printf("请输入密码:>\n");
	scanf("%s", password);
	//消除\n - 清理输入缓存区
	while (getchar() != '\n') {
		;
	}
	printf("请确认密码(Y/N):>\n");
	ch = getchar();
	if (ch == 'Y') {
		printf("确认成功\n");
	}
	else {
		printf("确认失败\n");
	}
	return 0;
}

在这里插入图片描述

(4)练习

#include <stdio.h>

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

在这里插入图片描述

(5)scanf与printf

在这里插入图片描述
大家也可以打开MSDN去了解一下。

(二)for循环语句

1.语法

在这里插入图片描述
在这里插入图片描述

2.流程图

在这里插入图片描述

来个简单的for循环语句:
在这里插入图片描述

大家可以发现:在while循环中依然存在循环的三个必须条件,但是由于风格的问题使得三个部分很可能偏离较远,这样查找修改就不够集中和方便。所以,for循环的风格更胜一筹;for循环使用的频率也最高。

3. break和continue在for循环中

在for循环中也可以出现break和continue,他们的意义和在while循环中是一样的。但是还是有些差异:
对break,while循环语句与for语句是一样的。
在这里插入图片描述
对continue,for循环和while循环是不一样的。
在这里插入图片描述

4. for语句的循环控制变量

建议:

1. 不可在for 循环体内修改循环变量,防止 for 循环失去控制。
2. 建议for语句的循环控制变量的取值采用“前闭后开区间”写法。

解释:
如果在for循环里面改变i的值,有可能会导致死循环的现象。
在这里插入图片描述
建议前闭后开方式进行书写,可读性高。
在这里插入图片描述

5.一些for循环的变种

for循环中的初始化部分,判断部分,调整部分是可以省略的。

(1)省略判断部分

省略掉判断部分,那么判断就恒为真,所以会产生死循环。
在这里插入图片描述

(2)省略初始化部分

在二重循环中容易造成错误,因为j那个循环没有初始化,所以j经过循环以后一直是3,所以一直进不去j的for循环。
在这里插入图片描述

(3)使用多余一个变量控制循环

在这里插入图片描述

6.练习题

在这里插入图片描述

(三)do……while循环语句

1.do语句的语法

在这里插入图片描述
不管三七二十一,先执行一遍语句。
在这里插入图片描述

2.do语句的特点

循环至少执行一次,使用的场景有限,所以不是经常使用。

在这里插入图片描述

3.do while循环中的break和continue

break语句好理解,打破这个循环体,直接跳到return 0;这个语句。
在这里插入图片描述
而continue就需要思考一下了,当进入continue这个语句的时候,会跳到判断的语句(i<11)中,所以会打印1 2 3 4 5(5死循环)。
在这里插入图片描述

(四)区别

其实在之前已经详细地分析了三个语句的不同点,do……while语句是不管三七二十一先运行一次,while语句是写的较为分散,for语句写的十分集中,把三要素写在括号里了!!!所以for语句用的最多哦!!!

(五)练习

1.计算n的阶乘

在这里插入图片描述

#include<stdio.h>

int main() {
	int n = 0;
	scanf("%d", &n);
	//产生1~n的数字
	int i = 0;
	int ret = 1;
	for (i = 1; i <= n; i++) {
		ret *= i;
	}
	printf("%d!=%d\n", n, ret);
	return 0;
}

2.计算 1!+2!+3!+……+n!

#include<stdio.h>

//计算 1!+ 2!+ 3!+ …… + 10!
//1!=1
//2!=1*2=1!*2
//3!=1*2*3=2!*3

int main() {
	int n = 0;
	int i = 0;
	int ret = 1;
	int sum = 0;
	scanf("%d", &n);
	for (i = 1; i <= n; i++) {
		ret = ret * i;
		sum = sum + ret;
	}
	printf("%d\n", sum);
	return 0;
}

3.在一个有序数组中查找具体的某个数字n

先上一个我们大家都能理解的代码:

#include<stdio.h>
//在一个有序数组中查找具体的某个数n

int main() {
	//数组如果有n个元素,有可能要找n次,比较慢
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int k = 7;
	int i = 0;
	int flag = 0;
	for (i = 0; i < 10; i++) {
		if (arr[i] == k) {
			printf("找到了,下标是%d\n", i);
			flag = 1;
			break;
		}
	}
	
	//break和找不到的时候也会来到这
	if (flag == 0) {
		printf("找不到\n");
	}
	return 0;
}

大家发现了吗?这个代码是不是需要遍历的太多了,如果查找数是n的话,是不是寻找的数太多了,计算量过大,计算效率也低,那大家仔细看看题目,这已经是一个有序数组了,所以我们接下来引进二分查找的概念。

(1)二分查找的概念

当我买了一双鞋,我告诉你价格为500以内,你肯定不可能一块一块的猜,而先去猜一下,250?375?这样去缩小范围,节省时间地猜。所以它的概念就是,分成两半,再分成两半,……,一直到找到这个数。

(2)二分查找的思路和代码

在这里插入图片描述

#include<stdio.h>

int main() {
	int k = 0;
	scanf("%d", &k);
	int flag = 0;
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int left = 0;
	int right = sz - 1;
	while (left <= right) {
		int mid = (left + right) / 2;
		if (arr[mid] > k) {
			right = mid - 1;
		}
		else if (arr[mid] < k) {
			left = mid + 1;
		}
		else {
			printf("找到了,下标为%d\n", mid);
			flag = 1;
			break;
		}
	}
	if(flag==0){
		printf("找不到\n");
	}
	return 0;
}

4.编写代码,演示多个字符从两端移动,向中间汇聚。

(1)解析及代码

#include<stdio.h>
#include<string.h>

//Hello Word!
//***********
//H*********!
//He*******d!
//Hel*****rd!
//Hell***ord!
//Hello*word!
//Hrllo word!
int main() {
	char arr1[] = "Hello Word!";
	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);
		left++;
		right--;
	}
	
	return 0;
}

在这里插入图片描述

(2)Sleep函数和system函数

Sleep是实现睡眠,单位是毫秒。
system是一个库函数,可以执行系统命令,cls是清空屏幕的一个命令,头文件是stdlib。

#include<stdio.h>
#include<string.h>
#include<windows.h>
#include<stdlib.h>

//Hello Word!
//***********
//H*********!
//He*******d!
//Hel*****rd!
//Hell***ord!
//Hello*word!
//Hrllo word!
int main() {
	char arr1[] = "Hello Word!";
	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);//是实现睡眠,单位是毫秒,头文件为windows
		system("cls");//system是一个库函数,可以执行系统命令,cls是清空屏幕的一个命令,头文件是stdlib
		left++;
		right--;
	}
	
	return 0;
}

5.编写代码实现,模拟用户登录情景,并且只能登录三次。

解析:只允许输入三次密码,如果密码正确则提示登录成,如果三次均输入错误,则退出程序。

int main()
{
	//假设密码是:字符串“123456”
	char password[20] = { 0 };//字符数组
	int i = 0;
	int j = 0;
	int flag = 0;
	for (i = 0; i < 3; ++i)
	{
		printf("请输入密码:>");
		scanf("%s", password);//数组名本身就是地址,所以不需要取地址
		//判断两个字符串是否相等,要用strcmp函数,不能直接相等
		//int ret=strcmp(password,"123456");
		//比较的是内容,一对一对对比的
		//如果第一个字符串小于第二个字符串,它会返回一个小于0的数字
		//如果第一个字符串大于第二个字符串,它会返回一个大于0的数字
		//如果第一个字符串等于第二个字符串,它会返回0
		if (strcmp(password, "123456") == 0) {
			printf("登录成功\n");
			flag = 1;
			break;
		}
		else {
			printf("第%d次密码错误\n", i + 1);
		}
	}
	if (flag == 0) {
		printf("三次密码输入均错误\n");
	}

	return 0;
}

大家可以看一下我之前写的模拟strcmp函数,深入理解一下strcmp。
模拟strlen函数

6.猜数字游戏

(1)思路

介绍:
在这里插入图片描述
菜单:
在这里插入图片描述

(2)rand函数

rand是专门用来生成随机数的
我们去MSDN看一下rand函数:
在这里插入图片描述

rand函数返回的是0-RAND_MAX之间的值
何为RAND_MAX — 转到定义去一看是7fff - 16进制
在这里插入图片描述
在这里插入图片描述
数字很大,那我们就%100吧,但是%100范围是0~99,那再+1不就是范围为1`100了吗!?

我们看一看打印一下rand的值,确实不一样,唉,我想玩第二次了,这怎么和第一次的数据是一样的,没有随机改变呀!那怎么解决呢?这就需要srand种子函数。

(3)srand种子函数

我们先了解一下srand函数,如下:
在这里插入图片描述
srand函数想当于rand函数生成随机数的起点。rand函数原本是随机生成的,但是它每次程序生成的值都一样,而srand函数恰好弥补了rand函数的这个缺陷,它是设置rand函数生成随机值的函数,相当于给rand函数不同的起点去进行生成随机值且每一次玩的时候起点都不一样。并且,srand函数是只调用一次即可,这涉及到了time函数时间戳的问题,因为起点的值是从现在这个时间到1970年1月1日0点相差的时间,如果调用过于多,则时间上太相近了,随机数差别不大。
我们要想生成随机数,需要给srand传用变化的值,我们想,时间是不是一个一直在改变的值,那我们就用时间函数吧!

(4)time函数

时间戳:现在这个时间到1970年1月1日的时间差,这是不是一直在改变的!?

在这里插入图片描述
它返回的是一个整型。

(5)代码

#include<stdio.h>
#include<stdlib.h>
#include<time.h>


//rand是专门用来生成随机数的
//rand函数返回的是0-RAND_MAX - 0x7fff(32767)之间的值
//rand函数在使用之前要使用一个srand函数来设置随机数的生成器
//
//时间戳
//C语言中,time函数会返回时间戳
//srand函数在程序中只要调用一次即可,不需重复调用


void menu(void) {
	printf("****************\n");
	printf("*****1.play*****\n");
	printf("*****0.exit*****\n");
	printf("****************\n");
}

void game(void) {
	//生成随机数
	int num = rand() % 100 + 1;
	//printf("%d\n", num);
	//猜数字
	int i = 0;
	while (1) {
		printf("请输入数字:>");
		scanf("%d", &i);
		if (i > num) {
			printf("大了\n");
		}
		else if (i < num) {
			printf("小了\n");
		}
		else {
			printf("恭喜你,猜对了\n");
			Sleep(1000);//睡眠1000毫秒
			system("cls");//情空屏幕
			break;
		}
	}
}

int main() {
	srand((unsigned int)time(NULL));//空指针
	int input = 0;
	do {
		//打印菜单
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input) {
		case 1:
			printf("猜数字\n");
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("重新选择\n");
			break;
		}
	} while (input!=0);

	
	return 0;
}

四、goto语句

(一)概念

C语言中提供了可以随意滥用的 goto语句和标记跳转的标号。
从理论上 goto语句是没有必要的,实践中没有goto语句也可以很容易的写出代码。但是某些场合下goto语句还是用得着的,最常见的用法就是终止程序在某些深度嵌套的结构的处理过程。
例如:一次跳出两层或多层循环。多层循环这种情况使用break是达不到目的的。它只能从最内层循环退出到上一层的循环。
注意:goto语句只能在同一函数内部跳转,不能跨函数跳转。
在这里插入图片描述

(二)例子

一个关机程序(不要轻易尝试哦),小编已经尝试过了,图片没有保存然后又重新做了一遍。

#include<string.h>
#include<stdlib.h>
#include<stdio.h>
//一个关机程序
//1.程序执行起来就倒计时关机,60秒关机
//2.如果输入我是猪,则取消关机
//shutdown -s -t 60 60秒后关机
//shutdown -a 取消关机
int main() {
	char input[20] = { 0 };
	system("shutdown -s -t 60");
again:
	printf("你的电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
	scanf("%s", input);
	//判断
	if (0 == strcmp(input, "我是猪")) {
		printf("好的,立马给你取消关机\n");
		system("shutdown - a");
	}
	else {
		goto again;
	}
	return 0;
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
	char input[10] = { 0 };
	system("shutdown -s -t 60");
	while (1)
	{
		printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");
		scanf("%s", input);
		if (0 == strcmp(input, "我是猪"))
		{
			system("shutdown -a");
			break;
		}
	}
	return 0;
}

总结

原来分支与循环的内容知识点是那么多啊!不整理不知道,一整理发现那么多复杂的知识点,大家相信看完以后会有很深的理解,如果再加以练习那可谓是完全掌握了分支与循环,而且,碰到一个比较复杂的代码不要太慌张觉得自己不行,可是要想,万丈大楼从基建做起,我们需要一点点运用之前学的知识一点一点剖析!!!


客官,码字不易,来个三连支持一下吧!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/124099.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

vulnhub DC系列 DC-1

目录 下载地址 漏洞分析 信息收集 漏洞尝试 漏洞利用 flag1 flag2 flag3 flag4 提权 下载地址 DC-1.zip (Size: 733 MB)Download: http://www.five86.com/downloads/DC-1.zipDownload (Mirror): https://download.vulnhub.com/dc/DC-1.zip使用方式:ova文件直接使用vm…

nacos安装与使用

nacos安装与使用nacos下载安装下载方式 一&#xff1a;下载方式 二&#xff1a;版本&#xff08;2.0.3&#xff09;nacos启动在项目中注册nacos服务nacos下载安装 下载方式 一&#xff1a; nacos官网下载 下载方式 二&#xff1a;版本&#xff08;2.0.3&#xff09; 链接&a…

【Flask框架】——28 Flask_SQLAlchemy

Flask-SQLAlchemy Flask-SQLAlchemy的使用对SQLAlchemy进行了封装和优化&#xff1a; Flask-SQLAlchemy是Flask框架的一个插件&#xff1b; Flask-SQLAlchemy是对SQLAlchemy进行了一个简单的封装的一个插件&#xff0c;使得我们在Flask中使用sqlalchemy更加的简单。 1.安装…

排查wx.previewImage真机预览一直loading问题

起因 使用van-uploader预览图片一直loading预览不了&#xff0c;开发者工具&#xff0c;浏览器都是秒开的。我看源码是使用wx.previewImage&#xff0c;自己写了个demo也是同样问题。 排查原因 链接是否拼接错误域名有没有添加进白名单防盗链referrer证书是否过期&#xff0…

企业数字化转型蓝图规划、生态体系建设、数字化管理平台建设方案

【版权声明】本资料来源网络&#xff0c;仅用于行业知识分享&#xff0c;供个人学习参考&#xff0c;请勿商用。【侵删致歉】如有侵权请联系小编&#xff0c;将在收到信息后第一时间进行删除&#xff01;完整资料领取见文末&#xff0c;部分资料内容&#xff1a; 数字化助力上下…

SuperMap iServer在不同系统中设置开机自启动--Linux篇

目录前言一&#xff1a;CentOS系统二&#xff1a;Ubantu系统作者&#xff1a;kxj 前言 在成功部署SuperMap iServer之后&#xff0c;每次重启电脑都需要手动去启动iServer&#xff0c;如何能让iServer在每次重启电脑时都自动启动呢&#xff1f;今天咱们一起来看看在Linux系统中…

实地址方式下的可屏蔽中断服务程序设计

目录 实地址方式下的可屏蔽中断服务程序设计 程序装入方式 直接装入&#xff08;会这种方式就可以&#xff0c;考试都给你地址让你装&#xff09; 系统功能调用装入&#xff08;了解考纲没要求&#xff09; 中断屏蔽与中断结束的处理&#xff08;了解&#xff09; 会直接装…

Python基础(十九):函数加强

文章目录 函数加强 一、递归 1、递归的应用场景 2、应用&#xff1a;3以内数字累加和 二、lambda 表达式 1、lambda的应用场景 2、lambda语法 3、示例&#xff1a;计算a b 4、lambda的参数形式 5、lambda的应用 三、高阶函数 1、体验高阶函数 2、内置高阶函数 …

Grafana配置邮件

1.Grafana配置文件路径 默认的配置文件路径是&#xff1a;/etc/grafana/grfana.ini 2.默认情况下&#xff0c;邮件服务是关闭的 systemctl status grafana-server 可以查看到当前服务的配置文件在哪里 3.没有改动之前的配置文件 /etc/grafana/grfana.ini systemctl resta…

插件算法管理以及任务队列机制

插件算法管理以及任务队列机制插件管理抽象插件基类插件导入导出规范__attribute__((visibility("default")))插件实例插件管理者算法管理抽象算法基类算法Map与具体算法注册规范PetCoin算法实例算法管理者任务队列机制抽象任务具体任务任务管理者任务队列插件管理 …

“浪潮信息龙蜥联合实验室”正式成立!2万+人在线,带你一文读懂MeetUp精彩瞬间

12 月 24 日&#xff0c;龙蜥社区&#xff08;OpenAnolis&#xff09; “走进系列” 第 4 期——走进浪潮信息 MeetUp 于线上开展并圆满结束。本次走进浪潮信息 MeetUp 线上观看 2 万人次&#xff0c;收回调研问卷近 500 份&#xff0c;直播间万人参与互动。本次 MeetUp 汇集了…

windows 10管理多版本nodejs

在实际的开发中,不同的项目使用的nodejs的版本不一致。又不想升级或者降低项目的版本。这时就需要灵活的切换本地开发环境的nodejs版本。这里推荐使用nvm&#xff08;一个管理nodejs版本的工具&#xff09;&#xff0c;亲测实用。 1、下载地址 https://github.com/coreybutle…

Biniware Run V6.1.0 快速启动工具中文版

前言 Biniware Run是一款便携式Windows桌面工具&#xff0c;可让您从一个地方快速访问自己喜欢的网站地址&#xff0c;文件和文件夹。只需从桌面拖放任何网站地址&#xff0c;文件或文件夹内的彩色圆圈内&#xff0c;您就可以使用这个方便的软件轻松访问您感兴趣的所有内容。 …

SpringCloud之服务治理Eureka

1.服务注册和发现是什么意思&#xff1f;Spring Cloud 如何实现&#xff1f; 服务注册和发现的意思是服务进程在注册中心注册自己的位置&#xff0c;客户端应用进程向注册中心发起查询&#xff0c;来获取服务的位置&#xff0c;服务发现的一个重要作用就是提供一个可用的服务列…

【Linux】Linux调试器--gdb的使用

有时候&#xff0c;我们并不需要被教导&#xff0c;而是应该被不断的提醒。 文章目录一、gdb的介绍二、debug和realease版本的区别三、gdb的使用1.显示代码&#xff1a; l行号&#xff08;list&#xff09;指令2.设置断点&#xff1a; b行号&#xff08;breakpoint&#xff09…

HTML5 定位

文章目录HTML5 定位geolocation简介getCurrentPosition()watchPosition() 和 clearWatch()百度地图HTML5 定位 geolocation 简介 在HTML5中&#xff0c;可以使用geolocation对象来获取用户的地理位置信息。 语法 window.navigator.geolocation //简写为 navigator.geoloca…

uni-app HBuilderX项目转为cli项目及踩坑记录

uni-app有两种创建创建项目的方式&#xff0c;通过HBuilderX可视化界面进行创建和通过vue-cli命令行&#xff0c;两者的区别可以参考uni-app官网-可视化方式的区别 其中cli项目是可以直接运行在hx中的&#xff0c;相比hx项目&#xff0c;cli的好处还有可以自定义环境变量和自定…

借助“云上”SPSS降低未来数据分析的不确定性

生活工作中我们常常会遇到这样或那样的困难&#xff0c;比如不得不临时居家办工&#xff0c;却发现家中电脑没有安装工作中的必备软件&#xff0c;比如毕业论文写到一半&#xff0c;同学告诉你&#xff0c;新版的软件升级加强了某个模型&#xff0c;能让你更好的完成论文。软件…

浅析从DWARF到BTF @龙蜥社区eBPF SIG

一、背景 一个程序会经历编码、编译、运行的过程&#xff0c;但所有的开发几乎都不可能是一帆风顺的&#xff0c;总会有些意想不到的错误&#xff0c;这时便需要调试。那么调试器使用的调试信息是从哪里来的呢&#xff1f;答案就是从编译后的文件中来的(依赖编译的时候使用特定…

Kubernetes使用Ingress Nginx流量代理

理论了解 1、ingress简介 kubernetes官方文档 Ingress 是 kubernetes API 中的标准资源类型之一&#xff0c;ingress 实现的功能是在应用层对客户端请求的 host 名称或请求的 URL 路径把请求转发到指定的 service 资源的规则&#xff0c;即用于将 kubernetes 集群外部的请求…