![6e0a266b7a527432ca35c36d137382a2.png](https://i-blog.csdnimg.cn/blog_migrate/e24ee9675c036408d1f5a26d98230911.jpeg)
我在哪?红色?黑暗?
终于,我睁开了眼睛。宇智波?难道我到了火影忍者中?那我现在是谁呢?
——《火影之雪殇》
逻辑类型与运算
逻辑类型
bool
- #include<stdbool.h>
- 之后就可以使用bool和true、false
#include
(这个bool不是真正的源生类型,你首先要包含一个源文件,这个源文件叫<stdbool.h>,有了这个头文件后,才能使用bool,ture和false。但是能我们并没有真正的布尔量的类型,实际上他们仍然是整数,所以当我们输入输出的时候,也没有一个特殊的方式去输出那个bool量,我们仍然用%d。)
逻辑运算
- 逻辑运算是对逻辑量进行的运算,结果只有0或1
- 逻辑量是关系运算或逻辑运算的结果
![5e61b137f9084c404a23b2b4cc939c71.png](https://i-blog.csdnimg.cn/blog_migrate/24cc5c94cf10b75951cb0134e6e4d700.jpeg)
- 如果要表达数学中的区间,如:x∈(4,6)或x∈[4,6],应该如何写C的表达式?
像4<x<6这样的式子,不是C能正确计算的式子,因为4<x的结果是一个逻辑值(0或1),0或1肯定小于6,所以我们得到的永远都是1.
那我们应该怎么写呢?
x∈(4,6)→x>4&&x<6 x∈[4,6]→x>=4&&x<=6
- 如何判断一个字符c是否是大写字母?
c>='A'&&c<='Z'
理解一下下面的语句
- age>20&&age<30; 年龄在20到30之间。
- index<0||index>99; index不在0到99之间。
- !age<20; 虽然逻辑运算符是低于比较运算符的,可是呢,这个“!”是单目运算符,我们又有另一条通道,单目运算符的优先级大于双目运算符的优先级。所以呢,这个就是“!”和age先结合在一起,如果age是0,!age就会变成1,如果age不是0,那!age就会变成0,再去和20作比较。因为!age的结果不是0就是1,所以!age<20永远是正确的了。
优先级
- !>&&>||
- !done&&(count > MAX)
![eb51f9f1adfdc7e83a03b85178703bc6.png](https://i-blog.csdnimg.cn/blog_migrate/d7387db233183908fac78d5c28376a6d.jpeg)
if
学过逻辑运算符后,我们可以改为
if
但是面对下面这个代码
if
这个时候你还能不能写成上面的那种形式呢?能吗?
短路
- 逻辑运算是自左向右进行的,如果左边的结果已经能够决定结果了,就不会做右边的计算
- a==6&&b==1
- a==6&&b+=1
如果说a==6已经是不成立的,但对于这个&&来说需要两边都成立,所以,如果a==6不成立,那么b==1就不会去判断,这是一个好事情,可以提高我们运算的速度;但是如果你在右边是有赋值的,是要产生一些结果的,如a==6&&b+=1,那么,右边的计算就不会做了。它不会把两边的运算都做完了再来做&&的运算,它一定是先做左边,发现不用做了,右边就不会做了。所以对于&&,左边是false时就不做右边了;对于||,左边是true时就不做右边了,这件事情叫做短路。
我们来试下这件事情
#include
我们发现,a>0是false,所以右边的就不会做了,所以最后的结果是-1
![1352fe3b2e70ea98ad8a0b38e00dd799.png](https://i-blog.csdnimg.cn/blog_migrate/7700be667af46170a1e4eba948c45a83.jpeg)
所以,我们以后不要把赋值,包括复合赋值组合写进表达式,如果你记住了这条,你就不会写出上面那样的代码来,这样短路对我们来说就没有什么意义,就是不会起作用的事情。
我们还有一种运算符叫条件运算符。
- count=( count>20)?count-10:count+10;
问号前面是条件,问号后面一直到冒号是条件满足时的值,冒号后面是条件不满足时的值。
想表达的意思也就跟下面代码一样
if
表面上看,你把if else语句写成上面的条件运算符后看起来很简单,但是呢,在复杂的情况下会给你带来很大的麻烦。
- 条件运算符的优先级高于赋值运算符,但是低于其他运算符。
我们来理解下下面几个语句。
- m<n ? x : a+5 如果m小于n的话,结果就是x,否则的话是a+5
- a++ >=1 && b-- > 2 ? a : b 如果a++的结果≥1并且b--的结果大于2的话,结果是a否则是b
- x=3 * a >5 ? 5 :20 如果x=3*a>5的话,结果是5,否则为20
这里我们把赋值运算组合在表达式里,更加增加了表达式的复杂性。所以,我们不想要这种表达,它使得别人理解我们的程序变得更困难了。
最后,我们还有一种非常有意思的运算叫做逗号,逗号在C语言里面是一个运算符。
逗号用来连接两个表达式,并以其右边的表达式的值作为它的结果。
我们来看一下它是什么意思。
#include
我们说过“逗号”的优先级是所有的运算符中最低的,低过“=”,所以,你看当我们编译的时候,它会说这个“5+6”没有用到。
![d06cf491df3eeceaf36b227041f305ff.png](https://i-blog.csdnimg.cn/blog_migrate/28001fc8e9abf6d88e6c5f1a567c5bd6.jpeg)
为什么会这么理解?是因为3+4被赋给了i,“i=3+4”是一个表达式,赋值(=)的优先级比逗号来的还要高,所以“i=3+4”会先算。算完以后才会去算5+6,但5+6没有交给任何人,所以这个表达式的结果没有用到。所以这个时候,我们一定要看到i的结果,那i是7。
如果现在我在3+4,5+6加一个括号,变为
#include
这个时候,3+4没有被用到
![46ce0f41931106e7ef80eaa1d6706069.png](https://i-blog.csdnimg.cn/blog_migrate/2e56be8a91af34a8597c25217575381f.jpeg)
因为这个时候“3+4,5+6”这是一个表达式,这时候,有优先级,因为括号提升了它的优先级,此时,逗号右边的5+6赋给了i,所以结果为11。
你可能会问,这种逗号表达式有什么用?
主要是在for当中使用。
如: for( i=0,j=10; i<j;i++,j--)......这个表达式里,分号把他们分成了3个区域,每一块区域是一个表达式。如果你想要在表达式进行多个运算时,就可以用“逗号”了。目前来说,逗号表达式就这一个用处。
下面我们来用比较a,b,c 的大小,来感受下if else(嵌套的if else)规范的用法。
![c99cd49fba4214758185aa0a1dc01f7c.png](https://i-blog.csdnimg.cn/blog_migrate/de8468feb67059fa38d5165e5fc78442.jpeg)
![e2b8e6dc934437c7e47839bbcdf1d441.png](https://i-blog.csdnimg.cn/blog_migrate/ca8a4accb80f8d96a1bbf54faf35a9fc.jpeg)
当然,if else的写法很多,但是,如果不按规范的写法,不仅给别人造成误读,自己在编写时也会把自己绕晕。所以,一定要规范!!!更何况,现在的编译器,每到一个括号,后面都会补上另一个括号。
综上:在if或else后面总是用{};即使只有一条语句的时候。且else总与最近的if相匹配。
我们下面看一个分段函数,f(x)=-1,当x<0时;f(x)=0,当x=0时;f(x)=2x,当x>0时;
根据这个函数,我们能写出这样的一个代码
if
这个代码看上去不是包含的关系,不是里面外面,而是一层一层连下来的。
![0279f4d6c0c79087f5eab5ddae4e3c51.png](https://i-blog.csdnimg.cn/blog_migrate/073e50f436068d7f1a57d7d31c35f607.jpeg)
这其实是一个级联的if-else if。
结构就是:
if
这里我们习惯把所有的else都对齐,最后会孤立一个“else”。
综上:一个判断且就能对应一个结果,不需要做二次判断,我们就可以选择级联的if-else if。如果有可能做多次判断,才能确定结果,我们用嵌套的if else。
我们再来看一下这段代码
switch
switch-case:里的大括号的内容是平级的,或者说他们都在一个大的房子里,里面的case并没有把他们给单独分开,它会按照一定顺序读取,直到遇到break才会跳出大括号。
比如,下面这个代码
switch
如果我们输入“1”呢?
![ca9259d926009c221028e10ee4e1041e.png](https://i-blog.csdnimg.cn/blog_migrate/fed1c1bc1720fc14fba1c03a654cf3c3.jpeg)
如果我们输入“3”呢?
![b0e2e61b56008bd8c5c764ab14e1f588.png](https://i-blog.csdnimg.cn/blog_migrate/0938c0ae959fe08f3da6b4163828d470.jpeg)
所以,switch语句可以看作是一种基于计算的跳转,计算控制表达式的值后,程序会跳转到相匹配的case(分支标号)处。分支标号只是说明switch内部位置的路标在执行完分支中的最后一条语句后,如果后面没有break,就会顺序执行到下面的case里去,直到遇到一个break,或者switch结束为止。
switch-case的结构
switch (控制表达式){
case 常量:
语句
……
case 常量:
语句
……
default:
语句
……
}
- 控制表达式只能是整数型的结果,也就意味着定义的时候,必须定义为int。
- 常量可以是常数,也可以是常数计算的表达式
讲了这么多,我们发现编程不就是输入和输出吗?那么编程难在哪?难在想问题,难在怎么把问题变成程序,怎么处理编程中遇到的细微的小的情况。
现在假设我们要算log以2为底x的对数。我们可以写出这样的代码
int
![f809f936e1130760b4c75881abbbd25c.png](https://i-blog.csdnimg.cn/blog_migrate/17fd6c457eb7bf9eabfbf62d3db3bcc9.jpeg)
运行后我们发现这里是1。其实因为x一直在除2,所以最终x的结果为1,那么,如何让这个x值为我们原先输入的x的值呢?
这里就又有一个小套路了。我们可以这样
int
![340b185a0adde5f9b2f32fe09a3ce256.png](https://i-blog.csdnimg.cn/blog_migrate/c5087d43e84ea4d7a8326c1a34b31b3c.jpeg)
我们再来看一段代码
int count =100;
while (count >=0 ){
count --;
printf("%dn",count);
}
printf("发射!n");
我们现在有3个问题
- 这个循环需要执行多少次?
- 循环停下来的时候,有没有输出最后的0?
- 循环结束后,count的值是多少?
小套路:如果要模拟运行一个很大次数的循环,可以模拟较少的循环次数,然后作出推断。
计算平均数
#include
其实,看了半天的代码,我们一直都在围绕着循环计算,那么现在就先暂时总结下吧,我们最先学了if语句来用于判断,接着,我们又学了if else来进行更充分的选择与输出;接着,为了能够循环进行某个计算,我们学了while循环;但是while循环是先判断后运算,那么,有先运算后判断的循环吗?答案:有。所以,我们紧接着学了do-while循环。在第二周笔记的最后,我们又介绍了for循环,它一般情况下用于计数,且循环的次数为有限次的,并且它还可以和while循环等价。(循环具体内容见第二周笔记)
前方 一片天:C语言入门——第二周笔记zhuanlan.zhihu.com![ad0db49a514303ccc917f1a661654b91.png](https://i-blog.csdnimg.cn/blog_migrate/a93beeacc5082f7f069feb52f894b715.jpeg)
现在我们来做一个猜数的游戏。这个游戏是这样的:让计算机来想一个数,然后让用户来猜,用户每输入一个数,就告诉它是大了还是小了,直到用户猜中为止,最后还要告诉用户它猜了多少次。
- 因为需要不断重复让用户猜,所以需要用到循环
- 在实际写出程序之前,我们可以先用文字描述程序的思路
- 核心重点是循环的条件
- 计算机随机想一个数,记在变量number里;
- 一个负责计次数的变量count初始化为0;
- 让用户输入一个数字a;
- count递增(加一);
- 判断a和number的大小关系,如果a大,就输出“大”;如果a小就输出“小”;
- 如果a和number是不相等的(无论大还是小),程序转回到第3步;
- 否则,程序输出“猜中”和次数,然后结束。
这里,我们看到,循环的条件是:a和number不相等。
#include
程序里的rand,表示能够随机取一个数。rand()%100,可以让这个随机数变小。而且,这里更适合用do-while循环,因为用户猜一个数,肯定先要运行一次算法,接着告诉用户结果。这里while后面的条件一定要是能够进行循环的条件,而不是跳出循环的条件。还有就是告诉大家一个小秘密,对于100数以内的数来猜的话,你正确的猜法,最多只用7次就能猜出来。为什么?以后我们会讲到的。
对一个整数,我们如何分解出它的各个位上的数字,然后加以计算?我们可以用%10得到它的各位,然后依次重复此操作,就能得到更多位的数;如果用/10,我们就能够去掉了它的个位数。
#include
if语句常见的错误
- 忘了大括号
- if后面的分号
- 错误使用==和=
- 使人困惑的else
分号,代表一个语句的结束,每个分号之间的语句没有直接的关系。如果在if语句中,你忘了加大括号,那么,if后面的每一条语句都会去执行,此时也就失去了判断的作用。
如
if
此时的结果是
![4c0d3f96891e9832e6f6ff5c2221f189.png](https://i-blog.csdnimg.cn/blog_migrate/9f4e3f2b83483df5899a66dcfc276a02.jpeg)
加上大括号后
![128f7c93b280ff31c78bb914db8f937c.png](https://i-blog.csdnimg.cn/blog_migrate/8c0988bba462151678f64895e1a31480.jpeg)
if后面如果加分号的话,就等于if判断的作用就消失,此时不论你输出哪个数,都会执行后面的语句也即大括号里的语句。
如
if (age >60);
{
salary = salary*1.2;
printf("%f",salay);
}
结果
![4f4a55c69d0d7eb6cc1df6faec944751.png](https://i-blog.csdnimg.cn/blog_migrate/e82e52bf526be5eea3dc66b4b21f7668.jpeg)
其次,if语句在表示等于时一定要用“==”,而“=”我们前面就说过,它代表赋值。
有时,我们在运行代码时,会出现error或者warning,要注意区分它们,有时出现warning不代表写的错,但是运行后所算的结果不一定是我们原先想要的,所以,在我们初学计算机时一定要敬畏warning,要养成一个良好的习惯。
代码风格
![c3349736d8636a18b64da650bb36db14.png](https://i-blog.csdnimg.cn/blog_migrate/cdcee4edf0fc1163ebc9fe5b682716b6.jpeg)
总之,我们在写if语句时一定要注意下面2点
- 在if和else之后必须加上大括号形成语句块;
- 大括号内的语句缩进一个tab的位置