初识C语言【2】——分支、循环语句

前言(C与哲学)

C语言的前辈们设计了两大类语句:分支语句和循环语句

从一个更高的角度看,这两种语句非常本质,它们支撑起了一个程序的大逻辑大框架。

对于 已有基础 或者 是已熟练掌握编程 的读者来说,这两种语句不免显得平凡,但笔者却觉得这两种语句充满哲学气息,它其实象征着我们生活的两种状态:一种(分支语句)是在岔路口前选择前进道路,另一种(循环语句)是在不断重复的练习中获得成长

接下来,笔者正式向各位介绍这两大类语句。

一、分支语句

1.语法结构

(1)if...else语句

if(condition 1)
{
   .......
}
else
{
   ......
}

当我们来到分支处时,就相当于我们遇到了 if...else 语句。
condition 1达成,我们就会进入if语句的作用域中,否则就进入else 的作用域。 其中,当作用域只有一条语句的时候,可以不用写大括号,只要多于一条,就必须要写{ }

让我们结合下面这个例子去理解。
在这里插入图片描述
如图:condition 1就是:吃饭睡觉打豆豆,当你吃饭睡觉打豆豆,你就会进入到if的作用域中,也就是成为爽文男主
如果你输入的条件是勤练屠龙技,你跟condition 1吃饭睡觉打豆豆的条件不匹配,就会进入else的作用域,成为屠龙工具人
也就是:决定进入哪一个作用域,看的是——是否符合条件!

阅读至此,相信各位读者已经明白了。但是,我们不一定只会遇到只有两个分支的情况呀,这时候应该怎么办呢?其实很简单,有两种方法。不过两种方法本质上其实是一种方法。

// 法一:嵌套
if (condition 1)
{
   .......
}
else
{
   if (condition 2)
   {
   	.......
   }
   else
   {
   	......
   }
}
// 法二:分离嵌套
if(condition 1)
{
   .......
}
else if(condition 2)
{
   ......
}
else
{
   ......
}

在这里插入图片描述
笔者在这里不再多赘述,请各位读者结合上面这张图自行理解。

值得注意的是,许多读者或许会想用 if(){ } if(){ } if(){ }来替代 if(){ } elseif() { } else{ },这是非常不可取的,下面举一个例子来说说明两者不存在替代性。

1) if(){ } if(){ } if(){ }
在这里插入图片描述
这属于逐条判断,每一个单独的if都会进行判断然后进入,三个if属于顺序结构

2) if(){ } elseif() { } else{ }
在这里插入图片描述
而这里的else if()会是 前面if之外 的情况判断进入,三者之间属于分支结构

(2)switch...case语句

switch(choose)
{
case 1:

case 2:

case 3:

...

case n:

default:

}

我们还是结合下面这张图来理解。
在这里插入图片描述
1)choose必须是:整型表达式(整型变量 或者 整型常量) 。但是choose是常量这个语句就失去意义了,因为case n根本不可能被进入。

2)当choose的值为多少时,就会进入对应的case语句中。比如:choose = 1,这时就会进入case 1case后的表达式只能是整形常量表达式

3)当所有的case都没办法进入的时候,switch语句就会进入default。我们可以default理解为switch语句对所有case的补集。

4)switct语句中的default子句case表达式不要求顺序。没有规定case必须在default之前,可以放在任意位置。但是case最好放在default之前,而建议把default放在最后。

5)值得思考的是:假设进入case 1之后,还会不会进入case 2?这要看情况。如果不想:就必须在case 1最后面加上break。(下方(2)示例2 已举了详细的例子,读者可自行阅读。)

6)其实,switch...case语句的case 后方的数字其实是不便于阅读的。在我们后面:学到枚举(一种自定义类型,枚举类型可以看成特殊的常量)之后,我们会对switch...case语句进行优化!

2.示例

(1)示例1

年龄与建议饮酒情况

#include<stdio.h>
int main()
{
	int age = 0;
	scanf("%d", &age);
	if (age < 18)
	{
		printf("少年\n");
		printf("不能喝酒\n");
	}
	else if (age >= 18 && age < 30)
	{
		printf("青年\n");
		printf("少量饮酒\n");
	}
	else if (age >= 30 && age < 45)
	{
		printf("中年\n");
		printf("适量饮酒\n");
	}
	else if (age >= 45 && age < 60)
	{
		printf("壮年\n");
		printf("适量饮酒\n");
	}
	else
	    printf("老寿星\n");
		printf("少量饮酒\n");
	return 0;
}

细心的读者可能发现了上面这段代码中,笔者故意放置的错误。当我们需要在ifelse中写多条语句的时候,我们要为语句加上一个大括号。所以,以上代码片段局部应改成——

else
{
    printf("老寿星\n");
    printf("少量饮酒\n");
}

(2)示例2

#include<stdio.h>
int main()
{
	int day = 0;
	scanf("%d", &day);
	// switch 后面必须是 整型表达式
	switch (day)
	{
	// case 后面必须是 整型常变量
	case 1:
		printf("星期1\n");
		break;
	case 2:
		printf("星期2\n");
	case 3:
		printf("星期3\n");
		break;
	case 4:
		printf("星期4\n");
		break;
	default:
		printf("输入错误,请重新输入!\n");
		break;
	}
	return 0;
}

同样的,笔者在上方代码中也埋下一个错误。笔者故意删去case 2语句中的break;。所以,当笔者输入2时,出来了以下的结果。
在这里插入图片描述

二、循环语句

1.应用情景

顾名思义,循环就是重复做某件事情,如下图所示,下方也附上了代码示例。
在这里插入图片描述

// 示例代码
#include<stdio.h>
int main()
{
	int a = 0;
	a = 1;
	while (a != 100)
	{
		printf("...\n");
		a++;
	}
	return 0;
}

读者看到上面的while这个语法结构或许不太能理解,下面笔者就给大家介绍while这个语法结构。

2.语法结构

前三种循环其实执行逻辑是大同小异的,只是语法结构不一样,在我们日常编写程序中,我们常用for循环,原因详见for循环介绍部分。

(1)while语句

while(condition)
{
    ...
    about condition;
}

我们借用上面这个 罚抄 的场景给大家介绍。场景中老师所要求的罚抄100遍,对于我们来说,我们要做的就是从第1次,抄到第100次,而这其实就已经暗示了进循环condition控制条件出循环about condition

用大白话解释:condition就是抄完一百遍没有?没抄完就进入循环继续抄about condition则是我又抄完一遍了about condition的目的就是:不断靠近 不满足条件 的情况

用示例代码解释:笔者利用a来控制循环的进出。(用int类型的变量来控制是非常常见的事,大家可以记住这个套路。)conditiona != 100意思就是:当a没达到100的时候,就进入循环。(注意这里的用词 没达到 )about conditiona++意思就是:a自加。最后a不断地自加,达到a == 100的时候,这时候就不满足条件,就会退出循环

笔者在这里强调:about condition是必须要有的,否则程序执行到此处就会死循环

(2)for语句

for( initalization ; condition; about condition)
{
    ...;
}

相关执行逻辑,笔者不再赘述,笔者将示例场景用for循环写个示例供各位参考,相信各位能够理解。

#include<stdio.h>
int main()
{
	int a = 0;
	for (a = 1; a <= 100; a++)
	{
		printf("...\n");
	}
	return 0;
}

这里需要稍作解释的是initalization,我们在while循环貌似没有看见这个初始化。但其实不是,while循环的初始化不做为语法结构的一部分,如果各位读者想初始化,可以在定义a的时候初始化,形如:int a = 50;也可以单独一行初始化,形如:a = 50;

for循环之所以更受大家欢迎,就是因为for循环将:“initialization” “condition” “about condition”放在一起,在编写代码过程中,更方便我们比较三者,更加人性化。(这里其实没有夸大的成分,因为三个表达式都可以做很精细的变化(如下图所示),这些变化直接会就影响一个程序的结果。对此,我们也不需要特别注意,只需要抓住这三个表达式的含义,其内在本质我们慢慢体会。)
在这里插入图片描述
在这里插入图片描述

关于for循环,我们其实能在三个表达式里放上多个条件。比如:在initalization部分可以写出(a = 0, b = 0;about condition部分写成a++, b++)就可以同时初始化多个值,本质上跟逗号操作符的特性有关。但是,对于condition部分,如果我们想控制多个条件,就必须使用&&或者||这两个操作符。

(3)do...while语句

do
{
    ...
    about condition;
}while(condition);

do...while最特别的就是,无论情况如何函数体总是会先执行一遍

#include<stdio.h>
int main()
{
	int a = 0;
	a = 1;
	do
	{
		printf("...\n");
		a++;
	} while (a != 100);
	return 0;
}

(4)goto语句

C语言中提供了可以随意滥用的 goto语句和标记跳转的标号goto语句最常见的用法就是终止程序在某些深度嵌套的结构的处理过
程。

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

此处的error就是 标记跳转的标号,读者也可以更换自己喜欢的标号。

3.两个关键字

(1)break

其意思就是:跳出本层循环。

#include<stdio.h>
int main()
{
	int i = 0;
	for (i = 1; i <= 100; i++)
	{
		printf("...\n");
		if (i == 50)
		{
			printf("不抄了,回家吃饭!\n");
			break;
		}
	}
	return 0;
}

在 罚抄 的场景中,break的作用就是在抄完第50遍的时候就不抄了,后面 50次 也不管了,就像斩断后面的部分。(如果printf("...\n");放在if语句的后面,第50遍也不会抄。)

需要特别解释的是本层这个词,因为在实际编码的过程中,我们会用到双层循环,甚至的三层、四层循环。如果在最内层循环处使用break,那只会跳出最内层的循环。

#include<stdio.h>
int main()
{
	int i = 0;
	int count = 0;
	for (i = 1; i <= 100; i++)
	{
		int j = 0;
		for (j = 1; j <= 100; j++)
		{
			printf("...\n");
			count++;
			if (50 == j)
			{
				printf("不抄了,回家吃饭!\n");
				break;
			}
		}
	}
	printf("%d\n", count);
	return 0;
}

在这里插入图片描述
笔者用了count来计算了抄写总次数。在j层循环中,每抄完第50次,就会跳出本层循环,所以总数就是内层循环 * 外层循环(50 * 100 = 5000).

(2)continue

其意思就是:直接进入调整部分,再判断是否进入循环。

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

在这里插入图片描述
其效果如上图所示。

在 罚抄 的场景中,我们本来应该抄一大段话,但是我们只抄了原本的 2/3 。因此,我们可以说continue的作用:就像偷懒

4.示例——二分查找

#include<stdio.h>
int main()
{
    // 这是一个有序数组。
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int left = 0;
	int right = sizeof(arr) / sizeof(arr[0]) - 1;
	int key = 7;
	int mid = 0;
	while (left <= right)
	{
		mid = (left + right) / 2;
		if (arr[mid] > key)
		{
			right = mid - 1;
		}
		else if (arr[mid] < key)
		{
			left = mid + 1;
		}
		else
			break;
	}
	if (left <= right)
		printf("找到了,下标是%d\n", mid);
	else
		printf("找不到\n");
}

结语

C语言不愧为最经典的编程语言,这两大类语句实在是有非常多值得品味的地方,希望各位读者有所收获,欢迎各位读者点赞支持,给更多的伙伴看见这篇文章。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值