一章通关c语言分支语句和循环语句

【前言】本系列(初阶)适用于初学者课前预习或者课后复习资料,包含了大部分基础知识点梳理与代码例方便看官理解,有问题请指出。本人邮箱地址:[email protected]

【概要】

分支语句

if     switch

循环语句

while       for       do while     

goto语句    

目录

1.语句

2.条件判断语句

2.1 if语句

2.2switch语句 

3.循环语句

3.1while循环

3.2for循环

3.3do while循环 

4.循环相关练习

4.1计算n的阶乘

 4.2计算1到10所有数的乘阶和

4.3二分查找

4.4字符移动

4.5 输入密码

4.6实现猜数游戏

5.goto语句


1.语句

 C语言大概有以下五类语句

1.表达式语句。

2.函数调用语句。

3.控制语句。

4.符合语句。

5.空语句。

而后面主要介绍的就是控制语句了。

控制语句用以控制程序的执行流程,用来实现程序的各种结构方式。c语言是一门结构化的程序设计语言,支持顺序结构选择结构循环结构三种结构。其实人生也是这样,在不断向前走,遇到分支踌躇不前,或者待在原地转圈。这些结构由九种控制语句组成。

条件判断语句: if语句,switch语句。

循环执行语句:for语句,do while语句,while语句。

转向语句:break语句,goto语句,continue语句,return语句

2.条件判断语句

人生处处面临选择,选择努力就有可能拿到好offer,但如果选择摆烂就有可能以后去摊煎饼果子了。

一章通关c语言分支语句和循环语句_第1张图片

2.1 if语句

//单分支
	if (表达式)  
		语句;
	//双分支
	if (表达式)  
		语句;
	else
		语句;
	//多分支
	if (表达式) 
		语句;
	else if(表达式)
		语句;
	else
		语句;

 这就是if语句的基本结构。if里面的表达式如果为真,则执行语句,如果为假则跳出if语句所管辖的范围。在c语言中规定0为假非0为真

单分支的运用

int age = 15;
	if (age < 18) {
		printf("未成年");
	}

但是一旦age大于了18就没有显示了,设计并不完善。

双分支

int age = 19;
	if (age < 18) {
		printf("未成年");
	}
	else {
		printf("成年");
	}

若age大于18则会输出成年字样。那么如果我们并不满意太少的age分类呢?

那我们还可以使用多分支的结构。

int age = 77;
	if (age < 18) {
		printf("未成年");
	}
	else if (age >= 18 && age < 30) {
		printf("青年");
	}
	else if (age >= 30 && age < 50) {
		printf("中年");
	}
	else if (age >= 50 && age < 120) {
		printf("老年");
	}
	else
	{
		printf("输入正确数据 ");
	}


以上就是简单的分支语句的使用。并且我们使用了代码块{}来使得程序更加的清晰。我建议每次写分支都加上{},如果不加上{}可能会出现意料之外的小错误,也会对别人看你的代码时产生误解。


		int a = 0;
		int b = 0;
		if (a == 1)
			if (b == 2)
				printf("1");
		else
				printf("2");
	

 第一眼告诉你的答案是多少呢,是2吗?

答案是什么都没有,如果你将这段代码放在vs上,会发现VS自动帮你调整了else的位置,放到了第二个if的正下方,这就说明了else的匹配是与其最近的if匹配的。这就从侧面说明了一个好的代码风格是非常重要的,在使用if语句时使用适当的{}可以让你的代码更加清晰,风格更加明了,毕竟代码不只是写给自己看的,还要给别人看。所以笔者不建议使用dev++这种老旧的编译器来进行代码书写,对初学者的代码风格养成不好。

一章通关c语言分支语句和循环语句_第2张图片

在看一个因为代码风格不好容易引起误解的例子。

if (true) {
		return 1;
	}
	return 2;

 如果true为真,则会返回1,同时也不会返回2,当返回1后这串代码执行就已经完成。但总会给人造成误解,认为就算true为真,在返回了1后还会返回2这个值,这是语法不允许的。

建议更改为

if (true) {
		return 1;
	}
	else {
		return 2;
	}

2.2switch语句 

比如我们想完成一个这样的代码功能,当输入1,输出星期一,输入2,输出星期二,直到输入7,输出星期天。

这样的程序实现如果还是使用多分支的语法结构,会显得非常复杂,且不利于查看。

这个时候就要用到switch语句了。

switch(整型表达式)
{
  语句项;
}

注意只能是整型表达式,不可以是其他。 

里面的语句项则是一些case语句。

case 整型常量表达式;
     语句;

并且在switch语句中,case决定入口break决定出口。 所以只有搭配了break才可以实现真正的分支。

int day = 0;
	scanf("%d", &day);
	switch (day) {
	case 1:
		printf("monday\n");
		break;
	case 2:
		printf("tuesday\n");
		break;
	case 3:
		printf("wednesday\n");
		break;
	case 4:
		printf("thursday\n");
		break;
	case 5:
		printf("friday\n");
		break;
	case 6:
		printf("saturday\n");
		break;
	case 7:
		printf("sunday\n");
		break;

	}

这就是一个简单的switch语句。当day等于1,2,3..... 时,走向不同的case入口。 注意,在进入case入口后,程序会一直执行,直到遇到出口break

比如如果case 1后面没有break,当day等于1,会输出monday和tuesday,在case 2后面遇到break才会终止并跳出。

如果输入了不符合1到7的数呢?则可以利用default。

default:
		printf("error\n");
		break;

 当我们不需要输出如此清晰,只需要weekday与weekend的区别时,就可以利用break的出口机制,简化代码。

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的效果就是将语句列表划分为不同的分支部分。 

来看一道练习加深你对switch语句的理解。

int n = 1;
int m = 2;
switch (n) {
case 1:
	m++;
case 2:
	n++;
case 3:
	switch (n) {
	case 1:
		n++;
	case 2:
		m++;
		n++;
		break;
	}
case 4:
	m++;
	break;
default:
	break;
}
printf("m=%d,n=%d", m, n);

输出结果是m=5,n=3

原理如下:

输入m=2,n=1后,进入了第一个switch的case 1语句,此时m++变成了3,同时因为没有break,所以程序继续向下走,使n++,变成 2,也是没有break,所以走向了case 3的switch嵌套,此时n-2,所以进入case 2语句,m与n分别++,变成了4,3,此时遇到break,跳出了嵌套的switch,继续进行第一个switch,进入case 4,使m++,变成5,此时遇到break,程序终止,跳出第一个switch语句

3.循环语句

3.1while循环

当我们使用if时,会发现其只能执行一次,但是生活中会有很多实际的例子需要我们去多次的实现

那就要用到while循环了。

while(表达式)
  循环语句;

当表达式为真,就会进入循环,执行循环语句。

现在来看一个打印1-10的例子。

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

代码的实现非常简单,i小于等于10时进入循环,打印后加1,再回到while进行判断是否进行下一次循环。 

在while语句中也会遇到break和continue。

先上结论

break:在循环中遇到break,就停止后期的所有循环,直接将循环进行永久终止

 代码示例

int main() {

	int i = 1;
	while (i <= 10) {
		if (i == 5) {
			break;
		}
		printf("%d ", i);
		i++;
	}
}

输出为1 2 3 4

当i等于5时,进入了循环,同时进入了if的判断,读到了break,终止了整个循环。后面也就不再执行了。

continue

continue用于终止本次循环,直接跳转到下一次while循环判断部分

代码示例

int main() {

	int i = 0;
	while (i < 10)
	{
		i++;
		if (i == 5)
		{
			continue;
		}
		printf("%d ", i);
		

	}
	return 0;
}

 运行后结果为1 2 3 4 6 7 8  9 10

唯独缺少了5,因为为5时进入了if的判断,执行了continue,终止本次循环,直接回到了while再次进行判断。

代码示例

int main() {
	int ch=0;
	while ((ch = getchar()) != EOF) {
		putchar(ch);
	}
	return 0;
}

这里简单介绍一下getchar。

getchar的作用是从键盘中读入一个字符,也就是从输入缓冲区中拿取,每次只能拿取一个字符

当我们输入比如A后,要按下回车,这个时候回车(\n)也被放入了输入缓冲区,当getchar读走了A时,会顺着循环继续读取缓冲区中剩下的回车。所以实际上循环进行了两次,分别通过putchar打出了A和\n。所以我们发现下标在输出的A的下一行。

 再来看一个代码示例熟悉getchar的基础用法。

int main() {
	char charr[20] = { 0 };
	char ch;
	scanf("%s", charr);//向字符数组中输入一串字符
	printf("确认字符串输入是否正确(y)?");
	ch = getchar();
	if (ch == 'y') {
		printf("正确");
	}
	else
	{
		printf("错误");
	}


}

在运行时会发现在输入一串字符串后会立即打印出错误的字样。根本没有给我们输入y的机会。

和上面是同理,按下的回车被下面的getchar接收了。

所以我们只需要在增添一个getchar消化掉回车就好了。在scanf后面加一个getchar即可。

int main() {
	char charr[20] = { 0 };
	char ch;
	scanf("%s", charr);//向字符数组中输入一串字符
	getchar();
	printf("确认字符串输入是否正确(y)?");
	ch = getchar();
	if (ch == 'y') {
		printf("正确");
	}
	else
	{
		printf("错误");
	}


}

在了解一下scanf的机制,scanf函数读到空格和回车都不会再继续读取。

所以如果我们打出的字符串是类似于dwda dw12这样的字符串,上面的代码又需要进一步在getchar上下功夫。

while (getchar() != '\n') {
		;
	}

 这样只能保证对字符串正确与否的判断正常进行,但是输入的字符串从空格后就不会再被读取了。所以我们只能得到dwda。

3.2for循环

for语法

for(exp1 ;exp2; exp3)
 循环语句;

exp1用于初始化循环变量

exp2用于判断循环终止

exp3用于调整循环条件

代码示例

int main() {
	int i = 0;
	for (i = 1; i <= 10; i++) {
		printf("%d ", i);
	}
	return 0;

}

i=1为初始化的循环变量,i<=10为判断循环是否终止的条件,i++为循环条件的调整。

还记得i++的用法吗?先用后加,所以进入循环的i是1,第一次循环完成后i在自增为2

和while循环相比较,使得while循环的三个条件分隔太远,所以像for循环这样的风格更好。

在for循环中也可以出现break和continue。其意义与上面讲的while并无差别。

通过代码示例来熟悉下用法吧。

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

}

打印结果仍然是1 2 3 4,在i=5时执行break直接中断整个for循环。

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

}

打印结果为1 2 3 4 6 7  8 9 10

与while循环结果一样。

同时也存在一些for循环的变种写法,需要大家了解。

for (;;) {
		printf("1");
	}

死循环打印1

int i = 0;
	int j = 0;
	for(i=0;i<3;i++)
	{
		for (j = 0; j < 3; j++)
		{
			printf("1 ");
		}
	}

 嵌套循环,打印了9个1,i=0时执行了三次j从0到2的打印,i也从0到2,所以是九次。

int i = 0;
	int j = 0;
	for(;i<3;i++)
	{
		for (; j < 3; j++)
		{
			printf("1 ");
		}
	}

 省略初始化的嵌套循环。这样只能打印3次。开始时,i为0,小于3,可以进入循环,同理j=0,进入嵌套循环,打印1,同时j自增,直到为3,跳出本次嵌套循环,回到i的循环。i此时为2,但往下进行时j已经等于3了无法进行嵌套的循环,所以跳过再次进入i的循环直到结束。

其实本质上就是因为j没有初始化,导致其无法在第二次i的循环中重置为1 

3.3do while循环 

语法结构

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

其实do while和while循环也无太大差别,但是do while循环至少会执行一次

 也就是执行一次,再去判断循环是否继续。

而while循环是先判断再执行,此外二者基本无太大差别了。

代码示例

int i = 1;
	do
	{
		printf("%d ", i);
		i++;
	} while (i <= 10);

打印结果为1 2 3 4 5 6 7 8 9 10

do while循环中也有break和continue。

break

int i = 1;
	do
	{
		if(i==5)
		{
			break;
		}
		printf("%d ", i);
		i++;
	} while (i <= 10);

打印结果为1 2 3 4

continue

int i = 1;
	do
	{
		i++;
		if(i==5)
		{
			continue;
		}
		printf("%d ", i);
		
	} while (i <= 10);

打印结果为1 2 3 4 6 7 8 9 10,结果中没有5

如果i++的位置仍然放在上一个代码原位置,会在一些编译器造成死循环。

4.循环相关练习

4.1计算n的阶乘

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

 4.2计算1到10所有数的乘阶和

int sum = 0;
	for (int i = 1; i <= 10; i++)
	{
		int ret = 1;
		for (int j = 1; j <= i; j++)
		{
			ret = ret * j;
		}
		sum += ret;
	}

	printf("%d", sum);

4.3二分查找

题目示例:在一个有序数组中寻找某个数字n

二分查找必须要求其具备某种大小顺序,否则无法进行。

比如现在有一个数组包含了1-10共10个数字。我们需要查找其中是否有7这个数字。

二分查找的思想很简单,就是每次砍掉一半,所以二分查找的效率很高,比如你需要在一个上亿的有序数组里查找,运用二分查找可以在开始就直接砍掉一半,并循环反复。

我们将数组第一位的下标定为left,最后一位的下标定为right

再将需要查找的数字定为key

再定义一个mid为0(下一步会用)

那么此部分代码为

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int right = 9;
	int left = 0;
	int key = 7;
    int mid=0;

接下来让mid成为数组中间那个数字的下标。

二分查找核心思想

因为是有序数组,即将key与arr[mid]作比较,如果key比他,则说明key在以mid为分隔符下半段里。若key比他,则说明key在上半段里。若相等那就直接找到了。

若在下半段,则将left指向mid+1的位置,若在上半段,则将right指向mid-1的位置。

然后再进行key与新的mid(新right或者新left与旧的相加再除以2)进行比较,如此循环。

笔者文笔略差,看官可以自己画一个数组来按照步骤进行操作方便理解。

查找终止的条件无非就是找到了或者left与right交叉

所以完整代码如下

int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int right = 9;
	int left = 0;
	int key = 7;
	int mid = 0;
	int flag=0;
	while (left <= right)
	{
		mid = (right + left) / 2;
		if (arr[mid] > key)
		{
			right = mid - 1;
		}
		else if(arr[mid]

4.4字符移动

编写一段代码使多字符从两端滑动,同时向中间汇聚。

#include
#include
int main()
{
	char arr1[] = "this is amazing!";
	char arr2[] = "****************";//创建两个数组,使其具有同样长度。
	int left=0;
	int right = strlen(arr1) - 1; //同二分查找相同,使用数组下标来控制字符串的改动。
	printf("%s", arr2);
	while (left<=right) //循环条件也同二分查找,当两下标移动到相同位置则停止打印。
	{
		
		arr2[left] = arr1[left];
		arr2[right] = arr1[right];
		left++;
		right--;
		printf("%s", arr2);
		Sleep(1000); //使用sleep函数使打印更具层次感
		system("cls");  //执行清理屏幕的指令
	}
return 0;
}

4.5 输入密码

条件:只有三次输入机会,错误则令程序停止

#include
int main()
{
	char password[20] = { 0 };
	int i = 0;
	int j = 0;
	for (i = 0; i < 3; i++)
	{
		printf("input the password\n");
		scanf("%s", password);//数组名已经是地址,无需取址符&
		if ((strcmp(password, "123456")) == 0)
		{
			printf("right!\n");
				break;
		}
		else
		{
			printf("try it again\n");
		}
	}
	if (i == 3)
		printf("exit\n");
	return 0;
}

4.6实现猜数游戏

游戏功能:随机提供一个1-100内的数字,每次猜测后会给出大了还是小了,直到猜中为止。

本题对循环并无太大要求,而是随机数的给出。

c语言中内置的库函数可以实现随机数,rand

int a;
	for (int i = 0; i < 3; i++)
	{
		a = rand();
		printf("%d\n", a);
	}

但是当你使用rand去创造数字,会发现每一次程序重新运行创建的数字都是一样的。

这样显然背离了游戏的初衷。

所以在使用rand函数时还需要使用一个前置函数srand

srand用于设置随机数生成器。

如果置srand(0),会使每一次循环所得到的a的值都是同一个。

所以想要得到一个随机数,我们需要使srand里的数也是随机的,用随机来创造随机。

各位看官可听说过时间戳吗?srand就可以利用时间戳来实现随机给出数字。

时间是随时变化的,刚好可以用来置srand的值。

	srand((unsigned)time(NULL));

 在c语言中,time函数返回时间戳。至于为什么要用unsigned ,感兴趣的看官可以自行百度。

不加会报错哦。

到这里一个随机数的给出器就基本完成了。接下来就是完善整个程序。

#include
#include
void menu()
{
	printf("*****1 play game*****\n");
	printf("*****0 game  over*****\n");
}
void game()
{
	int num = rand() % 100 + 1;//任何数除以100余的数都在1-99之间,再加1,即得1-100
	int b;
	
	while (1)
	{
		printf("input your number\n");
		scanf("%d", &b);
		if (b > num)
		{
			printf("your num is bigger\n");
		}
		else if (b < num)
		{
			printf("your num is smaller\n");
		}
		else
		{
			printf("right!\n");
			break;
		}
	}
}
int main()
{
	int a = 0;
	srand((unsigned)time(NULL));
	do
	{
		menu();
		printf("choose\n");
		scanf("%d", &a);
		switch (a)
		{
		case 1:
			game();
			break;
		case 0:
			break;
		default:
			printf("error,try it again");
		}
	} while (a);
	return 0;
}

5.goto语句

 goto语句在实际操作中使用非常少。最常见的用法也只是终止程序在某些深入嵌套得到结构处理过程。‘也就是跳出多层循环。因为break只能跳出一层最近的循环,而goto通过恰当设置可以跳出多层。

goto 也就是去往哪里,比如goto a,程序就会跳至a:这个地方执行。

代码示例:

不按要求输入就关机。

#include

int main()
{

	char a[20] = "";
	system("shutdown - s - t 60"); //关机指令为shutdown -s,-t则是设置在多少秒后
again:
	printf("即将关机,请输入123456停止关机程序\n");
	scanf("%s", a);
	if ((strcmp(a, "123456")) == 0)
	{
		system("shutdown -a"); //取消关机指令
	}
	else
	{
		goto again;
	}

	return 0;
}

以上就是c语言常用的几种语句啦。写文不易,希望看官能留下你的赞。给俺更多动力。

一章通关c语言分支语句和循环语句_第3张图片

你可能感兴趣的:(c语言高分指南,c语言)