C语言之分支与循环【附6个练习】

文章目录

    • 前言
    • 一、什么是语句?
      • 1.1 表达式语句
      • 1.2 函数调用语句
      • 1.3 控制语句
      • 1.4 复合语句
      • 1.5 空语句
    • 二、分支语句(选择结构)
      • 2.1 if语句
        • 2.1.1 悬空else
        • 2.1.2 练习(1. 判断一个数是否为奇数 2. 输出1-100之间的奇数)
      • 2.2 switch语句
      • 2.3 switch语句中的break:
      • 2.4 switch语句中的default子句:
      • 2.5 练习
    • 三、循环语句
      • 3.1 while循环
        • 3.1.1 while语句中的break和continue
      • 3.2 for循环
        • 3.2.1 语法
        • 3.2.2 练习:使用for循环 在屏幕上打印1-10的数字。
      • 3.3 do......while()循环
        • 3.3.1 do语句的语法
        • 3.3.2 do...while语句的特点
    • 四、goto语句
      • 4.1 goto语句的作用
      • 4.2 goto语句的使用场景
      • 4.3 goto语句的例子
    • 五、作业练习
      • 1、 计算 n的阶乘
      • 2、 计算 1!+2!+3!+……+10!
      • 3、 在一个有序数组中查找具体的某个数字n
      • 4、演示多个字符从两端移动,向中间汇聚
      • 5、密码校验
      • 6、猜数字游戏【经典】

前言

C语言是结构化的程序设计语言,这里的结构指的是顺序结构、选择结构、循环结构,C语⾔是能够实现这三种结构的,其实我们如果仔细分析,我们⽇常所⻅的事情都可以拆分为这三种结构或者这三种结构的组合。我们可以使⽤ifswitch 实现分⽀结构,使⽤ forwhiledo while 实现循环结构。

一、什么是语句?

在我们平时写字中,一句话的结尾是句号,然而正在C语言中一句话的结尾是;

  • 语句可以分为以下五类:
    1)表达式语句
    2)函数调用语句
    3)控制语句
    4)复合语句
    5)空语句

1.1 表达式语句

下面这个就是表达式语句:

3 + 5;  

1.2 函数调用语句

函数调用语句,就是将函数进行使用时调用的语句。

printf("%d\n", a);  
ADD(3, 5); 

1.3 控制语句

  • 控制语句用于控制程序的执行流程,以实现程序的各种结构方式,它们由特定的语句定义符组成,C语言有九种控制语句。
  • C语言是由三种结构组成的,有顺序结构选择结构循环结构

可分成以下三类:

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

1.4 复合语句

  • 复合语句就是被多个扩号括起来的语句
{int a = 0;int b = 0;printf("%d\n", a + b);return 0;
}

1.5 空语句

  • 空语句虽然很简单,但是其用途很大:有时候需要一条语句,但这条语句什么都不需要做
  • 例如下面这段代码,我们会后面在字符章节也会详细讲解
while(*dest++ = *src++)
{;
}

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

  • ​分支语句可以为双分支或者多分支。
  • 在C语言中需要知道真假两个概念:非0为真,0为假(注意:正数和负数都是真)
  • 分支语句分为两类if语句,switch语句

2.1 if语句

  • 那么if语句的语法结构是怎么样的?
if(表达式)//表达式为真执行下面的语句语句;
//单分支语句
if(表达式)语句1else语句2//多分支语句
if(表达式1)语句1else if(表达式2)语句2else语句3
  • 单分支练习(输入大于等于18输出为成年人,否则不输出):
#include <stdio.h>
int main()
{int age = 0;scanf("%d", &age);if (age >= 18){printf("成年人\n");}
}
  • 单分支练习(输入大于等于18输出为成年人,否则输出未成年人):
#include <stdio.h>
int main()
{int age = 0;scanf("%d", &age);if (age >= 18){printf("成年人\n");}else{printf("未成年\n");}
}
  • 多分支练习
#include <stdio.h>
int main()
{int age = 0;scanf("%d", &age);if (age < 18){printf("少年\n");}else if (age >= 18 && age < 30){printf("青年\n");}else if (age >= 30 && age < 50){printf("中年\n");}else if (age >= 50 && age < 80){printf("老年\n");}else{printf("老寿星\n");}}
2.1.1 悬空else
  • 当你写了这个代码:
#include <stdio.h>
int main()
{int a = 0;int b = 2;if(a == 1)if(b == 2)printf("hehe\n");elseprintf("haha\n");return 0;
}
  • 上面那个代码虽然可以运行,但是风格不是很好
#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;
}
  • 这段代码加上了{}使代码变得逻辑更加清楚,要养成更好的代码分格
  • 如何写出一个好的代码呢?

这里我推荐《高质量C/C++编程》,而这本书就写了如何写出好的风格,大家可以看一下

  • 在我们判断是否等于一个变量或者数的时候我们有可能少一个等于号,那么我们怎么避免呢?
//代码1
int num = 1;
if(num == 5)
{printf("hehe\n");
}
//代码2
int num = 1;
if(5 == num)
{printf("hehe\n");
}

上面的代码哪个比较好?

  • 肯定是代码2,因为在判断是否相等时用两个等于号写,这样反过来写就会避免只写一个等于号,只写一个等于号的话会编译错误,可以及时发现。
2.1.2 练习(1. 判断一个数是否为奇数 2. 输出1-100之间的奇数)
  1. 判断一个数是否为奇数
  • 思路:要判断是不是奇数,那么我们就可以看一个数的余数是不是等于1,如果等于1那么这个数就是奇数,否则就是偶数了
int main()
{int n = 0;scanf("%d", &n);if (n % 2 == 1){printf("YES\n");}else{printf("NO\n");}return 0;
}
  1. 输出1-100之间的奇数
  • 思路:要输出1-100之间的奇数,就要产生1~100的数,然后将每个数进行判断是不是奇数然后再输出
  • 我们目前学了while循环,那么我们就用while循环来解决这道题~,后面学到了for循环也可以很简便的写出来

方法一:

#include<stdio.h>
int main()
{int i = 1;while (i<= 100)//产生1~100的数字{if(i % 2 ==1)//进行判断是否奇数printf("%d ", i);i++;}return 0;
}

方法二:

  • 这个方法的话就有点投机取巧了~~
#include<stdio.h>
int main()
{int i = 1;while (i <= 100)//产生1~100的数字{printf("%d ", i);//i+=2;i = i + 2;//也可以这样写}return 0;
}

2.2 switch语句

  • switch语句也是一种分支语句,常常用于多分支情况~~

比如:

输入1,输出星期一;
输入2,输出星期二;
输入3,输出星期三;
输入4,输出星期四;
输入5,输出星期五;
输入6,输出星期六;
输入7,输出星期七。

  • 如果写成if…else if…else if…else的情况就很复杂,那我们需要有不一样的语法形式

  • switch语句(支持嵌套使用)

switch(整形表达式)
{语句项;
}
  • 而语句项是什么呢?
//是一些case语句:
//如下:
case 整形常量表达式:语句;

2.3 switch语句中的break:

  • 在switch语句中,我们没办法直接实现分支,搭配break使用才能实现真正的分支。
#include <stdio.h>
int main()
{int day = 0;switch(day){case 1printf("星期一\n");break;case 2:printf("星期二\n");break;case 3:printf("星期三\n");break;    case 4:printf("星期四\n");break;    case 5:printf("星期五\n");break;case 6:printf("星期六\n");break;case 7:printf("星期天\n");    break;}return 0;
}
  • 有时候我们的需求变了:
  1. 输入1-5,输出的是“weekday”;
  2. 输入6-7,输出“weekend”
  • 所以我们的代码就应该这样实现了:
#include <stdio.h>
//switch代码演示
int main()
{int day = 0;switch (day){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语句。
    (之所以这么写是可以避免出现在以前的最后一个 case 语句后面忘了添加 break语句~~)

2.4 switch语句中的default子句:

如果表达的值与所有的case标签的值都不匹配怎么办?

default:

  • 写在任何一个 case 标签可以出现的位置。
    当 switch 表达式的值并不匹配所有 case 标签的值时,这个 default 子句后面的语句就会执行。
  • 所以,每个switch语句中只能出现一条default子句。
    但是它可以出现在语句列表的任何位置,而且语句流会像执行一个case标签一样执行default子句。

推荐编程好习惯

  • 在每一个switch语句中都放入一条default语句是一个好习惯,甚至可以在后面加一个break。

2.5 练习

#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;
}

上面这段代码的结果是什么呢?
在这里插入图片描述

三、循环语句

  • 循环语句分为三类while循环,for循环,do…while循环

3.1 while循环

我们已经掌握了,if语句:

if(条件) 语句;
  • 当条件满足的情况下,if语句后的语句执行,否则不执行。
    但是这个语句只会执行一次。
    由于我们发现生活中很多的实际的例子是:同一件事情我们需要完成很多次。
  • 那我们怎么做呢?
    C语言中给我们引入了: while 语句,可以实现循环。
while(表达式)循环语句;

while循环的执行流程:

在这里插入图片描述

3.1.1 while语句中的break和continue

break介绍

#include <stdio.h>
int main()
{int i = 1;while (i <= 10){if (i == 5)break;printf("%d ", i);i = i + 1;}return 0;
}

这里代码输出的结果是什么?
在这里插入图片描述

总结

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

continue介绍

  • continue 代码实例1:
#include <stdio.h>
int main()
{int i = 1;while (i <= 10){if (i == 5)continue;printf("%d ", i);i = i + 1;}return 0;
}

输出1 2 3 4...

  • continue 代码实例2:
#include <stdio.h>
int main()
{int i = 1;while (i <= 10){i = i + 1; if (i == 5)continue;printf("%d ", i);}return 0;
}

输出:>2 3 4 6 7 8 9 10 11

总结:

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

那么我们在看几个代码~~

getchar介绍

#include <stdio.h>
int main()
{int ch = 0;while ((ch = getchar()) != EOF)putchar(ch);return 0;
}
  • 这里的getchar函数不接收任何的参数,返回类型是int stdin(键盘)上读取一个字符返回读取到字符的ASCLL码值,如果读取失败或者读取到文件末尾就会返回EOF
  • 这里可以打开msdn或者cplusplus网站进行搜索

在这里插入图片描述

  • 选中EOF转到定义就可以看到
  • 那么EOF是什么呢?EOF是-1,在一次证明了返回值是int的。

在这里插入图片描述

putchar介绍

  • 接收一个字符输出到屏幕,也就是从键盘上获取一个字符打印到屏幕上

在这里插入图片描述

  • 现在代码运行结果是什么呢?

输入:>q
输出:>q

  • 输入什么就会输出什么

那么我们这个程序怎么停止下来呢?

  • 只需要ctrl+z然后回车就可以了,目的是让读取到EOF这样程序就会终止。

那么这里的代码还有什么用呢?

  • 可以用来清理缓冲区的

列如:

int main()
{char password[20];scanf("%s", password);printf("请确认(Y/N):");int ch = getchar();if ('Y' == ch)printf("确认成功\n");elseprintf("确认失败\n");return 0;
}

输入:>abcde
输出:>请确认(Y/N):确认失败

怎么回事呢?还没确认就是确认失败了,为什么呢?

  • scanf会从键盘上读取一些你输入的数据,但你不输入的时候,它就一直等,一直等,直等到你输入为止。
  • 在计算机中,使用scanf时并不会直接获取键盘上输入的数据。相反,存在一个输入缓冲区,用户输入的数据首先会被放入这个缓冲区。当用户输入完数据(例如"abcde"),为了将这些数据送入缓冲区,用户需要按下回车键。
    • 举例来说,如果用户输入"abcde"并按下回车键,整个输入会被存储为"abcde\n",其中\n表示回车符。这时,scanf会从缓冲区读取数据,直到遇到换行符为止。所以,用户的输入实际上是被缓冲并在程序请求时才被获取的。
  • 通过scanf函数将数据输入到缓冲区,并检查是否有可读取的数据。如果有数据可读取,它会一直读取直到遇到换行符(\n)。随后,将这些数据作为密码赋给变量password。此时,getchar()函数也开始读取数据,其工作原理与scanf()相似,检查缓冲区是否有数据。一旦发现换行符(\n),就将对应的数据存储到变量ch中。然后,程序判断ch是否为‘Y’,由于不满足这个条件,进入else分支,并输出“确认失败”。这就是编译器在等待我们输入确认密码时,却直接结束程序的原因。

再看一个代码

#include <stdio.h>
int main()
{char ch = '\0';while ((ch = getchar()) != EOF){if (ch < '0' || ch > '9')continue;putchar(ch);}return 0;
}
  • 那么这段代码就要对ASCLL码表要熟悉

在这里插入图片描述

  • 这段代码只打印0~9的字符

3.2 for循环

3.2.1 语法

首先来看看for循环的语法:

for(表达式1; 表达式2; 表达式3)循环语句;
  • 表达式1:表达式1为初始化部分,用于初始化循环变量的;
  • 表达式2:表达式2为条件判断部分,用于判断循环时候终止;
  • 表达式3:表达式3为调整部分,用于循环条件的调整。

for循环的执行流程:
在这里插入图片描述

3.2.2 练习:使用for循环 在屏幕上打印1-10的数字。
#include <stdio.h>
int main()
{int i = 0;//for(i=1/*初始化*/; i<=10/*判断部分*/; i++/*调整部分*/)for (i = 1; i <= 10; i++){printf("%d ", i);}return 0;
}
  • 输出:>1 2 3 4 5 6 7 8 9 10

  • 就像我们这里去打印1-10的数字,使用for循环的话就会很清晰直观,代码也比较简练

  • 现在,我们学习完了while循环和for循环后,让我们进行对比一下这两个循环:

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");
}

通过上面的代码,可以发现在while循环中依然存在循环的三个必须条件,但是由于风格问题使得三个部分很可能偏离较远,这样查找修改不够集中和方便。

3.3 do…while()循环

do…while()执行流程:

在这里插入图片描述

3.3.1 do语句的语法

首先来看一下它的语法格式,和while循环很类似

do
{循环语句;
}while(表达式);
3.3.2 do…while语句的特点
  • 循环体内至少执行一次,使用的场景有限,所以不是经常使用。
  • 但是我们下面的猜数字游戏会有一个案例我们可以来看一下

四、goto语句

在大多数现代编程语言中,goto语句通常被认为是一种不良的编程实践,因为它可能导致程序难以理解和维护。然而,在某些情况下,它仍然是一种有用的控制流工具。在C语言中,goto语句可以用来无条件地将程序控制转移到指定的标签处

如果goto语句用的不好,会导致程序跳来跳去的。

4.1 goto语句的作用

  • C语言提供了⼀种非常特别的语法,就是 goto 语句和跳转标号,goto语句可以实现在同⼀个函数 内跳转到设置好的标号处。

4.2 goto语句的使用场景

for (...)
for (...)
{for (...){if (disaster)goto error;}
}
…
error :
if (disaster)
// 处理错误情况

4.3 goto语句的例子

  • 下面这是一个关机程序的例子,学会后可以拿去恶搞同学一下~~
#include <stdio.h>
#include <windows.h>
#include <string.h>
int main()
{char input[10] = {0};system("shutdown -s -t 60");
again:printf("电脑将在1分钟内关机,如果输入:我是猪,就取消关机!\n请输入:>");scanf("%s", input);if(0 == strcmp(input, "我是猪")){printf("shutdown -a");}else{goto again;}return 0;
}
  • 使用goto通常容易导致程序结构混乱,使得代码难以理解和维护。因此,除非有充分的理由,推荐使用其他控制流结构(如for、while、do-while、if等)来替代goto语句。

五、作业练习

1、 计算 n的阶乘

  • 计算一个n的阶乘,那只要定义一个变量去存放这个阶乘的结果,然后通过循环去遍历即可

  • 这里需要注意的一点就是,ret初始值为1

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

2、 计算 1!+2!+3!+……+10!

  • 第二小题又是一道计算阶乘的题,然后把计算出的阶乘再相加~~

  • 假设我们要计算1! + 2! + 3! 这一小规模的阶乘之和。首先,让我们审视解题思路。由于只需计算到数字3的阶乘,我们需要一个外层循环,从1迭代到3,表示我们要求解的是这三个数字的阶乘之和。

  • 接下来,内层循环用于计算每个数字的阶乘,从1迭代到该数字即可。我们使用一个累乘变量来存储计算结果。在完成每个数字的阶乘计算后,我们需要累加这些阶乘的和,因此还需要定义一个sum变量来存储这个累加和。最终,sum变量就是我们所需的结果。

  • 正确答案应该是1 + 2 + 6 = 9

int ret = 1;
int sum = 0;
for (int i = 1; i <= 3; ++i)
{for (int j = 1; j <= i; ++j){ret *= j;}sum += ret;
}
printf("sum = %d\n", sum);
  • 可以看到,sum的结果并非为9。这里涉及到一个常见的错误,很多同学容易犯这个错。因为我们正在计算不同数字的阶乘,但是使用的累乘变量是同一个ret。因此,当计算下一个数字的阶乘时,ret仍然保留了上一次数字累乘后的结果。这导致了阶乘计算的不准确,因此结果也会有所不同。
  • 在计算3!时,可能多乘了一个2!留下了额外的2,导致3!= 12,比实际结果多了6。因此,最终的计算结果也就多了6。
int ret = 1;
int sum = 0;
for (int i = 1; i <= 3; ++i)
{ret = 1;//这里要把ret掷为1for (int j = 1; j <= i; ++j){ret *= j;}sum += ret;
}
printf("sum = %d\n", sum);
  • 我们应该加上ret = 1;在每一次更新需要求阶乘的数时,都将这个累乘变量ret重置
int ret = 1;
int sum = 0;
for (int i = 1; i <= 3; ++i)
{ret *= i;sum += ret;
}

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

  • 在数组的两端分别设定左右两个指针,然后计算它们的中间值。将欲查找的数字与中间值比较,若小于中间值,则舍弃后半段区间,只需在前半段继续查找;若大于中间值,则舍弃前半段区间,继续在后半段查找。将此逻辑嵌入一个循环中,不断更新中间值进行比较。最终左右两指针会相遇,表示区间即将结束。若左指针大于右指针,表示已找到目标元素或未找到,此时退出循环并进行相应打印说明。

  • 接下来我们就看看代码~~

int main()
{	//二分查找法int a[10] = { 1,2,3,4,5,6,7,8,9,10 };int sz = sizeof(a) / sizeof(a[0]);int key = 7;//要查找的数字kint left = 0;int right = sz - 1;while (left <= right){int mid = (left + right) / 2;if (key < a[mid])right = mid - 1;else if (key > a[mid])left = mid + 1;else{printf("找到了,下标是%d\n", mid);break;		//找到了便跳出循环}}if (left > right)printf("没找到此元素\n");return 0;
}

4、演示多个字符从两端移动,向中间汇聚

  • 我们要展示多个字符从两端向中间汇聚的效果,需要实现一种覆盖的动画效果。我定义了两个数组,最终要打印的是第一个数组的内容,但在打印过程中,我们通过左右指针实现覆盖效果。

  • 首先,初始化左指针为0,右指针不能直接取末尾值,需要使用strlen()库函数求解数组1的长度,然后减1得到右指针位置。

  • 将逻辑放入循环中,通过左右指针将第一个数组的内容赋给第二个数组,然后不断移动这两个指针直至左指针大于右指针。

  • 为了慢慢显示出效果,使用了Sleep()睡眠函数,需要引入头文件#include <Windows.h>。这个函数的参数是毫秒值,比如1秒执行一次就传入1000,0.5秒执行一次就传入500。这样可以创建一个动画效果。

int main()
{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(500);left++;right--;}return 0;
}
  • 为了让其在一行打印,不需要一行行地打印,我们可以使用这样一个命令
system("cls");	//清屏,一行打印
  • 但是这个system()函数要加上头文件#include <stdlib.h>,大家不要忘了~~

5、密码校验

  • 这题的要求是输入一串字符,然后与正确密码进行比较,如果相同就立即跳出循环;如果不同,继续输入,但只有3次机会,用完后强制跳出循环,不允许再次输入。
  • 我们来看一下代码~~
int main()
{int i = 0;char password[20] = { 0 };for (i = 0; i < 3; ++i){printf("请输入密码>:");scanf("%s", password);if (strcmp(password, "bitbit") == 0){printf("密码输入正确\n");break;}else{printf("密码输入错误\n");}}if (i == 3){printf("输入机会用完,请30分钟后再试\n");}return 0;
}
  • 在这方面需要注意的一个问题是字符串比较时可能出现的挂字符串问题。我们不能直接使用==运算符进行比较,而应该利用字符串库函数strcmp来实现比较。关于strcmp的返回值,我们可以通过查阅cplusplus来获取详细信息。

  • 简而言之,strcmp函数的返回值取决于第一个字符串的首字母与第二个字符串的首字母的ASCII码值大小关系。如果第一个字符串的首字母大于第二个字符串的首字母,那么返回一个大于0的数字;反之,如果小于,则返回一个小于0的数字。如果两个字符串相同,返回值则为0。这里实际上进行的是ASCII码值的大小比较。

6、猜数字游戏【经典】

  • 首先我们来实现一个整体的逻辑,也就是当你输入的时候,通过我们上面学习的switch语句进行一个分支的判断,是要继续猜数字还是退出游戏
void menu()
{printf("\n");printf("********************************\n");printf("**********  1.play  ************\n");printf("**********  0.exit  ************\n");printf("********************************\n");printf("\n");
}
void game()
{printf("猜数字\n");
}
int main()
{int input = 0;srand((unsigned int)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;
}

在这里插入图片描述

  • 可以看到,整体的逻辑已经实现了按下【1】时启动猜数字功能。如果一直按下1,就能一直进行猜数字,直到按下0为止。

  • 接下来我们就要实现猜数字内部的逻辑了,我们首先要产生一个随机数,然后我们输入一个数字,比较要猜的数字,如果输入的大了就提示猜的数字打了,相反,输入的小了就提示小了,要么就一直继续,知道猜成功为止

  • 那么就要用到一个函数rand(),可以在cplusplus网站上找到~~

在这里插入图片描述

  • 我们要生成1~100内的数字,我们使用下面这段代码官方文档上面也有写
//生成随机数
int ret = rand() % 100 + 1;		//1 ~ 100
  • 但是我们这里又有一个问题,这个rand是一个伪随机数
  • 在C语言中,rand() 函数用于生成伪随机数。伪随机数是由一个算法生成的数字序列,其看似随机,但实际上是可预测的,因为它们是根据一个称为"种子"的初始值计算的。
  • 这个时候我们就要使用到一个C语言中的另一个函数叫做随机种子srand(),我们通过cplusplus我们再来看看

在这里插入图片描述

  • 这个时候我们有了这个函数是不够的,一般还要再配合使用一个时间戳函数time(),不会使用的话也可以在cplusplus中查看

在这里插入图片描述

  • 我们可以这样直接使用,下面我们来详细介绍一下这段代码
srand((unsigned int)time(NULL));
  • time(NULL) 返回当前的系统时间,表示从某个固定时间点(通常是1970年1月1日午夜)到现在的秒数。

  • (unsigned int) 是将时间转换为无符号整数。srand 函数的参数应该是一个无符号整数,因此这里进行了强制类型转换。

  • 最终,srand((unsigned int)time(NULL)); 将当前时间作为种子传递给 srand 函数,以初始化伪随机数生成器。

  • 这个time()函数是要包含头文件的#include <time.h>

  • 还可以加上一个猜数字的次数,如果只能猜10次,次数用完了就结束了,并告知要猜的数字~~

while (1)
{printf("次数还有%d\n", flag);printf("请输入猜的数字>:");scanf("%d", &input);if (input > random_num){printf("猜大了\n");flag--;}else if (input < random_num){printf("猜小了\n");flag--;}else{printf("恭喜你,猜对了\n");break;}if (flag == 0) {printf("次数用完了,数字是%d", random_num);break;}
}

完整的代码:>

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdlib.h>
#include <stdio.h>
#include <time.h>//设置猜的数字次数多少
#define NUM 10 void menu()
{printf("**********************\n");printf("******  1.play *******\n");printf("******  0.exit *******\n");printf("**********************\n");
}void game()
{int guess = 0;int ret = rand() % 100 + 1;int count = NUM;while (1){printf("你还有%d次机会\n", count);printf("请猜数字:>");scanf("%d", &guess);if (guess > ret){printf("猜大了!\n");}else if (guess < ret){printf("猜小了!\n");}else{printf("恭喜你,猜对了!\n");break;}count--;if (count == 0){printf("次数用完,正确的数字是%d\n", ret);break;}}
}
int main()
{int input = 0;srand((unsigned int)time(NULL));//生成随机数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;
}

在这里插入图片描述

  • 我们最后增加了一个次数限制,这样我们对一个猜数字游戏有更有游戏体验感~~

好了,分支与循环到这里就结束了,感谢大家的阅读,希望新的一年大家都有学有所成,感谢阅读!!!

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

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

相关文章

deepfacelive实时换脸教程(2024最新版)

deepfacelive其实操作用法很简单&#xff0c;难的是模型的制作。本帖主要讲deepfacelive&#xff08;下文简称dflive&#xff09;软件本身的操作&#xff0c;以及模型怎么从dfl转格式过来&#xff0c;至于模型如何训练才能效果好&#xff0c;请移步教程区&#xff0c;看deepfac…

51单片机中TCON, IE, PCON等寄存器的剖析

在单片机中&#xff0c;如何快速通过名字记忆IQ寄存器中每一个控制位的作用呢&#xff1f; IE&#xff08;interrupt enable&#xff09;寄存器中&#xff0c;都是中断的使能位置。 其中的EA&#xff08;enable all&#xff09;是总使能位&#xff0c;ES(enable serial)是串口…

构建安全的SSH服务体系

某公司的电子商务站点由专门的网站管理员进行配置和维护&#xff0c;并需要随时从Internet进行远程管理&#xff0c;考虑到易用性和灵活性&#xff0c;在Web服务器上启用OpenSSH服务&#xff0c;同时基于安全性考虑&#xff0c;需要对 SSH登录进行严格的控制&#xff0c;如图10…

WorkQueue模型

WorkQueues&#xff0c;也被称为任务队列模型。当消息处理比较耗时的时候&#xff0c;可能生产消息的速度会远远大于消息的消费速度。长此以往&#xff0c;消息就会堆积越来越多&#xff0c;无法及时的处理。此时就可以使用work模型&#xff1a;让多个消费者绑定到一个队列&…

gem5学习(8):创建一个简单的缓存对象--Creating a simple cache object

目录 一、SimpleCache SimObject 二、Implementing the SimpleCache 1、getSlavePort() 2、handleRequest() 3、AccessEvent() 4、accessTiming() &#xff08;1&#xff09;缓存命中&#xff1a;sendResponse() &#xff08;2&#xff09;缓存未命中&#xff1a; 三、…

matlab概率论例子

高斯概率模型&#xff1a; [f,xi] ksdensity(x): returns a probability density estimate, f, for the sample in the vector x. The estimate is based on a normal kernel function, and is evaluated at 100 equally spaced points, xi, that cover the range of the da…

Mybatis行为配置之Ⅰ—缓存

专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL Mybatis配置入门 Mybatis行为配置之Ⅰ—缓存 Mybatis行为配置…

读书笔记1-C++ Primer Plus

C是在C语言基础上开发的一种集面向对象编程&#xff08;OOP&#xff09;、通用编程和传统的过程化编程于一体的编程语言。本书是根据2003年的ISO/ANSI C标准编写的&#xff0c;通过大量短小精悍的程序详细而全面地阐述了C的基本概念和技术。 全书分17章和10个附录&#xff0c;分…

使用WAZUH检测LD_PRELAOD劫持、SQL注入、主动响应防御

目录 1、检查后门 使用工具检测后门 1.chkrootkit 2.rkhunter 手动检查文件 检查ld.so.preload文件 2、检测LD_PRELOAD ubuntu配置 wazuh配置 3、检测SQL注入 ubuntu配置 攻击模拟 4、主动响应 wauzh的安装以及设置代理可以参考本篇&#xff1a;WAZUH的安装、设置…

Apache Flink连载(二十三):Flink HA - Flink基于Yarn HA

🏡 个人主页:IT贫道_大数据OLAP体系技术栈,Apache Doris,Clickhouse 技术-CSDN博客 🚩 私聊博主:加入大数据技术讨论群聊,获取更多大数据资料。 🔔 博主个人B栈地址:豹哥教你大数据的个人空间-豹哥教你大数据个人主页-哔哩哔哩视频 目录 1. Yarn HA配置 ​​​​…

Cache替换算法

由于Cache很小&#xff0c;主存很大&#xff0c;Cache很容易装满&#xff0c;Cache满了怎么办&#xff1f; ——采用替换算法。 全相联映射&#xff1a;Cache完全满了才需要替换&#xff0c;需要在全局中选择替换哪一块。直接映射&#xff1a;如果对应位置非空&#xff0c;则…

linux线程与进程

简要 在Linux系统中&#xff0c;进程&#xff08;Process&#xff09;和线程&#xff08;Thread&#xff09;是操作系统中两个重要的概念&#xff0c;它们都是用于执行程序的执行单元&#xff0c;但有一些关键的区别。 在Linux系统中&#xff0c;可以使用fork系统调用创建新…

Vue3-30-路由-嵌套路由的基本使用

什么是嵌套路由 嵌套路由 &#xff1a;就是一个组件内部还希望展示其他的组件&#xff0c;使用嵌套的方式实现页面组件的渲染。 就像 根组件 通过路由渲染 普通组件一样&#xff0c;嵌套路由也是一样的道理。 嵌套路由的相关关键配置 1、<router-view> 标签 声明 被嵌套组…

在 Spring 中操作 Redis

&#x1f9f8;欢迎来到dream_ready的博客&#xff0c;&#x1f4dc;相信您对博主首页也很感兴趣o (ˉ▽ˉ&#xff1b;) &#x1f4dc;redis和缓存及相关问题和解决办法 什么是缓存预热、缓存穿透、缓存雪崩、缓存击穿 目录 1、引入依赖 2、对 Redis 的配置文件进行书写 3、S…

kivy PageLayout 的说明及例子

PageLayout 是 Kivy GUI 框架中的一个布局管理器&#xff0c;它允许开发者在同一个窗口中放置多个页面&#xff0c;用户可以通过滑动来浏览这些页面。PageLayout 的工作方式类似于一个可以滑动的标签页&#xff08;TabbedPanel&#xff09;&#xff0c;但其页面可以自由调整大小…

Linux常用命令大全总结及讲解(超详细版)

前言&#xff1a; Linux 是一个基于Linux 内核的开源类Unix 操作系统&#xff0c;Linus Torvalds于 1991 年 9 月 17 日首次发布的操作系统内核。Linux 通常打包为Linux 发行版。 Linux 最初是为基于Intel x86架构的个人计算机开发的&#xff0c;但此后被移植到的平台比任何其…

K8S 中对 Windows 节点的利用

目录 漏洞概述 漏洞详情 ​编辑 漏洞验证 补丁分析 在集群中探索 参考资料 在许多组织中&#xff0c;所运行的很大一部分服务和应用是 Windows 应用。Windows 容器提供了一种封装进程和包依赖项的方式&#xff0c;从而简化了 DevOps 实践&#xff0c;令 Windows 应用程序…

【xdma】 pcie.bar设置

FPGA优质开源项目– PCIE通信 xdma 两者保持一致 FPGA开源项目 – PCIE I/O控制卡 xdma PCIe的XDMA应用 读写部分分为两种&#xff0c;一种是数据的读写&#xff0c;另一种是配置数据的读写&#xff0c;在数据读写部分&#xff0c;DMA通过MIG控制DDR完成数据读写。配置数据…

使用 Tkinter 制作一个进制转换工具,好用!

在平时工作学习当中&#xff0c;我们经常会编写一些简单的 Python GUI 工具&#xff0c;以此来完成各种各样的自动化任务&#xff0c;比如批量处理文件&#xff0c;批量处理图片等等。当我们进行这些工具的编写之时&#xff0c;往往只关注了功能的实现&#xff0c;而忽略了页面…

基于Docker的软件环境部署脚本,持续更新~

使用时CtrlF搜索你想要的环境&#xff0c;如果没有你想要的环境&#xff0c;可以评论留言&#xff0c;会尽力补充。 本文提供的部署脚本默认参数仅适合开发测试&#xff0c;请根据实际情况调节参数。 数据库 MySQL version: 3.9 services:mysql:image: mysql:8.0.35container…