- 前言(C与哲学)
- 一、分支语句
- 1.语法结构
- (1)```if...else```语句
- (2)```switch...case```语句
- 2.示例
- (1)示例1
- (2)示例2
- 二、循环语句
- 1.应用情景
- 2.语法结构
- (1)```while```语句
- (2)```for```语句
- (3)```do...while```语句
- (4)```goto```语句
- 3.两个关键字
- (1)break
- (2)continue
- 4.示例——二分查找
- 结语
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
之外 的情况判断进入,三者之间属于分支结构。
switch...case
语句
switch(choose)
{
case 1:
case 2:
case 3:
...
case n:
default:
}
我们还是结合下面这张图来理解。
1)choose
必须是:整型变量 或者 常量 。但是choose
是常量这个语句就失去意义了,因为case n
根本不可能被进入。
2)当choose
的值为多少时,就会进入对应的case
语句中。比如:choose = 1
,这时就会进入case 1
。
3)当所有的case
都没办法进入的时候,switch
语句就会进入default
。我们可以把default
理解为switch
语句对所有case
的补集。
4)值得思考的是:假设进入case 1
之后,还会不会进入case 2
?这要看情况。如果不想:就必须在case 1
的最后面加上break
。(下方(2)示例2 已举了详细的例子,读者可自行阅读。)
5)其实,switch...case
语句的case
后方的数字其实是不便于阅读的。在我们后面:学到枚举(一种自定义类型)之后,我们会对switch...case
语句进行优化!
年龄与建议饮酒情况
#include
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;
}
细心的读者可能发现了上面这段代码中,笔者故意放置的错误。当我们需要在if
与else
中写多条语句的时候,我们要为语句加上一个大括号。所以,以上代码片段局部应改成——
else
{
printf("老寿星\n");
printf("少量饮酒\n");
}
(2)示例2
#include
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
时,出来了以下的结果。
顾名思义,循环就是重复做某件事情,如下图所示,下方也附上了代码示例。
// 示例代码
#include
int main()
{
int a = 0;
a = 1;
while (a != 100)
{
printf("...\n");
a++;
}
return 0;
}
读者看到上面的while
这个语法结构或许不太能理解,下面笔者就给大家介绍while
这个语法结构。
前三种循环其实执行逻辑是大同小异的,只是语法结构不一样,在我们日常编写程序中,我们常用for
循环,原因详见for
循环介绍部分。
while
语句
while(condition)
{
...
about condition;
}
我们借用上面这个 罚抄 的场景给大家介绍。场景中老师所要求的罚抄100遍
,对于我们来说,我们要做的就是从第1次,抄到第100次,而这其实就已经暗示了进循环的condition
和控制条件出循环的about condition
。
用大白话解释:condition
就是抄完一百遍没有?没抄完就进入循环继续抄。about condition
则是我又抄完一遍了。about condition
的目的就是:不断靠近 不满足条件 的情况。
用示例代码解释:笔者利用a
来控制循环的进出。(用int类型
的变量来控制是非常常见的事,大家可以记住这个套路。)condition
为a != 100
意思就是:当a
没达到100的时候,就进入循环。(注意这里的用词 没达到 )about condition
为a++
意思就是:a
自加。最后a
不断地自加,达到a == 100
的时候,这时候就不满足条件,就会退出循环。
笔者在这里强调:about condition
是必须要有的,否则程序执行到此处就会死循环。
for
语句
for( initalization ; condition; about condition)
{
...;
}
相关执行逻辑,笔者不再赘述,笔者将示例场景用for
循环写个示例供各位参考,相信各位能够理解。
#include
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
部分,如果我们想控制多个条件,就必须使用&&
或者||
这两个 *** 作符。
do...while
语句
do
{
...
about condition;
}while(condition);
do...while
最特别的就是,无论情况如何函数体总是会先执行一遍。
#include
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
就是 标记跳转的标号,读者也可以更换自己喜欢的标号。
其意思就是:跳出本层循环。
#include
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
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).
其意思就是:直接进入调整部分,再判断是否进入循环。
#include
int main()
{
int i = 0;
for (i = 1; i <= 100; i++)
{
printf("..\n");
continue;
printf(".");
}
return 0;
}
其效果如上图所示。
在 罚抄 的场景中,我们本来应该抄一大段话,但是我们只抄了原本的 2/3 。因此,我们可以说continue
的作用:就像偷懒。
#include
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语言不愧为最经典的编程语言,这两大类语句实在是有非常多值得品味的地方,希望各位读者有所收获,欢迎各位读者点赞支持,给更多的伙伴看见这篇文章。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)