欢迎光临散文网 会员登陆 & 注册

第 15 讲:程序结构(一):条件结构

2021-03-31 08:32 作者:SunnieShine  | 我要投稿

我们前面用了六个文章介绍了运算符的使用。今天我们进入新的板块:程序控制结构。C 语言里,程序控制结构一共有四种:顺序结构、条件结构、循环结构和跳转结构。C# 里一共是 5 种:顺序结构、条件结构、循环结构、跳转结构和异常控制结构。顺序结构是最基础的结构,在前面的文章早就体现过了,只是没有提出它的名称。只要一段代码从上到下依次执行的过程,我们就把这段代码称为顺序结构。

Part 1 if 的用法

1-1 if 语句

前面的内容我们无法控制代码在指定条件的时候,才做一些工作。当我们需要这样的用法的话,我们将使用 if 语句来控制。

格式是这样的:

有这样两种写法。我们来写一个例子。

在这个例子里,我们在 if (a > b) 之后使用大括号,将 Console.WriteLine 完整包裹起来。这表示,用大括号包裹起来的所有内容,都属于“当 a > b 成立的时候,才会执行的逻辑”。

a > b 的结果是 false(即不成立)的时候,不管大括号里有多少东西,都不会得到执行,会被完全忽视掉。显然,这个例子里,30 是比 40 小的,所以条件并不成立。因此,你在执行过程之中,什么输出都看不到。

顺带一说,既然用到了大括号,那么里面的内容就需要缩进来保证代码的整洁。如果大括号内的内容不缩进的话,看起来就很奇怪。当然,它并不影响编译程序和运行程序就是了。

1-2 else 语句

显然,这样的格式并不能满足我们正常的需求。前文的例子我们其实还想看到另外一个输出内容,“ba 大”,但在代码里没有体现。因此,else 就派上用场了。

if 差不多,else 后也是跟一个大括号,或者一个单独的语句。这部分表示在 if 条件并不成立的时候,才会得到执行。

如果我们这么写代码的话,这就表示,当 if (a > b) 里的 a > b 条件成立的时候,会输出 ab 大的内容;但是如果不成立,就会输出 b 大于 a 的内容。

从这个介绍文字就可以看出,它们是完全对立的两种情况,所以 if-else 整体的话,if 的部分和 else 的部分并不会都执行,也必然必须执行至少一个部分。这就是 if-else 配合一起使用的时候的特点。

当然,前文说过,空格是不影响编译和运行程序的,因此我们甚至可以写在一行:

这么写依然是没有问题的。代码写成什么样看的是个人的习惯,只要逻辑没有问题就行。

1-3 else 后也不一定非得是大括号和语句

前面的示例,可能我们漏掉了一个地方。a > b 的对立情况就一定是 b > a 吗?当然不是,还可以相等。但是我们刚才没有体现这一点。下面我们来试着添加这个部分:

a > b 条件不成立的时候,我们会想着走 else 这一段代码。而 else 里又是一个 if 判断:a == b 的条件。所以实际上就是这么一个过程:我们先看 a > b 条件是不是成立的。如果不成立,就会继续判断 a == b 这个条件。因此,实际上这种写法就解决了前面说的,忘记判断 a == b 的问题。

不过,这个写法还是有点丑。C# 可以允许我们去掉 else 的大括号:

这个写法是没有问题的。C# 是知道,下方的 if-else 是一个整体,因此不需要大括号就知道整个代码里的 else 就完整包含了下面一大坨内容。但是,实际上还是有点丑。不如我们把 else 后直接跟上 if

这样就很好了。从这个角度来说,我们一下就可以看出逻辑:先 a > b;如果不满足就 a == b;再不满足就执行最下面的 else 的部分。

1-4 它和条件运算符的关联

最开始,我们说到过一个东西,叫条件运算符。条件运算符的逻辑完全类似于这里的 if-else 的过程。不过问题在于,它们有区别吗?

条件运算符用来表示和赋值,因此 ? 后和 : 后的部分全都是一个表达式(所谓的表达式,就必须反馈一个结果数值出来;而语句则不一定要反馈结果,它可以像是 Console.WriteLine 那样,单独成一个语句来用)。而 if-else 则可以跟语句或者是赋值表达式。我们来看一下。

这是将 ab 较大的数值赋值给 c 的过程。如果要写成 if-else,就得这样:

或者直接写到一行上去:

不管怎么做,代码都比条件运算符要复杂。因此,我们建议用条件运算符而不是用 if-else,尽管逻辑上是完全一样的。

1-5 永真和永假条件

有没有想过,既然这里我们传入的是一个 bool 的表达式,那么我们直接写 truefalse 会如何。

或者

猜都猜得到,只要条件是 true 就会进去执行。因此 if (true) 等价于根本没写条件判断。而 if (false) 则判断了个寂寞。永远都不成立,那么 if 里面的语句永远都得不到执行。

Part 2 switch 的用法

很显然,前文的 if-else 是无敌的。但是很遗憾的是,对于一些特殊的条件判断,if-else 怎么写都很臃肿。比如我们输入一个月份数值,然后判断月份到底有多少天。那么用 if 就得这样:

我且不说其它的内容,就判断 month 的信息,也显得很臃肿。此时,我们这里介绍一个新的语法格式:switch 语句。

2-1 switch 语句

switch 语句的用法是这样的:

这个写法可能不是很好懂。我们直接上代码:

貌似……好像代码没有减少多少。不过更好看了,因为 month 直接写到 switch 上用来表示“我这里就是按 month 自身的数值进行分情况讨论”。case 里写的就是 month 的所有可能数值。default 则表示当前面所有数值都不是 month 现在的数值的时候,就走这里。

请注意一下,每一个 case 语句最后,都要跟一个 break;,这是因为这是为了让每一个 case 断层。C 语言里,没有写 break 就会导致执行的时候出现潜在的问题。C# 沿用了这种机制,但防止你误用代码,所以不写 break 会产生编译错误,提示你必须加了 break; 之后才能继续执行。C# 里,break; 语句遇到后,会自动跳出 switch 的内容。比如这个例子里,会自动跳转到第 27 行代码执行。

2-2 同执行语句简化

显然,我们发现当 1、3、5、7、8、10、12 月份的时候,day 都是 31;而当 4、6、9、11 的时候,day 都是 30。switch 还有一个强劲的功能就是,简化 case。我们只看 switch 这一块,代码可以简化成这样:

这样的话,就更简单一些了。如果写 if 的话,可能你需要用 || 来连接条件。比如说第 3 行转成 if 就得写成这样:

显然,就很丑。

2-3 字符串的 switch

在 C# 里,因为有字符串这种类型,因此 switch 还可以对字符串进行判断。

当然,这只是一个例子程序。不过这一点我们用到了 case 字符串 的格式。确实,C# 也是允许这么做的。

由于字符串的每一个字符都不一样的关系,就算只有大小写不同的两个字符串也属于两个不同的字符串,因此我们这里在例子程序中是分开成两个情况作判断的。

2-4 很遗憾,布尔量没有 switch 一说

这显然是废话。bool 类型的数值往往只有 truefalse 两种可选情况,那么你要写成 switch 语句的话,你只能写成这样:

可问题在于,case truecase false 就已经构成了 bool 类型的所有可能取值的情况。那么,我是不是就意味着我可以把这里的 case false 替代为 default 呢?那么,我这么写和前文的语义是一样的吗?

如果真的是一样的,那么我这么写代码不就很奇怪了吗?

是的。考虑到这种写法的语义格式的复杂性,以及使用场景的问题,C# 并未对布尔型变量开放允许使用 switch 语句。虽然很遗憾,但也是合情合理的情况。

Part 3 混用 switchif

前文我们没有判断 2 月份在平年还是闰年。如果我们加上这个判断的话,就这么写:

但仍请注意,case 最后必须跟一个 break;,因此就算我们写了一大坨东西,最后的 break; 也是不可少的。当然了,你也可以这么写:

这么写呢,就是长一点,但是用的是条件运算符。

Part 4 ifswitch 的选择

如果你在写代码的时候,肯定会遇到“我到底用 if 好,还是 switch 好”的问题。有一个很好的判断标准是,只要你要对一个单独的数值进行判断的,就用 switch;否则都用 if

比如前面的例子,我们对 month 进行数值的确认,显然是用 switch 更合理;但是如果是其它的情况,我们都应该采用 if 来表示。当然了,如果可能数值过多的话,我们就不建议用 switch 了。


第 15 讲:程序结构(一):条件结构的评论 (共 条)

分享到微博请遵守国家法律