5_6 5_7C语言_分支和循环语句

1、分支和循环语句

C语言可分为以下五类语句:

        1.表达式语句

        2.函数调用语句

        3.控制语句

        4.复合语句

        5.空语句

后面学的是控制语句。

控制语句用于控制程序的执行流程,以实现程序的各种结构方式,他们由特定的语句定义符组成,C语言有九种控制语句。(C语言是【结构化】的程序设计语言)

可分为以下三类:

1.条件判断语句也叫分支语句:if语句,switch语句;

2.循环执行语句:do while语句,whlie语句,for语句;

3.转向语句:break语句,goto语句,continue语句,return语句。

2、分支语句

2.1  if

语法结构:第一种:

if(表达式)

     语句;

表达式的内容为真,打印语句;为假就不打印。

#include<stdio.h>
int main()
{
	if (3 == 5)  //3==5为假
		printf("hehe\n");  //条件为假,不打印
	return 0;
}

结果: 

#include<stdio.h>
int main()
{
	if (3 == 3)  //3==3为真
		printf("hehe\n");  //条件为真,打印
	return 0;
}

结果: 

第二种:

if(表达式)

     语句1;

else

     语句2; 

 例子:

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

结果:

 

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

结果:

 

 另外:如果if语句后面语句1要写多条语句,要用代码块(就是要用一个大括号括起来),不能直接跟;语句2一样。

#include<stdio.h>
int main()
{
	int age = 10;
	if (age < 18)
	{
		printf("未成年\n");
		printf("不能喝酒\n");
	}
	else
		printf("成年\n");
	return 0;
}

结果:

 

第三种:多分支

 if(表达式1)

     语句1;

else if(表达式2)

     语句2;

else 

     语句3;

例子: 

#include<stdio.h>
int main()
{
	int age = 10;
	if (age < 18)
		printf("青少年\n");
	else if (age >= 18 && age < 28)//不能写成18<=age<28
		printf("青年\n");
	else if (age >= 28 && age < 40)
		printf("中年\n");
	else if (age >= 40 && age < 60)
		printf("壮年\n");
	else if (age >= 60 && age <= 100)
		printf("老年\n");
	else
		printf("老寿星\n");
	return 0;
}

 结果:

 注:这么多分支只会执行一条语句

在C语言中,0表示假,非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;
}

 结果:

 因为else是和离他最近的if匹配,所以,此时else语句匹配的是if(b==2)这条语句。

如果直接把上面这串代码复制到vs(我使用的编译器)里面,就是这样的。

单如果改成这样,就可以运行出结果,跟第一个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;
}

 结果:

代码风格 

1、变量的命名(有意义,规范)

2、空格,空行,换行

注:当一个常量和一个变量比较的时候,最好把常量放在左边

#include<stdio.h>
int main()
{
	int num = 3;
	if (5 == num)//这样如果少了一个等于号,也不会运行下去,会报错拦截下来
		//但如果写成if(num==5),这样就算少了一个"=",也不会报错,但会导致一些bug出现
		printf("hehe\n");
	return 0;
}

 练习

1、判断一个数是否为奇数;

2、输出1-100之间的奇数;

2.2  switch

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

比如:

输入1,输出星期一;输入2,输出星期二;输入3,输出星期三;输入4,输出星期四;

输入5,输出星期五;输入6,输出星期六;输入7,输出星期日;

如果写成if...else if ... else if 的形式太复杂了,用switch语句更简单。

语法介绍:

switch(整型表达式)

{

    语句项;

}

整型表达式:表达式的结果是整型

语句项:是一些case语句,如下:

case 整型常量表达式:

        语句;

 整型常量表达式:这里可以是字符,字符本质上也是个整型,因为字符存储的时候存的是它的ASCII码值,它也是整数。

 例子:

#include<stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
		printf("星期一\n");
	case 2:
		printf("星期二\n");
	case 3:
		printf("星期三\n");
	case 4:
		printf("星期四\n");
	case 5:
		printf("星期五\n");
	case 6:
		printf("星期六\n");
	case 7:
		printf("星期日\n");
	}
	return 0;
}

 结果:

case只是决定了入口,从case 3:这里进来,但是没告诉他从哪里出去,所以后面的都打印出来了。

 switch首先根据后面的整型表达式的值,决定他匹配哪个case语句,就从哪个case语句进去,进去之后,那这个switch语句从哪里跳出去呢,这个地方就有一个专门的跳转语句,叫break。如果星期三这执行完之后不想让他往下走,就给一个break。

#include<stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
		printf("星期一\n");
	case 2:
		printf("星期二\n");
	case 3:
		printf("星期三\n");
		break;//中断,停止的意思
	case 4:
		printf("星期四\n");
	case 5:
		printf("星期五\n");
	case 6:
		printf("星期六\n");
	case 7:
		printf("星期日\n");
	}
	return 0;
}

 结果:

 但如果是输入4,就又不会停下来

如果想停下来,就在每个case语句后面都加break。

#include<stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
		printf("星期一\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>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
		printf("weekday\n");
		break;
	case 2:
		printf("weekday\n");
		break;
	case 3:
		printf("weekday\n");
		break;
	case 4:
		printf("weekday\n");
		break;
	case 5:
		printf("weekday\n");
		break;
	case 6:
		printf("weekend\n");
		break;
	case 7:
		printf("weekend\n");
		break;
	}
	return 0;
}

 这样也行,但这种写法有点啰嗦,可以改成下面这样:

#include<stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	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;
}

 结果:

 说明:

1、case后面可以不加break,如果逻辑需要时,可以不加break

2、没有break的时候会持续往下走,这样就可以实现多个case匹配同一个执行语句的效果

编程好习惯:

在最后一个case语句的后面加上一条break语句。

(之所以这么写是可以避免出现在以前的最后一个case语句后面忘了添加break语句) 

 default字句

万一有人输入错了,不是1-7之间的数字,最好提示一下,

#include<stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	switch (day)
	{
	case 1:
	case 2:
	case 3:
	case 4:
	case 5:
		printf("weekday\n");
		break;
	case 6:
	case 7:
		printf("weekend\n");
		break;
	default:
		printf("选择错误\n");
		break;
	}
	return 0;
}

 结果:

练习:

3、循环语句

3.1  while

while语法结构:

while(表达式)
    循环语句;

 表达式为真,执行循环语句,再执行while语句,表达式为真,执行循环语句...表达式为假,推出while语句,注意,如果表达式一直真,此时while语句就是一个死循环。

执行流程图

 打印1-10数字  

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

结果:

遇到break

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

 结果:

 break终止整个循环,作用于while循环,不在if语句起作用

遇到continue

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

 结果:

后面光标一直在动,死循环了

分析:

#include<stdio.h>
int main()
{
	int i = 1;
	while (i <= 10)
	{
		if (5 == i)//当i=5为真时,执行这条语句,
			continue;//执行这条语句,会直接跳过本次循环continue后面的代码,此时i=5,
		//再进入while循环,又是if语句为真,又是一样,一直死循环
		printf("%d  ", i);
		i++;
	}
	return 0;
}

再改一下:

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

 结果:

 进入while循环就执行了i++;此时i=2,打印2,后面类推,

不过视频应该更清晰,我有发布,下面是链接

具体情况-CSDN直播

这个怎么打开监视界面我之前有发过,我后面再重新单独发一次

总结:

while循环中的

break是用于永久的终止循环

continue是跳过本次循环后面的代码,直接去判断部分,进行下一次循环的判断

 3.2 另加:(具体getchar知识点)

再看几个代码

代码1

补充知识点:getchar和putchar

#include<stdio.h>
int main()
{
	int ch = getchar();//getchar():get叫获取,char叫字符,可以获取一个字符
	//就是getchar()能获取一个字符,把获取的字符的ASCII码值放到这个ch里面
	printf("%c\n", ch);//然后我们就能把ch里面放的值以字符的形式打印出来,方法1
	putchar(ch);//getchar叫获取,putchar叫打印,这个跟printf("%c\n", ch)都可以,方法2
	return 0;
}

结果:

getchar获取一个字符,从键盘上获取,就是运行之后输入一个字符
getchar和putchar的头文件就是stdio.h
getchar返回的时候如果读取正常,就返回他读到的字符,但如果遇到文件错误或end-of-file(文件的末尾),就返回EOF(文件结束标志),那他本质上什么呢

-1是个整数,那去接收他返回的时候,最好用个整型来接收,如果用char来接收,char是字符类型,字符类型是1个字节,他是放不下一个-1这样一个整数的,所以这里写了个int,既可以放正常读取的ASCII码值,也可以放这个EOF更合适一些

接下来正文:

#include<stdio.h>
int main()
{
	int ch = 0;
	while ((ch = getchar()) != EOF)  //如果这个(ch = getchar())不等EOF,说明这个getchar读取到了正常的字符
		putchar(ch);
	return 0;
}

结果: 

这个为什么会自动换行,我输入了一个a,其实还敲了一个回车,此时输入缓冲区里面有两个字符,  【a  \n】两个

当getchar()去获取字符的时候,不是直接在键盘上就读了一个字符,中间还有个缓冲区

 当输入a之后,一按回车,这个时候其实就触发了getchar去读,因为我已经把这个放到缓冲区了。
getchar先读一个字符,读到了a,他一次只能读一个字符,一个字符放到ch里面,ch就是a,这个地方a不等与EOF,这个时候就进到了putchar这里,就把a打印,a打印完之后,getchar又读取了一个字符\n,\n是换行,这时候ch就是\n,不等于EOF,这个时候又进到了putchar这里,打印了一个换行,就到下一行来了。

他打印完a之后,这个光标直接就来到了下一行,其实就是因为他打印了一个换行,这个时候打印一个s,这个光标又直接就来到了下一行。(再看具体一点就调试打开监视界面)


停下来就按ctrl+z (就是让get返回一个EOF)

这里的代码适当的修改是可以用来处理缓存区的。

这个有什么用呢,下面举个例子

#include<stdio.h>
int main()
{
	//假设密码是一个字符串
	char password[20] = { 0 };//给20个字符的一个空间
	printf("请输入密码:>");
	scanf("%s", password);//因为这个password是个数组名,本来就是个地址,所以这里没有&
	//
	printf("请确认密码(Y/N):>");
	int ret = getchar();
	if ('Y' == ret)
	{
		printf("Yes\n");
	}
	else
		printf("No\n");
	return 0;
}

 结果:

 解析:

 

 

 但是这个scanf只会拿他该拿的,不会拿这个\n,因为这不是密码,这个时候scanf只是拿走了这个abced,把这个拿走之后放到了password里面,然后接着运行到了getchar,然后这个getchar一看,这缓冲区里面有东西,有个\n,他就拿走了,他看到这个缓冲区里面有东西,他压根没等,直接把\n拿走,拿走之后,他把\n拿走放到 ret 里面去了,因为ret里面是\n,他不等于Y,所以就走了else,打印 No 

那这个时候我就希望这个getchar可以停下来(就是让getchar到这个缓冲区里面去看的时候什么都没有,这个时候就会等待了,就是要想办法把这个缓冲区里面的\n去掉)

#include<stdio.h>
int main()
{
	char password[20] = { 0 };
	printf("请输入密码:>");
	scanf("%s", password);
	getchar();//这个getchar就读取了\n,这个缓冲区里面就没有东西了
	printf("请确认密码(Y/N):>");
	int ret = getchar();
	if ('Y' == ret)
	{
		printf("Yes\n");
	}
	else
		printf("No\n");
	return 0;
}

 结果:

 但这个写法也只是临时凑活一下,下面这样输入就又是错误了

分析:

 

 这个scanf读到空格就不读了,所以scanf读的时候只读了abcdef,然后紧接着过来了getchar(),发现这个缓冲区里面的东西很多,有:[空格]  asdfg  \n ,但他只拿走了这个[空格],,此时缓冲区里面还有:asdfg  \n 。他拿了这个空格之后再一次往下走,那这个getchar发现里面还有这么多,读取了这个asdfg,还是没有等键盘输入,直接就是读取了字符,走了else语句,输出No

所以用getchar();清理缓冲区的时候可能不是一个字符,而是一堆字符

#include<stdio.h>
int main()
{
	char password[20] = { 0 };
	printf("请输入密码:>");
	scanf("%s", password);
	int ch = 0;
	while ((ch = getchar()) != '\n')//这个时候读的字符不是\n,就继续读,注意,读一个缓冲区少一个,读一个,缓冲区少一个
		//直到getchar读的是\n,把\n也拿走了,放到这个ch里面,\n不等于\n为假,
		//说明现在把\n,包括他之前的字符全部清理掉了,此时就可以正常了
	{
		;
	}
	printf("请确认密码(Y/N):>");
	int ret = getchar();
	if ('Y' == ret)
	{
		printf("Yes\n");
	}
	else
		printf("No\n");
	return 0;
}

结果:

当然密码可以有空格 

代码2
#include<stdio.h>
int main()
{
	char ch = '0';
	while ((ch = getchar()) != EOF)
	{
		if (ch < '0' || ch>'9')
			continue;
		putchar(ch);
	}
	//只打印数字字符
	return 0;
}

 结果:

 只打印数字字符

3.3  for

for循环语法

for (表达式1;表达式2;表达式3)
    循环语句;

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

表达式2为条件判断部分,用于判断循环是否终止

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

执行流程

打印1-10

#include<stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 10; i++)//这里循环语句只有一条,不用大括号,如果不止一条,就要大括号
		printf("%d ", i);
	return 0;
}

结果:

 

 遇到break

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

结果:

 

 当 i 等于5时,遇到break,直接终止了循环,循环不再继续

遇到continue

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

结果:

 

 continue跳过本次循环代码continue后面的 printf("%d ", i);到for循环的调整部分,i++,这里

注:break只能结束一层循环,只能结束他所在的那个for循环或while循环

一些for循环的变种:

代码1
#include<stdio.h>
int main()
{
    //for循环的判断部分省略意味着判断会恒成立,导致代码死循环
	for (;;)
	{
		printf("hehe\n");
	}
	//for循环中的初始化部分,判断部分,调整部分是可以省略的,但是不建议初学时省略,容易导致问题
	return 0;  //结果死循环了
}

结果:

建议:不要随便省略

#include<stdio.h>
int main()
{
	for (int i = 0; i < 10; i++)
	{
		printf("hehe\n");
	}
	return 0;
}

 for (int i = 0; i < 10; i++)中这个 int i = 0,C99语法才支持了这种写法,但如果用某个编译器不支持这个C99语法,这串代码是编不过去的。

另,C++中支持这种写法

代码2
#include<stdio.h>
int main()
{
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j< 3; j++)
		{ 
			printf("hehe\n");
		}
	}
	return 0;
}

 结果:

代码3
#include<stdio.h>
int main()
{
	int i = 0;
	int j = 0;
	for (; i < 3; i++)
	{
		for (; j< 3; j++)
		{ 
			printf("hehe\n");
		}
	}
	return 0;
}

 结果:

分析:

因为当第一次执行循环 for (; i < 3; i++) ,此时 i=0 ,进入循环语句也就是下一条循环语句for ( ; j< 3; j++) ,打印出三次 hehe,这条循环语句执行完成,此时 i=0,j=3 ,然后第二次执行这个语句 for ( ; i < 3; i++) 中的 i++ ,得到 i=1,再次判断 i<3 ,进入 for ( ; j< 3; j++) ,但是因为这里没有初始化(即 j=0 ),所以此时 j 还是等于3,与 j<3 判断不符合,无法执行打印 hehe,第三次与第二次一样的原因。

代码4

使用多于一个变量控制循环

#include<stdio.h>
int main()
{
	int x, y;
	for (x = 0, y = 0; x < 2 && y < 5; ++x, y++)
	{
		printf("hehe\n");
	}
	return 0;
}

结果:

 

练习:

请问循环要循环几次

#include<stdio.h>
int main()
{
	int i = 0;
	int k = 0;
	for (i = 0, k = 0; k = 0; i++, k++)
		k++;
	return 0;
}

3.4  do...while

3.4.1  do语句的语法:

do
    循环语句;
while(表达式);

循环语句不止一条时也要加大括号括起来

 特点:

循环至少要执行一次,使用场景有限,不是经常使用

 3.4.2 执行流程

 例子:

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

 结果:

 3.4.3 遇到break

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

结果:

 3.4.4 遇到continue

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

结果:

 continue跳过后面语句 printf("%d ", i); ,还是要来到 while (i <= 10); 判断

把 i++放后面

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

结果:  打印出 1 2 3 4 之后死循环了

 

 因为当 i 到等于 5 时,跳过本次循环后面的代码  printf("%d ", i);  i++;  ,导致后面 i一直没有变化,while判断一直符合,最后死循环。

3.5 练习

写代码:

办法(编程思维)+写代码(按照语法形式去写)

1、计算n的阶乘

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

3、在一个有序数组中查找具体的某个数字n (讲解二分查找法)

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

5、编写代码实现,模拟用户登录情景,并且只能登陆三次。(只允许输入三次密码,如果密码正确则提示登陆成功,如果三次均输入失败,则退出程序)

3.6 goto语句

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

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

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

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

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

goto那就是到哪里去,他有一个跳转的功能,goto语句的执行,会打乱我程序原本有的这个执行流程,容易让代码出现问题。

#include<stdio.h>
int main()
{
again:
	printf("hehe\n");
	printf("haha\n");
	goto again;//跳到前面那个again那里去了,导致hehe和haha一直循环打印
	return 0;
}

结果:

 

goto语句不能跨函数使用 

 就是没有看到again这个符号,不能跨函数跳转

goto语句真正适合的场景如下:

for(...)
    for(...)
    {
        for(...)
        {
            if(disaster)//如果灾难发生
                goto error;
        }
    }
    ...
error:
    if(disaster)
        //处理错误情况

写一个goto语句的代码,再改造成其他方法 

//关机程序
//1、电脑运行起来后,1分钟内关机
//2、如果输入:easy,就取消关机
#include<stdio.h>
#include<string.h>
int main()
{
	system("shutdown -s -t 60"); // -s是关机,-t是设计关机,60是表示60秒之后关机。
	//这个shutdown -s -t 60就是系统命令,system函数执行系统命令。
	// (系统命令就是按win+r输入cmd之后打开的运行框里面输入的指令)
again:
	printf("请注意,你的电脑在60秒内关机,如果输入:easy,就取消关机\n");
	char input[20] = { 0 };
	scanf("%s", input);
	if (strcmp(input, "easy") == 0) //strcmp要加头文件string.h
	{
		system("shutdown -a");// -a 取消关机
	}
	else
	{
		goto again;
	}
	return 0;
}

 提示:别输错关机了!!

#include<stdio.h>
#include<string.h>
int main()
{
	system("shutdown -s -t 60"); 
	while (1)
	{
		printf("请注意,你的电脑在60秒内关机,如果输入:easy,就取消关机\n");
		char input[20] = { 0 };
		scanf("%s", input);
		if (strcmp(input, "easy") == 0)
		{
			system("shutdown -a");
			break;
		}
	}
	return 0;
}

4、练习答案

2.1  1、练习

判断一个数是否为奇数;

#include<stdio.h>
int main()
{
	int num = 0;
	scanf("%d", &num);
	//判断  奇数,除2余1就叫奇数
	if (num % 2 == 1)
		printf("奇数\n");
	else
		printf("不是奇数");
	return 0;
}

2.1  2、练习

输出1-100之间的奇数;

要输出1-100之间的奇数,首先要产生1-100之间的数,再判断这个数是否为奇数,是奇数打印,不是奇数就不打印。

利用while循环的循环变量就可以产生1-100之间的数,然后每产生的循环变量,就判断他是不是奇数。

//要输出1-100之间的奇数,首先要产生1-100之间的数,
//再判断这个数是否为奇数,是奇数打印,不是奇数就不打印
#include<stdio.h>
int main()
{
	//利用while循环的循环变量就可以产生1-100之间的数,然后每产生的循环变量,就判断他是不是奇数
	int i=1;
	while (i <= 100)
	{
		if (i % 2 == 1)
			printf("%d  ", i);
		i++;
	}
	return 0;
}

结果:

 

或者这样:

#include<stdio.h>
int main()
{
	
	int i = 1;
	while (i <= 100)
	{
		printf("%d  ", i);
		i+=2; //此时直接就知道i=1是奇数,所以直接加2也都是奇数,没有用到判断,结果一样
	}
	return 0;
}

2.2  练习

 解析:

#include<stdio.h>
int main()
{
	int n = 1;
	int m = 2;
	switch (n)  
	{
	case 1:m++; //n=1匹配进入,此时m=3,且这条语句后没有加break语句,会接着执行后面的case语句
	case 2:n++;  // 此时n=2,这条也没有break语句,也会接着执行后面的case语句
	case 3:
		switch (n)  //n=2
		{//switch允许嵌套使用
		case 1:n++;
		case 2:m++; n++;//匹配到这条,此时m=4,n=3
			break;//只会中断这个小的嵌套的switch语句
		}//整个case 3没有break语句,接着执行后面的case语句
	case 4: 
		m++; //接着前面的执行,此时m=5
		break;//有break,中断switch语句
	default:
		break;//这条不会执行到,因为执行case 4语句,这条语句有break,直接中断了这个switch语句
	}
	printf("m=%d,n=%d\n", m, n);//最后输出m=5,n=3
	return 0;
}

3.3 练习

零次,因为 for (i = 0, k = 0; k = 0; i++, k++)中的标红字体(;k = 0;),是赋值,不是判断,k 一但赋值为 0 ,0为假,这个表达式(标红字体)为假,就不进入循环了,循环0次。

3.5 练习

1、计算n的阶乘

//计算n的阶乘
//1*2*3*...*n
//要产生1到n个数字,用循环产生,把这些数字累计乘在一个数上
#include<stdio.h>
int main()
{
	int i = 1;
	int n = 0;//n是随便输入的一个值
	int ret = 1; //暂时不考虑溢出的问题
	scanf("%d", &n);
	for (i = 1; i<= n; i++)
	{
		ret = ret * i;
	}
	printf("%d\n", ret);
	return 0;
}

结果:

 

溢出结果:(暂时不考虑溢出问题)

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

#include<stdio.h>
int main()
{
	int n = 1;  // 1 2 3 4。。。10这几个阶乘
	int i = 1;   //用来做阶乘的递增的
	int ret = 1;//接收阶乘的值
	int sum = 0;//将每一个阶乘值相加
	for (n = 1; n <= 10; n++)
	{
		ret = 1;
		for (i = 1; i <= n; i++)//这里n=1,就是求1的阶乘,n等于几就是求几的阶乘
		{
			ret = ret * i;
		}
		sum = sum + ret;
	}
	printf("%d\n", sum);
	return 0;
}

结果: 4037913 

或者这样效率更高

#include<stdio.h>
int main()
{
	int n = 1; 
	int ret = 1;//接收阶乘的计算得到的结果
	int sum = 0;//将每一个阶乘值相加
	for (n = 1; n <= 10; n++)
	{
		ret = ret * n; //等式右边的ret就是上一次阶乘的结果,这里就没有重复计算,
		//没次都把上一次的值利用起来了
		sum = sum + ret;
	}
	printf("%d\n", sum);
	return 0;
}

3、在一个有序数组中查找具体的某个数字n (讲解二分查找法)

#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//找7  在一个有序数组中查找具体的某个数字n
	int k = 7;
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);//用整个数组的大小除以第一个元素大小就是元素个数
	for (i = 0; i < sz; i++)
	{
		if (arr[i] == k)
		{
			printf("找到了,下标是:%d", i);
			break;
		}
	}
	if (i == sz)
	{
		printf("找不到\n");
	}
	return 0;
}

但这个效率是比较慢的,没有利用到这个 有序

用二分查找(折半查找)更快

#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	//找7  在一个有序数组中查找具体的某个数字n
	int k = 7;
	int sz = sizeof(arr) / sizeof(arr[0]);
	int left = 0;
	int right = sz - 1;
	while (left<=right) //当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;
}

这个时间复杂度是 \log_{2} n  。

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

//要打印这个welcome to home!!!
//##################
//w################! 
//we##############!!
//wel############!!!
//......
//welcome to home!!!
#include<stdio.h>
#include<windows.h>
#include<stdlib.h>
int main()
{
	char arr1[] = "welcome to home!!!";//这个数组里面最后还有个\n,所以是19个
	char arr2[] = "##################";
	int left = 0;//第一个元素下标
	int right = strlen(arr1)-1;//求到了这个arr1里面字符串的长度(不包括\n),注,空格也是字符
	//最后一个元素的下标
	//另一种方法:int right=sizeof(arr1)/sizeof(arr1[0])-2;
	//这个sizeof(arr1)/sizeof(arr1[0])算的是元素个数,包含\n在内,所以后面要-2
	while (left <= right)
	{
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		printf("%s \n", arr2);
		Sleep(1000);  //1000毫秒,1秒,这里休息一秒  这里头文件要加windows.h
		//清空屏幕
		system("cls");//system是个库函数,是用来执行系统命令的,
		//这个cls就是系统命令,要包含头文件stdlib.h
		left++;
		right--;
	}
	printf("%s \n", arr2);
	return 0;
}

5、编写代码实现,模拟用户登录情景,并且只能登陆三次。(只允许输入三次密码,如果密码正确则提示登陆成功,如果三次均输入失败,则退出程序)

#include<stdio.h>
#include<string.h>
//比较两个字符串是否相等,不能使用 == ,而应该使用一个库函数:strcmp,头文件是string.h
//这个strcmp函数的返回值如果等于零,就说明这两个字符串相等
int main()
{
	int i = 0;
	char password[] = { 0 };
	//假设密码是字符串abcdef
	for (i = 0; i < 3; i++)
	{
		printf("请输入密码:>");
		scanf("%s", password);//数组名本来就是地址,不需要加&
		if (strcmp(password,"abcdef")==0) //比较两个字符串是否相等,不能使用==,
		//而应该使用一个库函数:strcmp,这个strcmp函数的返回值如果等于零,就说明这两个字符串相等
		{
			printf("登陆成功\n");
			break;
		}
		else
		{
			printf("密码错误\n");
		}
	}
	if (i == 3)
	{
		printf("三次密码均输入错误,退出程序\n");
	}
	return 0;
}

  • 68
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值