C语言学习第三篇分支循环全

分⽀和循环

选择结构程序设计

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

1. if语句

1.1 if

if 语句的语法形式如下:

if ( 表达式 )
语句

表达式成⽴(为真),则语句执⾏,表达式不成⽴(为假),则语句不执⾏在C语⾔中,0为假,⾮0表⽰真,也就是表达式的结果如果是0,则语句不执⾏,表达式的结果如果不是0,则语句执⾏。

1.2 else

if ( 表达式 )
语句1
else
语句2
练习:输⼊⼀个年龄,>=18岁就输出:成年,否则就输出:未成年

 #include <stdio.h>
 int main()
 {
   int age = 0;
   scanf("%d", &age);
   if(age>=18)
    printf("成年\n");
  else
    printf("未成年\n");
 return 0;
 }

1.3 分⽀中包含多条语句

默认情况下,if和else的后边只能跟一条语句。如果使用多条语句可以用{}括起来else 后也可以跟上⼤括号。(单条语句也可以加大括号)

 #include <stdio.h>
 int main()
 {
   int age = 0;
   scanf("%d", &age); 
   if(age >= 18) //if 后使⽤{} 控制多条语句这个块也叫:
                 //程序块,或者复合语句 
    {
        printf("成年了\n");
        printf("可以谈恋爱了\n");
    }
   else //else 后使⽤{}控制多条语句这个块也叫:
   		//程序块,或者复合语句
    {
        printf("未成年\n");
        printf("不可以早恋哦\n");
    }
    return 0;
 }

1.4 嵌套if

if else 语句中,else可以与另⼀个if语句连⽤,构成多重判断。
⽐如:要求输⼊⼀个整数,判断输⼊的整数是0,还是正数或者负数。请看如下代码:

 #include <stdio.h>
 int main()
 {
   int num = 0;
   scanf("%d", &num);
   if(num == 0)
       printf("输⼊的数字是0\n");
   else
     {
        if(num > 0)
           printf("输⼊的数字是正数\n");
        else
           printf("输⼊的数字是负数\n");
     }
     return 0;
 }
//方法二
 #include <stdio.h>
 int main()
 {
   int num = 0;
   scanf("%d", &num);
   if(num == 0)
      printf("输⼊的数字是0\n");
   else if  (num > 0)
      printf("输⼊的数字是正数\n");
   else
      printf("输⼊的数字是负数\n");
   return 0;
}
//方法三
 #include <stdio.h>
 int main()
 {
   int num = 0;
   scanf("%d", &num);
   if (num >= 0)
   {
      if(num == 0)
          printf("输⼊的数字是0\n");
      else
          printf("输⼊的数字是正数\n");
   }
   else
   {
      printf("输⼊的数字是负数\n");
   }
   return 0;
}

练习:输⼊⼀个⼈的年龄
如果年龄<18岁,打印"少年"
如果年龄在18岁⾄44岁打印"⻘年"
如果年龄在45岁⾄59岁打印"中⽼年"
如果年龄在60岁⾄89岁打印"⽼年"
如果90岁及以上打印"⽼寿星"

//方法一
#include <stdio.h>
 int main()
 {
    int age = 0;
    scanf("%d", &age);
    if(age<18)
        printf("少年\n");
    else //age>=18
    {
           if(age<=44)//18~44
               printf("⻘年\n");
           else //>44
           {
                if(age<=59) //45~59
                     printf("中⽼年\n");
                else //>59
                {
                       if(age<=89)
                            printf("⽼年\n");
                        else //>89
                            printf("⽼寿星\n");
                }
           }
     }
     return 0;
 }
//方法二
#include <stdio.h>
 int main()
 {
     int age = 0;
     scanf("%d", &age);
     if(age<18)
        printf("少年\n");
     else if(age<=44)// 18~44
        printf("⻘年\n");
     else if(age<=59) // 45~59
        printf("中⽼年\n");
     else if(age<=89)
        printf("⽼年\n");
     else //>89
        printf("老寿星\n");
     return 0;
  }

1.5 悬空else问题

如果有多个if和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匹配,而第一个if (a == 1 )不成立所以嵌套的if else没有机会执行
代码应该改成以下好理解一些:

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

用if语句实现选择结构的总结

一.If语句的三种基本形式

(1)if(表达式)    语句
在这里插入图片描述
(2)if(表达式)    语句1
    else        语句2

在这里插入图片描述
(3)if  (表达式1)  语句1
else if  (表达式2)语句2
else if  (表达式3)语句3
 …
else if(表达式m)语句m
else语句n
在这里插入图片描述

在这里插入图片描述

二.选择结构的嵌套

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

例如:
输入三个数a,b,c,要求按由小到大的顺序输出。
if a>b 将a和b对换
         (a是a、b中的小者)
if a>c 将a和c对换
          (a是a、c中的小者,是三者中最小者)
if b>c 将b和c对换
         (b是b、c中的小者,是三者中次小者)

#include <stdio.h>
int main() 
{
	float a,b,c,t;
	scanf("%f,%f,%f",&a,&b,&c);
	if(a>b)
		{t=a;a=b;b=t;}
	if(a>c)
		{t=a;a=q;c=t;}
		if(b>c)
		{t=b;b=c;c=t;}
		printf("%5.2f,%5.2f,%5.2f\n",a,b,c);
}

2. 关系操作符

关系表达式

  • 关系运算符两个常量、变量或表达式(可以是算术表达式、关系表达式,逻辑表达式,赋值表达式)接起来的式子,称关系表达式。

关系表达式里运用的运算符叫关系运算符
主要有:>大于 <小于 >= 大于等于 <=小于等于 ==等于 !=不等于
关系表达式通常返回0或1表示真假
C语言中0表示假,非0表示真 3>5表示真返回值为1
多个关系运算符不宜使用比如a>b>c

#include <stdio.h>
int main()
{
	int a = 3;
	int b = 7;
	int c = 4;
	if (a< b < c)
	{
		printf("hehe\n");//hehe
		//因为a==3 <b==7为真,所以1,又因为1<4,又为真所以为真打印出呵呵
	}
	return 0;
}


多个关系运算符不宜使用比如a>b>c
应该为&&符号来写的

i < j && j < k

程序员喜欢将变量写在等号的右边。

if (3 == x)

在这里插入图片描述

举例:⽐如:我们输⼊⼀个年龄,如果年龄在18岁~36岁之间,我们输出⻘年。

#include <stdio.h>
int main()
{
 	int age = 0;
 	scanf("%d", &age);
 	if(age>=18 && age<=36)
 	//错误写法:if(18<=age<=36)
	 {
 		printf("⻘年\n");
 	}
 	return 0;
}

3. 条件操作符(三目操作符)

  • 条件运算符是C语言中唯一的一个三目运算符
  • 优先级仅高于赋值运算符,低于关系运算符和算术运算符。结合性为右结合。
  • 条件运算符的结合方向为“自右至左”
  • 使用场合:若在if语句中,当被判别的表达式的值为“真”或“假”时,都执行一条赋值语句且向同一个变量赋值时,可以用一个条件运算符来处理。

形式:

表达式1  ?  表达式2  :  表达式3

条件操作符的计算逻辑:1.若表达式1为真,表达式2计算为整个表达式的结果;2.若表达式1为假,表达式3计算计算的结果是整个表达式的结果。(也就是说判断表达式表达式1,若为真则执行表达式表达式2,假则执行表达式表达式3)
在这里插入图片描述

if (a>5)
   b=3;
else
   b=-3;
等价于
b=a>5?3:-3;

练习:求两个数中较大值

#include <stdio.h>
int main()
{
 int a = 0;
 int b = 0;
 scanf("%d %d", &a, &b);
 int m = a>b ? a : b;
 printf("%d\n", m);
 return 0;
}

4. 逻辑操作符:&& ,|| , !和逻辑表达式

一.逻辑运算符

!:逻辑取反运算符(改变单个表达式的真假)。
&&:逻辑与(两侧的表达式都为真,则为真,否则为假)。
||:逻辑或(两侧⾄少有⼀个表达式为真,则为真,否则为假)。

C语言中,非0表示真,0表示假

在这里插入图片描述

1. 逻辑取反运算符
a!a
非00
01

我们有⼀个变量叫 flag ,如果flag为假,要做⼀个什么事情,就可以这样写代码:

#include <stdio.h>
int main()
{
 int flag = 0;
 if(!flag)
 {
 printf("do something\n");
 }
 return 0;
}
//如果 flag 为真, !flag 就是假,如果 flag 为假, !flag 就是真
//所以上⾯的代码的意思就是 flag 为假,执⾏if语句中的代码。
//也就是如果输入为非零的数比如8,8为真,所以!flag为假,所以不进入if循环,什么都不输出
//如果输入为0,0为假,所以!flag为真,所以进入if循环输出do something

2. 逻辑与运算符
aba&&b
非0非01
非000
0非00
000

&& 逻辑与运算符,也是并且的意思, && 是⼀个双⽬操作符,使⽤的⽅式是 a&&b.两侧的表达式都为真,则为真,否则为假

⽐如:如果我们说⽉份是3⽉到5⽉,是春天

#include <stdio.h>
int main()
{
	int month = 0;
	scanf("%d", &month);
	if(month >= 3 && month <= 5)
	//表达的意思就是month既要⼤于等于3,⼜要⼩于等于5,必须同时满⾜。
	{
 		printf("春季\n");
	}
	return 0;
}
3. 逻辑或运算符

在这里插入图片描述
|| 逻辑或运算符,也就是或者的意思, || 也是⼀个双⽬操作符,使⽤的⽅式是 a || b,两侧⾄少有⼀个表达式为真,则为真,否则为假

⽐如:我们说⼀年中⽉份是12⽉或者1⽉或者2⽉是冬天

#include <stdio.h>
int main()
{
	int month = 0;
	scanf("%d", &month);
	if(month == 12 || month==1 || month == 2)
	{
 		printf("冬季\n");
	}
	return 0;
}
4. 练习:闰年的判断

输⼊⼀个年份year,判断year是否是闰年
闰年判断的规则:

  1. 能被4整除并且不能被100整除是闰年
  2. 能被400整除是闰年
#include <stdio.h>
//代码二
int main()
{
 	int year = 0;
	scanf("%d", &year);
 	if((year%4==0 && year%100!=0) || (year%400==0))
 	{
 		printf("是闰年\n");
 	}
 	return 0;
} 
#include <stdio.h>
//代码1 
int main()
{
 	int year = 0;
 	scanf("%d", &year);
 	if(year%4==0 && year%100!=0)
 		printf("是闰年\n");
 	else if(year%400==0)
 		printf("是闰年\n");
 
 return 0;
}
5. 短路
  • C语⾔逻辑运算符还有⼀个特点,它总是先对左侧的表达式求值,再对右边的表达式求值,这个顺序是保证的。

  • 如果左边的表达式满⾜逻辑运算符的条件,就不再对右边的表达式求值。这种情况称为“短路”。

  • if(month >= 3 && month <= 5)
    表达式中&&的左操作数是 month >= 3 ,右操作数是 month <= 5 ,当左操作数 month >= 3 的结果是0的时候,即使不判断 month <= 5 ,整个表达式的结果也是0(不是春季)
    所以,对于&&操作符来说,左边操作数的结果是0的时候,右边操作数就不再执⾏。

  • if(month == 12 || month==1 || month == 2)
    如果month= =12,则不⽤再判断month是否等于1或者2,整个表达式的结果也是1(是冬季)。
    所以, || 操作符的左操作数的结果不为0时,就⽆需执⾏右操作数。

像这种仅仅根据左操作数的结果就能知道整个表达式的结果,不再对右操作数进⾏计算的运算称为短路求值

#include <stdio.h>
int main()
{
 int i = 0,a=0,b=2,c =3,d=4;
 i = a++ && ++b && d++;
//先使用a++为0,且是&&运算符,所以i=0为假,与运算中有一个为假则为假所以后面都不看了,a++后a=1
 printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);//1234
 return 0;
#include <stdio.h>
int main()
{
 int i = 0,a=1,b=2,c =3,d=4;
 i = a++ && ++b && d++;
 //a++后a=2,i=1,i为真可以继续算。++b后b=3,a++ && ++b 为1&&3,1和3均为真所以i为真为1。
 //再继续看d++,d=5;1&&4其中1为真4为真所以i为真为1
 printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);//12335
 return 0;
#include <stdio.h>
int main()
{
 int i = 0,a=1,b=2,c =3,d=4;
 i = a++||++b||d++;
 //a=2,a++后i的值为1为真,所以后面不用算了因为||有一个为真则真
 printf("a = %d\n b = %d\n c = %d\nd = %d\n", a, b, c, d);//2234
 return 0;
}

二.逻辑表达式

在这里插入图片描述

三.总结

在这里插入图片描述
在这里插入图片描述
逻辑运算符还有⼀个特点:它总是先对左侧的表达式求值,再对右边的表达式求值
如果左边的表达式满⾜逻辑运算符的条件,就不再对右边的表达式求值。

在逻辑表达式的求解中,并不是所有的逻辑运算符都要被执行。
(1)a&&b&&c
只有ā为真时,才需要判断b的值
只有a和b都为真时,才需要判断c的值。
(2)a||b||c
只要a为真,就不必判断b和c的值
只有a为假,才判断b。
a和b都为假才判断c。

5. switch语句

switch语句语句是⼀种特殊形式的if…else结构。⽤于判断条件有多个结果的情况。

switch (expression) {
case value1: statement
case value2: statement
default: statement
}

1. 根据表达式不同的值,执行相应的case分支,如果找不到对应的值就执行default分支。
2.switch后的表达式必须是整形表达式(字符也是整型)不能是变量(所以也可以switch(ch))
3.case后的值,必须是整型常量表达式(所以也可以case ‘a’ 或者case ‘b’)

if(n%3 == 0)
     printf(“整除,余数为0\n”);
else if(n%3 == 1)
     printf(“余数是1\n”);
else
     printf(“余数是2\n”);
等价于
switch(n%3)
{
case 0:
      printf(“整除,余数为0\n”);
      break;
case 1:
      printf(“余数是1\n”);
      break;
case 2:
      printf(“余数是2\n”);
       break;
}
注意:
1. case和后边的数字之间必须有空格
2.每一个case语句中的代码执⾏完成后,需要加上break,才能跳出这个switch语句
3.break不是每个case语句都能有

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

练习:1. 输⼊1~5,输出的是“⼯作⽇”;
2. 输⼊6~7,输出“休息⽇”

#include <stdio.h>
int main()
{
 int day = 0;
 scanf("%d", &day);
 switch(day)
 {
 	case 1case 2:
 	case 3:
 	case 4:
 	case 5:
		 printf("⼯作⽇\n");
 		 break;
 	case 6:
 	case 7:
 		printf("休息⽇\n");
 		break;
	default://不是1~7的值就用default
 		printf("输⼊错误\n");
 		break;
 }
 return 0;
}

循环

6. while循环

在这里插入图片描述

while语句用来实现“当型”循环结构*
在这里插入图片描述

执⾏判断表达式,表达式的值为0,循环直接结束;表达式的值不为0,则执⾏循环语句,语句执⾏完后再继续判断,是否进⾏下⼀次判断。

while(表达式)
       语句;  //如果循环体想包含更多的语句,可以加上⼤括号

  • 执行过程:当表达式为非0值时,执行while语句中的内嵌语句。其特点是:先判断表达式,后执行语句。
  • 注意:
    1. 循环体如果包含一个以上的语句,应该用花括弧括起来,以复合语句形式出现。
    2. 在循环体中应有使循环趋向于结束的语句。如果无此语句,则i的值始终不改变,循环永不结束。

if和while的对比

if(表达式)
       语句;
while(表达式)
       语句;  //如果循环体想包含更多的语句,可以加上⼤括号

//代码1 
#include <stdio.h>
int main()
{
	int n = 10;
 	if(n > 10)
 	printf("hehe\n"); //if后边条件满⾜,打印⼀次hehe 
	 return 0;
}
//代码2 
#include <stdio.h>
int main()
{
	int n = 10;
 	while(n > 10)
 	printf("hehe\n"); //while后边的条件满⾜,死循环的打印hehe 
 	return 0;
}

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

练习:在屏幕上打印1~10的值

//i=1,i为循环变量,然后打印i,然后给i,+1
#include <stdio.h>
int main()
{
 int i = 1;
 while(i<=10)
 {
 	printf("%d ", i);//打印加个空格好看一些。输出:1 2 3 4 5 6 7 8 9 10
 	i++;
 	//或者i = i+1;
 }
 return 0;
}

或者

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

练习:逆序打出数字
例如:1234 输出:4 3 2 1

//题⽬解析
//1. 要想得到n的最低位,可以使⽤n%10的运算,得到的余数就是最低位,如:1234%10得到4
//2. 要想去掉n的最低位,找出倒数第⼆位,则使⽤ n=n/10 操作就可以去掉最低位的,如:n=1234/10得到123,123相较于1234就去掉了最低位,123%10就得到倒数第⼆位3。
//3. 循环1和2两个步骤,在n变成0之前,就能到所有的位。
#include <stdio.h>
int main()
{
	int n = 0;
	scanf("%d",&n);
	while(n)//或者(n!=0)
	{
		printf("%d ",n%10);//有个空格好看点
		n=n/10;
		//本题比如输入1234先1234%10为4打印出来,然后1234/10=123,循环n=123不等于0,然后就进入循环,123%10为3打印出来,然后123/10=12,n=12不等于0,所以又进入循环12%10为2打印出来,然后12/10=1,n=1不等于0所以又进入循环,1%10为1打印出来然后1/10=0,n=0为假后进不去循环了。所以就打印出 4 3 2 1
	}
	return 0}

7. do-while循环

在这里插入图片描述

do
        语句;
while(表达式);

while和for都先判断后循环,do while是先循环后判断。
do while的循环体至少循环一次

在屏幕上打印1~10的值

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

输⼊⼀个正整数,计算这个整数是⼏位数?
例如:
输⼊:1234输出:4
输⼊:12输出:2

#include <stdio.h>
int main()
{
 	int n = 0;
 	scanf("%d", &n);
 	int cnt = 0;
 	do
 	{
 	cnt++;//因为一个正整数至少是一位数,所以必须输出一位。比如123先至少知道有一位数所以一上来先加加然后弄出个一位数下面n/10去掉3。然后n=12,不等于0可以入循环,然后又cnt++又数量加1位数,然后n/10去掉2。然后n=1,不等于0还可以入循环又加一位数,后又去掉一位数1/10,最后剩下0就进不去循环了就可以打印数的数了。总的;来说就是加一位减一位这样的方式来数,也就是先统计然后去掉一位数的方法
 //剩下1cunt++又数量+1,n/10去掉1。这样就算出数量1+1+1=3
 	n = n / 10;
 	} while (n);
 	printf("%d\n", cnt);
 	return 0;
}

8. for循环

在这里插入图片描述

for(表达式1; 表达式2; 表达式3)
     语句;//如果循环体想包含更多的语句,可以加上⼤括号
表达式1⽤于循环变量的初始化
表达式2⽤于循环结束条件的判断
表达式3⽤于循环变量的调整

⾸先执⾏ 表达式1 初始化循环变量,接下来就是执⾏ 表达式2 的判断部分, 表达式2 的结果如果 = = 0,则循环结束; 表达式2 的结果如果!=0则执⾏循环语句,循环语句执⾏完后,再去执⾏表 达式3 ,调整循环变量,然后再去 表达式2 的地⽅执⾏判断, 表达式2 的结果是否为0,决定循环是否继续。

for循环的初始化部分只被执行一次
说明

  1. for语句的一般形式中的“表达式1”可以省略,此时应在for语句之前给循环变量赋初值。注意省略表达式1时,其后的分号不能省略。如
    int i=1;
    for( ; i<=100; i++) sum=sum+i;
    执行时,跳过“求解表达式1”这一步,其他不变。
  2. 如果表达式2省略,即不判断循环条件,循环无终止地进行下去。也就是认为表达式2始终为真
    例如:for(i=1; ;i++) sum=sum+i;
    表达式1是一个赋值表达式,表达式2空缺。它相当于:
    i=1;
    while(1)
    {sum=sum+1; i++;}
  3. 表达式3也可以省略,但此时程序设计者应另外设法保证循环能正常结束。如:
    for(i=1;i<=100;)
    { sum=sum+i; i++;}
    在上面的for语句中只有表达式1和表达式2,而没有表达式3。但是i++的操作不放在for语句的表达式3的位置处,而作为循环体的一部分,效果是一样的,都能使循环正常结束。
  4. 可以省略表达式1和表达式3,只有表达式2,即只给循环条件。如:
    for(;i<=100;) while(i<=100) {sum=sum+i; 相当于 { sum=sum+i;
    i++;} i++;}
    在这种情况下,完全等同于while语句。可见for语句比while语句功能强,除了可以给出循环条件外,还可以对循环变量赋初值,使循环变量自动增值等。
  5. 3个表达式都可省略,如:
    for( ; ; ) 语句
    相当于
    while(1) 语句
    即不设初值,不判断条件(认为表达式2为真值),循环变量不增值。无终止地执行循环体。
  6. 表达式1可以是设置循环变量初值的赋值表达式,也可以是与循环变量无关的其他表达式。如:
    for (sum=0;i<=100;i++)
    sum=sum+i;
    表达式3也可以是与循环控制无关的任意表达式。
  7. 表达式1和表达式3可以是一个简单的表达式,也可以是逗号表达式,即包含一个以上的简单表达式,中间用逗号间隔。如:
    for(sum=0, i=1; i<=100; i++)sum=sum+i;或
    for(i=0, j=100; i<=j; i++, j–) k=k+i+j;
    • 表达式1和表达式3都是逗号表达式,各包含两
      个赋值表达式,即同时设两个初值,使两个变量
      增值.
    • 在逗号表达式内按自左至右顺序求解,整个逗号表达式的值为其中最右边的表达式的值。如:
      for(i=1;i<=100;i++,i++) sum=sum+i;
      相当于
      for(i=1;i<=100;i=i+2) sum=sum+i;
  8. 表达式2一般是关系表达式(如i<=100)或逻辑表达式 (如a<b && x<y),但也可以是数值表达式或字符表达式,只要其值为非零,就执行循环体。

与while语句类似
#include <stdio.h>
int main()
{
int i = 1;//循环变量的初始化
while(i<=10)//循环结束条件的判断
{
printf("%d ", i);
i = i+1;//循环变量的调整
}
return 0;
}
练习:在屏幕上打印1~10的值

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

练习计算1~100之间3的倍数的数字之和

#include <stdio.h>
int main()
{
 	int i = 0;
 	int sum = 0;
 	for(i=1; i<=100; i++)//1~100
 	{
 		//printf("%d ", i)
		//判断i是否是3的倍数
 		if(i % 3 == 0)
 		sum += i;//等于sum = sum + i
 	}
 	printf("%d\n", sum);
 	return 0;
}
//⼩⼩的优化 
//如果能直接产⽣3的倍数的数字就省去了多余的循环和判断 
#include <stdio.h>
int main()
{
 	int i = 0;
 	int sum = 0;
 	for(i=3; i<=100; i+=3)
 	{
 		sum += i;
 	}
 	printf("%d\n", sum);
	return 0;
}

9. 循环的嵌套

三种循环 while , do while , for ,这三种循环往往会嵌套在⼀起
练习
找出100~200之间的素数,并打印在屏幕上。
注:素数⼜称质数,只能被1和本⾝整除的数字。

#include <stdio.h>
int main()
{
 	int i = 0;
 	int count = 0;
 	for(i=100; i<=200; i++)//循环产⽣100~200的数字
 	{
 	//判断i是否为素数 
 	int j = 0;
 	int flag = 1;//假设i是素数 
 	for(j=2; j<=i-1; j++) //循环产⽣2~i-1之间的数字 。 这里也可以改为for(j=2; j<i; j++)
 	//如果2~i-1之间有数字能整除i,则i不是素数
 	//如果都不能整除,则i是素数。
 	//比如数字5=i,先弄出 2 3 4 看有数字可以整除5吗,发现不可以整除则说明i为数字5是素数。
 		{
 			if(i % j == 0)//2~i-1之间有数字能整除i
 			{
 				flag = 0;//i不是素数
 				break;
 			}
 		}
 	if(flag == 1)
 		{
 			count++;//素数数量计算
 			printf("%d ", i);
		}
 	}
 	printf("\ncount=%d\n",count);
 	return 0;
}

10.几种循环的比较

  1. 四种循环都可以用来处理同一问题,一般情况下它们可以互相代替。但一般不提倡用goto型循环。
  2. 在while循环和do-while循环中,只在while后面的括号内指定循环条件,因此为了使循环能正常结束,应在循环体中包含使循环趋于结束的语句(如i++,或i=i+1等)。
  • for循环可以在表达式3中包含使循环趋于结束的操作,甚至可以将循环体中的操作全部放到表达式3中。因此for语句的功能更强,凡用while循环能完成的,用for循环都能实现。
  1. 用while和do-while循环时,循环变量初始化的操作应在while和do-while语句之前完成。
    而for语句可以在表达式1中实现循环变量的初始化。
  2. while循环、do-while循环和for循环,可以用break语句跳出循环,用continue语句结束

11. break和continue语句

break 的作⽤是⽤于永久的终⽌循环
continue 的作⽤是跳过本次循环中 continue 后边的代码,在for和while循环中有所差异的
在这里插入图片描述

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

#include <stdio.h>
int main()
{
   int i = 1;
   while(i<=10)
   {
      if(i == 5)
          break;
 //后面终止了5以后不打印break用于终止整个循环
      printf("%d ", i);//1 2 3 4
      i = i+1;
    }
    return 0;
}


```c
#include <stdio.h>
int main()
{
   int i = 1;
   while(i<=10)
   {
      if(i == 5)
          continue;
 //当i等于5后,就执⾏continue,直接跳过continue的代码,去循环的判断的地⽅ 
 //因为这⾥跳过了i = i+1,所以i⼀直为5,程序陷⼊和死循环 
      printf("%d ", i);
      i = i+1;
    }
    return 0;
}
#include <stdio.h>
int main()
{
   int i = 1;
   for(i=1; i<=10; i++)
   {
       if(i == 5)
          continue;//这⾥continue跳过了后边的打印,来到了i++的调整部分 
       printf("%d ", i);//1 2 3 4 6 7 8 9 10 11
    }
    return 0;
}

12. goto语句

goto 语句可以实现在同⼀个函数内跳转到设置好的标号处。
在多层循环的代码中,如果想快速跳出使⽤ goto 就⾮常的⽅便了。

#include <stdio.h>
int main()
{
 	printf("hehe\n");
 	if1goto end;
 	printf("haha\n");
 
end:
 	printf("end\n"); 
 	return 0;
 	//打印:hehe
 	//      end
 	//       -
 	//直接跳过了haha
}
#include <stdio.h>
int main()
{
again:
 	printf("hehe\n");//死循环打印hehe
 	goto again;
 	return 0;
}
#include <stdio.h>
int main()
{
 	printf("hehe\n");
 	goto next;
 	printf("haha\n");
 
next:
 	printf("跳过了haha的打印\n"); 
 	return 0;
}

for(…)
{
     for(…)
     {
          for(…)
          {
               if(disaster)
                     goto error;
          }
      }
}
error:
        //…

本来 for 循环想提前退出得使⽤ break ,⼀个 break 只能跳出⼀层 for 循环,如果3层循环嵌套就得使⽤3个 break 才能跳出循环,所以在这种情况下我们使⽤ goto 语句就会更加的快捷

13. 例题:关机程序

//方法一
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
	char input[20] = { 0 };
	system("shutdown -s -t 60");//运用这个函数要加库函数头#include<stdlib.h>
again:
	printf("请注意,你的电脑在一分钟内关机,如果输入:你是美女,就取消关机\n");
	scanf("%s", input);//因为输入你是美女是一段字符串所以要用%s,并且把输入信息放在input数组中
	//判断input中存放的是否是“你是美女”
	//两个字符串比较相等的时候不是使用==,而是使用strcmp函数,这个函数要加函数头#include<string.h>
	if (strcmp("你是美女",input) == 0)
	{
		system("shutdown -a");//取消关机指令
	}
	else
	{
		goto again;//输入不正确就返回跳转到上面的again又执行again以下的语句
	}
	return 0;
}
//方法二
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
	char input[20] = { 0 };
	system("shutdown -s -t 60");//运用这个函数要加库函数头#include<stdlib.h>
	while (1)
	{
		printf("请注意,你的电脑在一分钟内关机,如果输入:你是美女,就取消关机\n");
		scanf("%s", input);//因为输入你是美女是一段字符串所以要用%s,并且把输入信息放在input数组中
		//判断input中存放的是否是“你是美女”
		//两个字符串比较相等的时候不是使用==,而是使用strcmp函数,这个函数要加函数头#include<string.h>
		if (strcmp("你是美女", input) == 0)
		{
			system("shutdown -a");//取消关机指令
			break;//执行完就break这样才能跳出循环不然就一直为真进入循环
		}

	}
	return 0;
}

14. 猜数字游戏

游戏要求:

  1. 电脑⾃动⽣成1~100的随机数
  2. 玩家猜数字,猜数字的过程中,根据猜测数据的⼤⼩给出⼤了或⼩了的反馈,直到猜对,游戏结束

1. 随机数生成

1. rand

C语⾔提供了⼀个函数叫rand,这函数是可以⽣成随机数的,函数原型如下所⽰:

int rand (void);
rand函数的使⽤需要包含⼀个头⽂件是:stdlib.h

rand函数会返回⼀个伪随机数,这个随机数的范围是0~RAND_MAX之间,这个RAND_MAX的⼤⼩是依赖编译器上实现的,但是⼤部分编译器上是32767。你会发现第一次和第二次很多次生成的随机数都一样的。
测试⼀下rand函数,这⾥多调⽤⼏次,产⽣5个随机数:

#include <stdio.h>
#include <stdlib.h>
int main()
{
 	printf("%d\n", rand());
 	printf("%d\n", rand());
 	printf("%d\n", rand());
 	printf("%d\n", rand());
 	printf("%d\n", rand());
 	return 0;
 	//发现不管多少次运行,运行出来都是下面5个数
 	//41
 	//18467
 	//6334
 	//26500
 	//19169
 	//我们可以看到虽然⼀次运⾏中产⽣的5个数字是相对随机的,但是下⼀次运⾏程序⽣成的结果和上⼀次⼀模⼀样,这就说明有点问题。
}

rand函数⽣成的随机数是伪随机的,伪随机数不是真正的随机数,是通过某种算法⽣成的随机数。⽽**rand函数是对⼀个叫“种⼦”的基准值进⾏运算⽣成的随机数。**之所以前⾯每次运⾏程序产⽣的随机数序列是⼀样的,那是因为rand函数⽣成随机数的默认种⼦是1。如果要生成不同的随机数,就要让种⼦是变化的

2. srand

C语⾔中⼜提供了⼀个函数叫srand,⽤来初始化随机数的⽣成器的,srand的原型如下:

void srand (unsigned int seed);

程序中在调⽤rand函数之前先调⽤srand函数,通过srand函数的参数seed来设置rand函数⽣成随机数的时候的种⼦,只要种⼦在变化,每次⽣成的随机数序列也就变化起来了。那也就是说给srand的种⼦是如果是随机的,rand就能⽣成随机数;在⽣成随机数的时候⼜需要⼀个随机数,这就⽭盾了。

3. time

在程序中我们⼀般是使⽤程序运行的时间作为种⼦的,因为时间时刻在发⽣变化的。在C语⾔中有⼀个函数叫time,就可以获得这个时间,time函数原型如下:

time_t time (time_t* timer);

time函数会返回当前的⽇历时间,其实返回的是1970年1⽉1⽇0时0分0秒到现在程序运⾏时间之间的差值,单位是秒。返回的类型是time_t类型的,time_t类型本质上其实就是32位或者64位的整型类型。
time函数的参数timer如果是⾮NULL的指针的话,函数也会将这个返回的差值放在timer指向的内存中带回去。
如果timer是NULL,就只返回这个时间的差值。time函数返回的这个时间差也被叫做:时间戳。
time函数的时候需要包含头⽂件:time.h

//VS2022 上time_t类型的说明 
#ifndef _CRT_NO_TIME_T
 	#ifdef _USE_32BIT_TIME_T
 		typedef __time32_t time_t;
 	#else
 		typedef __time64_t time_t;
 	#endif
#endif
typedef long __time32_t;
typedef __int64 __time64_t;

如果只是让time函数返回时间戳,我们就可以这样写:

time(NULL);//调⽤time函数返回时间戳,这⾥没有接收返回值

那我们就可以让⽣成随机数的代码改写成如下:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
 	//使⽤time函数的返回值设置种⼦ 
 	//因为srand的参数是unsigned int类型,我们将time函数的返回值强制类型转换 
 	//设置随机数的生成起点
 	srand((unsigned int)time(NULL));
 	printf("%d\n", rand());
 	printf("%d\n", rand());
 	printf("%d\n", rand());
 	printf("%d\n", rand());
 	printf("%d\n", rand());
 	return 0;
}
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
int main()
{
	//设置随机数的生成起点
	srand((unsigned int)time(NULL));
	for (int i = 0; i < 10; i++)
	{
		printf("%d\n", rand());
	}
	return 0;
}

srand函数是不需要频繁调用的,⼀次运⾏的程序中调⽤⼀次就够了。

4. 设置随机数的范围

如果我们要⽣成0~99之间的随机数,⽅法如下:

rand() % 100;//余数的范围是0~99

如果要⽣成1~100之间的随机数,⽅法如下:

rand()%100+1;//%100的余数是0 ~ 99,0 ~ 99的数字+1,范围是1~100

如果要⽣成100~200的随机数,⽅法如下:

100 + rand()%(200-100+1)
//余数的范围是0 ~ 100,加100后就是100~200

所以如果要⽣成a~b的随机数,⽅法如下:

a + rand()%(b-a+1)

2. 猜数字游戏实现

代码

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
//void 表示函数不返回任何值
void menu()
{
	printf("***********************\n");
	printf("****** 1. play ******\n");
	printf("****** 0. exit ******\n");
	printf("***********************\n");	
}
void game()
{
	//游戏逻辑
	//1. 生成随机数
	int r = rand() % 100 + 1;//生成随机数1~100
	//2. 猜数字,一般不是一次猜对所以要使用循环
	int guess = 0;
	while (1)//只要没猜对就一直循环猜
	{
		printf("请猜数字:");
		scanf("%d", &guess);
		if (guess < r)//如果猜的数字小于随机数r
		{
			printf("猜小了\n");
		}
		else if (guess > r)//如果猜的数字大于随机数r

		{
			printf("猜大了\n");
		}
		else
		{
			printf("恭喜你,猜对了\n");
			break;
		}
	}
}

int main()
{
	int input = 0;
	//设置随机数的生成起点
	//整个工程中只调用一次就可以了,所以不放入void game函数中
	srand((unsigned int)time(NULL));
	//一上来就要打印菜单,所以就用do-while循环比较合适
	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;
}

还可以加上猜数字的次数限制,如果5次猜不出来,就算失败

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
//void 表示函数不返回任何值
void menu()
{
	printf("***********************\n");
	printf("****** 1. play ******\n");
	printf("****** 0. exit ******\n");
	printf("***********************\n");	
}
void game()
{
	//游戏逻辑
	//1. 生成随机数
	int r = rand() % 100 + 1;//生成随机数1~100
	//2. 猜数字,一般不是一次猜对所以要使用循环
	int guess = 0;
	int count = 5;//5次机会
	while (count)//count不等于0就进入循环
	{
		printf("还有%d次机会\n", count);
		printf("请猜数字:");
		scanf("%d", &guess);
		if (guess < r)//如果猜的数字小于随机数r
		{
			printf("猜小了\n");
		}
		else if (guess > r)//如果猜的数字大于随机数r

		{
			printf("猜大了\n");
		}
		else
		{
			printf("恭喜你,猜对了\n");
			break;//记住猜对了直接break跳出game函数了不经过后面的if (count == 0)
		}
		count--;//猜一次count(次数减少一次)
	}
	//到这要么就是count已经为0了没有机会了,要么就是已经猜对了跳出来了
	if (count == 0)
	{
		printf("用完了所有的机会,猜数字失败,正确的值是:%d\n",r);
	}
}

int main()
{
	int input = 0;
	//设置随机数的生成起点
	//整个工程中只调用一次就可以了,所以不放入void game函数中
	srand((unsigned int)time(NULL));
	//一上来就要打印菜单,所以就用do-while循环比较合适
	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;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值