Skip to content

Latest commit

 

History

History
195 lines (128 loc) · 7.69 KB

Lesson06.md

File metadata and controls

195 lines (128 loc) · 7.69 KB

Lesson 06 - 判断

终于,我们已经了解了基本所有的关于变量与操作符的知识了,你也终于可以对你的各种类型的变量们“肆意妄为”了。那么这节课,我们将开始接触编程逻辑的训练了。

以我们目前的所学,我们只知道计算机可以按照某种预定的顺序去执行代码。但是有的时候我们可不能让程序不顾目的地一条路走到底,这时咱们就请判断语句闪亮登场吧。

我想先请各位思考一下,大家每天是怎么选择穿什么衣服的:

  1. 如果某件衣服穿过但还没洗,我则不会考虑穿这件衣服;
  2. 如果我想穿的裤子颜色是黑色的,我则不会再选择黑色的衣服;
  3. 如果我想……

在这个过程中,我是通过一次次判断(检查某件衣服的情况)与执行相对应的操作(把排除的衣服放到另一边)进行筛选的。

而这就是写判断语句块的两大要素:条件相应条件对应的该执行的语句

1 if

我们直接来看if判断语句块的代码:

if (condition) { // condition为条件
    statements; // statements为相应条件成立时需要执行的语句(组)
    ...
}
  • condition:本质上是一个布尔表达式,其实就是一个条件,诸如radius < 0GPA >= 3.7 && GPA < 3.8
  • statements:相对应括号条件成立时,所需要的执行的语句

执行效果最终表现为:当condition这个地方的条件成立(值为true)时,才执行后面的语句块(大括号括起来的地方)里的statements。

2 if-else

有的时候我们希望condition不成立的时候,也去做一些特定的事情。那么我们就可以用到if-else语句块了:

if (condition) {
    // do something
    ...
}
else {
    // do something else
    ...
}

在这里,我们先停下来看一个例子:

我们希望按照四年一闰,百年不闰,四百年闰的规则输出一个年份(year)是一个闰年还是平年(想要练习一下的同学可以先不看下面的答案哦)

注意我刚刚说的两大要素,首先我们想到的必然是去把四年一闰,百年不闰,四百年闰的规则用逻辑表达式表示出来。第一步,我们需要判断以下三点:

  • 条件1:变量year能被4整除?
  • 条件2:变量year能被100整除?
  • 条件3:变量year能被400整除?

接下来你要做的就是确定这个几个条件之间的逻辑关系,也就是它们应该用什么逻辑操作符进行连接

  1. 当条件1成立且条件2不成立时,year才是闰年,显然,这里需要用到且操作符
  2. 但是注意,上面的条件忘记了考虑像2000年(千禧年!)这种闰年
  3. 不难发现,只要条件3成立,year就一定是闰年,因此条件3应该与上面的条件使用或操作符连接

那么,我们的判断就应该是这样的:year % 4 == 0 && year % 100 != 0 || year % 400 == 0,如果你不确定是&&先算还是||先算,推荐你打一个括号:(year % 4 == 0 && year % 100 != 0) || year % 400 == 0

那么当它成立时,我则打印xxxx is a leap year;否则我应该打印xxxx is a common year

最终,我们的核心代码如下:

if( (year % 4 == 0 && year % 100 != 0) || year % 400 == 0 ) {
    System.out.println(year + " is a leap year!");
}
else {
    System.out.println(year + " is a common year!")
}

同学们常常被debug的问题困扰着,明明本地IDEA里自己输啥都对,但是放到OJ上一跑就WA(Wrong Answer),手动怎会如此.jpg

当遇到这种问题时,建议各位去仔细想一想每一种情况,去针对每一种情况为自己出一些样例。比如在这个题中,你就可以想出针对三个条件成立与不成立的样例,如:

  • 2021年(123都不成立)
  • 2024年(1成立,2不成立,3不成立)
  • 2100年(1成立,2成立,3不成立)
  • 2000年(1成立,2成立,3成立)

检查看看,它们是否都有正确的结果呢?

不知道大家是否了解2000年的千年虫危机(好像已经是大部分人出生之前的事情了)。大量计算机的智能系统,年份只使用额两位十进制数表示,因此当系统进行(或涉及到)跨世纪的日期处理运算时(如多个日期之间的计算或比较等),就会出现错误的结果,进而引发各种各样的系统功能紊乱甚至崩溃。除此之外,有一部分电脑系统缺乏对四百年闰的判断底层逻辑,导致日期直接由2月28日过渡到了3月1日。

3 else if

当某个条件进入else分支时,你想要再次进行判断,就可以使用方便的else if,而不是再在else块内写一个if块啦:

if (condition1) {
    ...
}
else if (condition2) {
    ...
}
else {
    ...
}

4 switch

switch语句可以根据变量的值来选择下一步执行哪一句代码

下面的代码想要根据month的值,来输出相应月份对应的季节:

switch(month){
    case 3:
    case 4:
    case 5: System.out.println("Spring"); break;
    case 6:
    case 7:
    case 8: System.out.println("Summer"); break;
    case 9:
    case 10:
    case 11: System.out.println("Autumn"); break;
    case 12:
    case 1:
    case 2: System.out.println("Winter"); break;
    default: System.out.println("Invalid month!"); // run default branch if there's no same value of month
}

当程序执行到这里时,switch会根据其后小括号中变量month的值,选择应该从哪里执行,而break;语句,会结束switch块,直接去执行这之后的代码。我写到这里的时候正好是十一假期,那我们就假设month的值为10。那么程序在经过第一行的判断后,就会找case 10的那一行,也就是第9行。但是第九行没有语句,也没有break;,所以程序会继续向下执行第十行的语句,打印出Autumn字样,然后出现了break;,于是直接结束了switch块。更细节地,month为3、4、5时会输出Springmonth为6、7、8时会输出Summermonth为9、10、11时会输出Autumnmonth为12、1、2时会输出Winter;若都不是,则输出Invalid month!

注意事项:

  1. 括号内的变量值只可以是char、byte、short、int或者String型值
  2. case后的值必须与括号中的变量的类型相同
  3. default语句块和break语句都是可加可不加的,重点在于你的逻辑

5 condition expression

条件表达式(condition expression)像是一种简化版的if-else语句块,我们先来看看它的形式:

// condition ? expression1 : expression2
max = (num1 > num2) ? num1 : num2;

其中的(num1 > num2) ? num1 : num2就是一个条件表达式,若condition为真,则结果为expression1;否则为expression2。在这个具体的例子中,当num1大于num2时,表达式结果为num1,赋值给变量max的值就是num1的值;否则就是num2

上面的代码其实等效于如下的代码:

if (num1 > num2) {
    max = num1;
}
else {
    max = num2;
}

6 省略大括号

当某个语句块中只有一条语句时,我们可以省略其周围的大括号,比如上一节最后的代码就可以写成这样:

if (num1 > num2)
    max = num1;
else
    max = num2;

但是为了避免一些不必要的歧义(例子请看下节),建议大家在初学阶段都打上该打的括号。

最后要说的

逻辑能力不仅仅是与生俱来的,也可以是后天的努力习得的。

多多练习如何将一些抽象的判断用逻辑语言表现出来

(思考:如何判断一个字符串是不是一个合法的学号呢?)