二、C语言分支结构、循环结构
本章概括if语句关系操作符 !条件操作符esp1 ? esp2 : esp3;逻辑操作符||~switch语句while循环for循环do-while循环break与continuegoto语句1. if语句1.1 if语法if (表达式)语句;表达式成立为真执行语句。表达式不成立为假则不执行语句。在整个C语言中0为假非0为真。非0只要值不是0就为真。这个值可以是整型int、浮点型float、甚至字符型char、指针都可以。1.2 双分支if...else...语法格式if (表达式)语句1;else语句2;表达式成立执行语句1表达式不成立则执行语句2。1.3 if 同时控制多条语句在C语言里if 和 else默认只控制一句语句。要想同时控制多条语句则需要用 { } 将其括起来。 大括号和它里面的语句形成了一个整体称为程序块。1.4 if 的嵌套在 if 或者 else 后面再嵌入一个 if 语句称为 if 的嵌套。if 嵌套示例执行逻辑说明外层 if 先判断 score 是否大于等于 60若成立再进入内层 if 判断等级内层 if 的 else 与最近的 if 配对外层 else 与最外层 if 配对缩进采用统一的 4 空格规范使嵌套层级一目了然。1.5 else总是跟最近的 if 匹配上面的代码中else 并没有与第一个 if 配对而是与最近的第二个 if 配对。因为 C 语言规定else 总是与它前面最近的、尚未配对的 if 匹配。这就是所谓的「else 悬空」问题。为了避免歧义建议在嵌套时使用大括号明确配对关系例如加上大括号后else 与内层 if 的配对关系一目了然代码可读性更高也不容易出错。2. 关系操作符在C语言里用于比较的表达式称为“关系表达式”。其里面的操作符称为“关系操作符”或“关系运算符”。共有6个关系操作符大于、 小于、等于、小于等于、大于等于、!不等于。需要注意的是不要拿和混淆在想要使用时应避免写成这是常犯的错误。例如if (i 1) { printf (haha\n); } 如果写成这样表达式先完成赋值操作再判断真假。此时i为1表达式为真则执行语句。所以这表达式永远为真那么这里用 if 语句就没有任何意义了。这里有一个写法能避免这个错误。if (1 i) { printf(haha\n); } 数值在前变量在后。如果写成if (1 i) { printf(haha/n); 少了一个等号是编译不了的因为变量无法给数字赋值。另一个错误关系操作符不宜连用。例如abc、18age30。因为有时候结果跟预期不一样。就拿abc来说编译器会这么理解(ab)c是拿(ab)的结果去跟c比较。并不是 ab 并且 bc。想实现这个功能就得使用逻辑运算符了ab bc。3. 条件操作符条件操作符也称为“三目操作符”。为什么是三目操作符呢因为一个正常的条件操作符有三个操作数。语法格式exp1 exp2 exp3当exp1为真时执行exp2当exp1为假时则执行exp3。4. 逻辑运算符并且逻辑与运算符意思是并且。例如if (age 18 age 35) { printf(青年\n); }。 当age18 和 age35这两个关系表达式同时为真时if 的整个表达式才为真才会执行语句。有0出0全1出1。||或者逻辑或运算符意思是或者。例如if (age 18 || height 170) { printf(合格\n); }。当age18 或者 height 170任意一个关系表达式为真则 if 的整个表达式为真。有1出1全0出0。!取反逻辑非运算符意思是取反它的存在是为了增加写法的。if (i ! 0) { printf(%d\n, i); }。当 i 不为0时为真。4.1 短路表达式是从左往右执行的。短路例如( 表达式1 表达式2 表达式3 ) 当表达式1为假时后面的表达式2和表达式3都不会被执行并以表达式1的结果作为整个逻辑表达式的结果。|| 短路例如( 表达式1 || 表达式2 || 表达式3 ) 当表达式1为真时后面的所有表达式将不会被执行并以表达式1的结果作为整个逻辑表达式的结果。当表达式1为假时则继续执行后面的表达式。5. switch语句这也是分支语句。语法switch (exp){case 常量1语句;case 常量2语句;···default语句;}exp可以是变量、表达式。但结果必须是整数比如0、1、2、3。常量必须是整数。比如0、1、2、3、4。default当exp没有匹配到对应的case时则执行default。default 可以写在 case 前面也可以写在最后。default的位置没有限制 但通常写在最后。5.1 switch语句和if语句的对比当需要根据整数去执行对应的语句时选择switch语句更合适。大多数情况使用 if 即可。5.2 switch中的break在switch中只要执行到break则跳出switch。假设三个子句都没有break匹配case1后继续往下执行default再执行case2。6. while循环语法格式while表达式语句;表达式为真时执行语句继续判断表达式直到表达式为假时循环结束。在语句中可以有一个条件一个能让表达式为假的条件。练习1屏幕上打印1~10练习2输入一个整数逆序输出。例输入 345 输出 5 4 3先 n % 10 取整数最后一位再 n / 10 去掉整数最后一位。当整数为个位数时例如9 / 10 的结果为0为什么是0因为 9 / 10 执行的是整数除法整数除法丢掉小数点后面的所有值。7. for循环for循环是最常用的循环。因为for循环更可控、更直观。语法格式for (初始化部分; 判断部分; 调整部分)语句;初始化部分只会被执行一次。判断部分为真执行语句为假循环结束。调整部分能让判断部分为假。练习1打印1~100之间3的倍数的数字之和思路首先通过循环遍历产生1~100之间的数字再拿每个数对3取余。当结果余0的时说明该数是3的倍数再将该数累加起来。但是接下来还有更优的算法。思路要算3的倍数可以直接遍历3的倍数再将这些数累加。这样就省掉了判断效率会更高。8. while和for循环的使用场景不知道要循环多少次时使用while循环。知道要循环多少次时使用for循环。9. do - while循环先执行语句再判断。表达式为真继续循环为假则循环结束。语法格式do {语句;}while(表达式);练习打印1~10do - while使用场景至少要执行一次语句时使用do - while。10. break和continuebreak结束整个循环。在循环和swtich语句里只要执行到break跳出循环。continue结束本次循环执行下一次循环。在循环里执行到continues时将不执行continues后面的语句直接进行下一次循环。10.1 while中的break和continue执行break时输出0 1 2 3 4 5当 n 为6时if 语句的表达式成立执行break循环结束。执行continue时输出0 1 2 3 4 5 然后陷入死循环。因为 n 等于6时会执行continue然后直接跳到循环开头判断表达式由于continue后面的代码不会被执行所以n 还是6导致程序陷入死循环。10.2 for 中的break和continue执行break时输出0 1 2 3当 i 为 0 1 2 3时正常输出。当 i 为4时if 语句的表达式成立执行break整个循环结束就没有后面的事了。执行continue时输出0 1 2 3 5 6 7 8 9当 i 为4时if 语句为真执行continue本次循环结束continue后面的代码将不执行直接开始下一次循环所以 4 是不会被打印的。10.3 do - while中的break和continue它的效果跟while的一样没有区别。11. 循环的嵌套循环的嵌套是很常见的。比如遍历二维数组的每个元素输出0 1 2 3 41 2 3 4 5这是一个for循环嵌套for循环的情况。外层循环确定行数内层循环确定列数。12. goto语句也被称为“跳转语句”。在同一个函数内执行到goto语句会无条件跳转到指定标签。语法格式goto label 1;语句1;label 1语句2;当程序执行到 goto label 1 时会无条件跳转到 label 1跳过语句1。例如输出hellogood night直接跳过了“printf(good morning\n); ”