分支语句
c语言是结构化的程序设计语言
c语言有三种结构
- 顺序结构
- 选择结构 if switch 分支语句
- 循环结构 while for do while 循环语句
什么是语句?
c语言中由一个分号隔开的就是一条语句。
例如:
printf(“hehe”);
1 + 1;
正如我写的c语言基础概况一样,分支语句简单说就是选择,如果你坚持写代码你就有好工作,如果天天玩,以后就找不到工作。
当然,选择是很多的,你也可以设置更多的选择来判断最后的答案。
那么if语句是如何实现分支的呢?
语法结构:
if(表达式)
语句;
if(表达式)
语句1;
else
语句2;
//多分支情况
if(表达式)
语句1;
else if
语句2;
else
语句3;
语句执行的条件是表达式为真,如果表达式为假,则不被执行。
int main()
{
int age = 20;
if (age > 18)
{
printf("成年");
}
return 0;
}
这个代码打印成年,为了更加完善代码,我们添加了未成年
int main()
{
int age = 10;
if (age > 18)
{
printf("成年\n");
}
else
printf("未成年\n");
return 0;
}
这就是两种分支的效果,不是这个就是那个。他里面会选择一个代码块进行打印输出。这就是if else的形式。
接下来讨论的是多分支用的if() else if() else()
int main()
{
int age = 10;
if (age < 18)
printf("青少年\n");
else if (age < 30)
printf("青年");
else if (age < 50)
printf("中年");
else
printf("老年");
return 0;
}
但是千万不能这样写
int main()
{
int age = 12;
if (18 <= age < 30)
printf("青年");
return 0;
}
看代码就能就知道十二岁绝对不处于青年状态下,但是我们来看打印结果。
可以看到结果产生了出乎意料的情况,十二岁不属于我规定的青年范围却打印了青年,这是为什么呢?
原因是:18 <= 12 结果为假也就是0,然后0 < 30 条件成立打印青年。
这个代码是绝对错误的千万别这样写。
至于if语句需不需要大括号这件事情,让我们来看看代码。
int main()
{
int age = 10;
if (age > 18)
printf("成年\n");
printf("已经长大了\n");
return 0;
}
我写这个代码主要是想不输出任何的东西但打印的结果却不一样。
所以为了避免出现这样的情况我们会用大括号把我们想要表达的代码放在里面,这样就可以避免这种错误的产生。但是如果我们只要控制一条语句的话,这个大括号不加也是可以的。
加上大括号的代码阅读效果会更好,可以很明确代码的思路,不产生歧义。
在c语言中如何表示真假?
0表示假,非0表示真。
悬空else
请大家看看这个代码,你觉得打印的答案是什么呢?
int main()
{
int a = 0;
int b = 0;
if (a == 1)
if (b == 2)
printf("hehe\n");
else
printf("haha\n");
return 0;
}
答案是:
不打印
原理是:else是离它最近的if匹配。所以在if(a = 1)的时候这个语句就不成立了,所以直接就return 0 了,也就没打印出来东西。
所以代码风格非常的重要。
修正:
int main()
{
int a = 0;
int b = 0;
if (a == 1)
{
if (b == 2)
printf("hehe\n");
else
printf("haha\n");
}
return 0;
}
这样看 逻辑更加的清晰。
同样的也可以看这些代码,可以看出有空格的代码更加美观一些,还是得强调代码的风格非常的重要。
int main()
{
int a = 10;
int a=10;
return 0;
}
int main()
{
Add(10, 20);
char first_name[20];
char FirstName[20];
return 0;
}
if书写形式的对比
这个代码的意思是if如果成立就返回x,如果不是就返回y呢?
代码1
int main()
{
if (condition)
{
return x;
}
return y;
}
代码二
int main()
{
if (condition)
{
return x;
}
else
{
return y;
}
}
这两个代码的对比,代码一的迷惑性很强,但是代码2却可以很明显的理解它的意思。但这两个的代码的意思完全一摸一样。因为return之后就结束了不会再次return下一句的语句。
再来看看这个详细代码,我们就可以更加的了解return是如何操作的。
int test()
{
if (1)
{
printf("hehe\n");
return 3;
}
printf("haha\n");
return -3;
}
int main()
{
int ret = test();
return 0;
}
我们打开监视器看看。发现ret 储存的值就是3.
好,我相信你已经掌握了以上两个代码,接下来我们来看代码3和代码4的对比;
先声明这两个代码都是正确的,在你看来哪种更好一些呢?
代码3
int main()
{
int num = 1;
if (num == 5)
{
printf("hehe\n");
}
return 0;
}
int main()
{
int num = 1;
if (5 == num)
{
printf("hehe\n");
}
return 0;
}
答案是代码四更好一些。
为什么说代码四更好一些?我举个代码例子。
int main()
{
int num = 3;
if (num = 5)
{
printf("hehe\n");
}
return 0;
}
你有看出什么错误了吗?是的,可以发现的是少了一个=,要知道的是=可是赋值,导致的结果就是num = 5 为真会打印hehe。
因为我们深受数学的影响会不由自主的只写一个=,但是编译器却不这样认为,所以代码四可以有效的避免这样的情况发生。
结论:
常量和变量比较相等的时候,常量放左边会更好一些。
练习
1.判断一个数是否为奇数
2.输出1-200之间的奇数
int main()
{
int a = 0;
scanf_s("%d", &a);
if (a % 2 == 1)
{
printf("奇数");
}
else
{
printf("偶数");
}
return 0;
}
int main()
{
int a = 0;
while (a < 100)
{
a++;
if(a % 2 == 1)
printf("%d\n", a);
}
return 0;
}
在优化一下
int main()
{
int a = 1;
while (a <= 100)
{
printf("%d\n", a);
a += 2;
}
return 0;
}
switch语句
switch语句也是一种分支语句,常常用于多分支情况。
有些语句用if来实现实在是复杂又拖沓,比如:
int main()
{
int day = 0;
scanf("%d", &day);
if (1 == day)
{
printf("星期一\n");
}
else if (2 == day)
{
printf("星期二\n");
}
return 0;
}
我们可以用switch依据来优化这些代码
int main()
{
int day = 0;
scanf_s("%d", &day);
switch (day)
{
case 1:
printf("星期1\n");
case 2:
printf("星期2\n");
case 3:
printf("星期3\n");
case 4:
printf("星期4\n");
case 5:
printf("星期5\n");
case 6:
printf("星期6\n");
case 7:
printf("星期7\n");
}
return 0;
}
你以为这就万事大吉了吗?诶,但是老司机可能就看出来少了点东西了。我们先输出一下这些代码来看看结果。
我们明明想要的是输出星期四就行了,但是代码未停止一直输出到了最后的星期天。其实我们漏掉了break,现在我们加上试试。
int main()
{
int day = 0;
scanf_s("%d", &day);
switch (day)
{
case 1:
printf("星期1\n");
case 2:
printf("星期2\n");
case 3:
printf("星期3\n");
case 4:
printf("星期4\n");
break;
case 5:
printf("星期5\n");
case 6:
printf("星期6\n");
case 7:
printf("星期7\n");
}
return 0;
}
这个时候我们就可以打印一个星期四了。如果不写break,就会一直往下滑,加了break我们就可以跳出。
结论:
case决定入口,break决定出口。
值得注意的是,case语句执行多条语句的时候也是需要大括号的。switch后面的括号里要的是整型表达式,如果换成float类型是不行的。如下
switch (整型表达式)
{
语句项;
}
case 整型常量表达式:
语句;
case后面可以跟比如说:1,‘a’(为什么可以跟a呢,因为字符a储存的是ASCII码值8)
但是不能跟1.0
这些都是细节。
并不是所有的case都要加上break。
比如:
int main()
{
int day = 0;
scanf_s("%d", &day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("工作日");
break;
case 6:
case 7:
printf("非工作日");
break;//这个加不加都无所谓,但是如果后面你想在加点case8东西进去有可能就会出现故障。
}
return 0;
}
如果这样处理,多种情况对应的一样的结果这样就省力很多。
break语句的是绩效股票是把语句列表划分为不同的部分。
default子句
如果表达的值与所有的case标签的值都不匹配,这个时候就需要用到default
对于用户来说他们可能都不知道自己要输入什么范围的值,这样就很容易超出你设定的规定的值。在之前的代码中1-7是合理的值,但是可能用户就会输入9,这样就超出了值,所以我们最好给用户反馈一下标准的值为哪些。
int main()
{
int day = 0;
scanf("%d", &day);
switch (day)
{
case 1:
case 2:
case 3:
case 4:
case 5:
printf("working\n");
case 6:
case 7:
printf("rest\n");
default:
printf("erro, please enter 1 - 7\n");
}
return 0;
}
接下来看看练习题
练习题:
你认为执行完后的结果是什么呢?
#include <stdio.h>
int main()
{
int n = 1;
int m = 2;
switch (n)
{
case 1:
m++;
case 2:
n++;
case 3:
switch (n)
{//switch允许嵌套使用
case 1:
n++;
case 2:
m++;
n++;
break;
}
case 4:
m++;
break;
default:
break;
}
printf("m = %d, n = %d\n", m, n);
return 0;
答案是5 3
switch(n) n是几就执行case几的语句,如果没遇到break就一直往下滑,break会跳出最近的switch语句这一部分而来到最初的switch语句,并不是直接到return。
循环语句
- while
- for
- do while
现在来介绍while循环
while语法结构:
while(表达式)
循环语句;
打印1-10 的数字
int main()
{
int a = 0;
while (a < 10)//为真就进,为假就停止
{
a++;
printf("%d\n", a);
}
return 0;
}
这个代码已经帮我们基础了解了while语句,那我们再继续:
这个代码打印的结果是什么呢?
int main()
{
int i = 1;
while (i <= 10)
{
if (5 == i)
{
break;
}
printf("%d ", i);
i++;
}
return 0;
}
答案:1 2 3 4
break是永久的终止循环
如果我们把代码换成continue会怎样?
int main()
{
int i = 1;
while (i <= 10)
{
if (5 == i)
{
continue;
}
printf("%d ", i);
i++;
}
return 0;
}
答案:1 2 3 4 然后程序陷入了死循环,因为continue会返回到while的判断里面然后一直没有超过5,所以始终没有跳出循环。
continue的作用是:
跳过本次循环的continue后面的代码。直接到while循环的判断部分。
我们在换个代码看看
int main()
{
int i = 1;
while (i <= 10)
{
i++;
if (5 == i)
continue;
printf("%d ", i);
}
}
而这个代码的输出结果是
再看几个代码:
int main()
{
int ch = 0;
while (ch = getchar() != EOF)
{
putchar(ch);
}
return 0;
}
// ch = getchar() = scanf("%c", &ch);
//putchar(ch) = printf(%c", ch);
停止下来的方法是ctrl + z
//EOF - end of file - 文件结束的标志
//getchar()读取失败的时候就会返回EOF。
有可能有人会疑惑,为什么获取的字符要返回是int ch的类型呢?
- 返回的字符,本质上是ASCII码值,是整数。
- getchar函数不仅仅是返回正常字符,还会返回EOF,而EOF是 -1
- 所以不要纠结
我们再继续举几个例子
int main()
{
int ch = 0;
char password[20] = { 0 };
printf("please enter password>:");
scanf("%s", password);
printf("please ensure your password>:(y/n)");
ch = getchar();
if (ch == 'y')
{
printf("success\n");
}
else
{
printf("fail\n");
}
return 0;
}
注意:
scanf里面数组不用取地址,因为数组名本来就是个地址所以我们不需要取地址,但是我们是变量的时候就需要&。
注意2:
如果出现scanf_s函数报错:没有为格式字符传递足够的参数,不要慌张,解决办法是在后面加上一个缓冲区边界值就可以了,如:scanf_s("%s", password, sizeof(password));
这个代码打印的结果是这样的,在我还没输入y\n的时候就立马输出了fail。
原因是:
\n在缓冲区被getchar读取走了。所以等都没等就出现了结果fail。
scanf只提走了abcdef而回车就被getchar提走了。
所以我们下一个要求就是清理掉\n
我们可以再加一个getchar()
但是这样是非常不可取的,因为会碰上其他的麻烦比如说输入一个空格。又会出现fail。
原因:
scanf只会读到abcdef就结束了,getchar又只会读到空格,第二个getchar只能读到1,然后就失败了。所以我们要清理一下这些不必要的缓存。
优化
int main()
{
int ch = 0;
char password[20] = { 0 };
printf("please enter password>:");
scanf_s("%s", password, sizeof(password));
while ((ch = getchar()) != '\n')
{
;
}
printf("please ensure your password>:(y/n)");
ch = getchar();
if (ch == 'y')
{
printf("success\n");
}
else
{
printf("fail\n");
}
return 0;
}
注意:
while空语句
练习:
最后的结果是什么?
int main()
{
int ch = 0;
while ((ch = getchar()) != EOF)
{
if (ch < '0' || ch > '9')
continue;
putchar(ch);
}
return 0;
}
答案:只打印数字。
未完待续,
你的支持就是我的动力。