运算符和表达式-2 与分支结构

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了运算符和表达式-2 与分支结构相关的知识,希望对你有一定的参考价值。

1. 运算符和表达式-2

1.1. 赋值运算

1.1.1. 使用“=”进行赋值运算

“=”称为赋值运算符,用于对变量赋值。关于赋值运算符,除了将右边的表达式计算出来赋给左边以外还具备如下特点:赋值表达式本身也有值,其本身之值即为所赋之值。示例代码如下所示:

  1. int num = 18, index;
  2. System.out.println(index = num % 5); // 结果为:3,赋值表达式本身也有值
  3. System.out.println(index); // 结果为:3
  4. int a, b, c;
  5. a = b = c = 100;
  6. //c=100 整个表达式的值为100,将其赋值给b,同样b=(c=100) 整个表达式的值也为100,然后又将这个值赋给了a,所以a的值也是100.

1.1.2. 使用扩展赋值表达式

在赋值运算符”= ”前加上其它运算符,即为扩展赋值运算符,其效率高于赋值运算符,推荐使用,扩展赋值运算符如下图 - 5所示:

技术分享

1.2. 字符连接运算

1.2.1. 使用“+”进行字符串连接

“+”除了可以进行算术运算以外,还可以实现字符串的连接,同时可以实现字符串与其他数据类型的“相连”。

当 + 号作用于两个数字类型变量时,是在进行算术运算。

当 + 号两边的变量有一个是字符串类型,即””括起来的时候,则其进行的是字符串的连接,连接后的结果为字符串类型。示例代码如下所示:

  1. int a = 100;
  2. String msg = "a=" + a;
  3. System.out.println(msg); //a=100,字符串拼接
  4. msg = "" + 100 + 200;
  5. System.out.println(msg); //结果为: 100200,””+100,为字符串100再拼上200为100200
  6. msg = 100 + 200 + "";
  7. System.out.println(msg); //结果为:300,100+200为算术运算结果为300,再加上””为300

1.3. 条件(三目)运算

1.3.1. 使用条件(三目)运算符

条件运算符又称“三目”运算符,其结构为:boolean表达式 ? 表达式1:表达式2。

条件运算符的规则如下:

  1. 先计算boolean表达式;
  2. 如果boolean表达式的值为true,整个表达式的值为表达式1的值;
  3. 如果boolean表达式的值为false,整个表达式的值为表达式2的值。

示例代码如下:

  1. int a = 100, b = 200;
  2. int flag = a > b ? 1 : -1; //因为a>b为false,所以整个表达式的值为-1,将其赋给flag,即:flag的值为-1。

1.3.2. 条件(三目)运算符的嵌套

条件运算符可以嵌套使用,所谓嵌套是指在条件(三目)表达式:“boolean表达式 ? 表达式1:表达式2”中的表达式1或表达式2也是条件(三目)表达式,相当于多重判断,示例代码如下所示:

  1. int a = -3;
  2. String r = a > 0 ? "正数" : (a == 0 ? "0":"负数");
  3. System.out.println(r); //结果为负数,因为 a 的值小于 0,即boolean 表达式的值为 false ,则取问号后第二个表达式的值作为表达式的结果。而问号后的第二个表达式也是一个三目运算符所构成的表达式。因为 a==0 表达式的值为 false,则取“负数”为表达式的结果。

2. 分支结构

2.1. 什么是分支结构

首先,看一个需求,假设需要编写一个收银柜台收款程序,要求根据商品单价、购买数量以及收款金额,计算并输出应收金额和找零。

通过分析可以想到,这个程序,需要定义三个输入,即:单价、数量、金额。定义两个输出,即:应收金额、找零。因为金额有可能为小数类型,所以变量的数据结构定义为double类型。

此程序可以以如下方式解决,用户由控制台输入:商品单价、购买数量、收款金额;而后计算商品的总价及找零,并输出。示例代码如下所示:

  1. public static void main(String[] args) {
  2.         //定义输入
  3.         Scanner console = new Scanner(System.in);
  4.         System.out.println("请输入单价(¥):");
  5.         double unitPrice = console.nextDouble();
  6.         System.out.println("请输入数量:");
  7.         double amount = console.nextDouble();
  8.         System.out.println("请输入金额(¥):");
  9.         double money = console.nextDouble();
  10.         console.close();
  11.         
  12.         //计算商品总价
  13.         double totalPrice = unitPrice * amount;
  14.         //计算找零
  15.         double change = money - totalPrice;
  16.         
  17.         //输出
  18.         System.out.println("应收金额为:" + totalPrice +",找零为:" + change);
  19.     }

如上代码,输入数据后,可以正确输出应收金额及找零,假设现在需求增加,当商品总价满500时享受8折优惠, 如何解决?这种情况,在软件应用中,需要使用分支结构来实现。

任何复杂的程序逻辑结构都可以通过“顺序”,“分支”,“循环”这三种基本的程序结构实现。如图 – 1所示:

技术分享

刚刚的案例即为顺序结构,第一步A执行完执行第二步B,第二步执行完执行第三步,一步一步顺序执行。分支结构即为根据一个条件做判断,如果条件满足则执行A,否则执行B。还有一种即为后面要介绍的循环结构。原则上,任何复杂的程序, 都可以通过这三种结构来解决。

当程序在运行过程中, 需要根据不同的条件而运行不同的语句时,即可以使用分支结构,Java中有专门的语法结构来实现分支:

  1. 当条件满足时运行某些语句;当条件不满足时则不运行这些语句——if结构。
  2. 当条件满足时运行某些语句; 当条件不满足时运行另外一些语句——if-else结构 

2.2. if语句

2.2.1. if语句的执行逻辑

首先看下面if语句的语法:

  1. 语句0;
  2. if(逻辑表达式){
  3.      语句1;
  4.      语句2;
  5. }
  6. 语句3;

如上语句的执行步骤如下所示:

步骤一:执行语句0;

步骤二: 判断逻辑表达式的值,此表达式的值结果为boolean类型,即true或者false。此处可以是关系表达式也可以是逻辑表达式。

  1. 若值为true,则执行if语句块中的语句;
  2. 若值为false,则跳过if语句块;

步骤三:执行语句3语句。

2.2.2. if语句流程图

if语句的执行逻辑如下图 - 2所示:

技术分享

通过图示得出结论:当条件满足时,执行语句块,然后执行if语句下面的语句;否则跳过语句块,直接执行if语句下面的语句。

2.2.3. if语句用于处理分支逻辑

if语句是java中用于处理分支结构的语句,下面,通过if语句来实现刚刚的打折功能逻辑,再回顾一下新添的需求:如果商品总价大于等于500,则打8折。如下图– 3 红色部分即为if的判断逻辑:

技术分享

可以看到,计算商品总价之后,进行了总价大于等于500的业务判断,若判断结果为true,则计算折扣后的应收金额,再计算找零后输出。若判断结果为false,则直接计算找零后输出。如下即为实现代码:

  1. ……
  2. double totalPrice = ……;
  3. if (totalPrice >= 500) {
  4.         totalPrice = totalPrice * 0.8;
  5. }
  6. ……

通过如上代码可以看出: 当total>=500为true时, 总额乘以0.8, 即打8折。当total>=500为false时,不执行if语句块的内容。

2.2.4. if语句块不要省略“{}”

if语句块在执行过程中,有一个问题是需要注意的,先看下面的两段代码:

  1. 代码一:
  2. int num = 5;
  3. if(num>2)
  4.         System.out.print(num);
  5.         System.out.println(“ 大于2 ”);
  6. 代码二:
  7. int num = 5;
  8. if(num>2){
  9.     System.out.print(num);
  10.     System.out.println(“ 大于2 ”); }

分析如上两个代码段,得出的结论是:两段代码输出结果一样,即 “5 大于 2”。再看如下两段代码,输出结果还一样吗?

  1. 代码一:
  2. int num = 5;
  3. if(num<2)
  4.         System.out.println(num);
  5.         System.out.println(“小于2”);
  6. 代码二:
  7. int num = 5;
  8. if(num<2){
  9. System.out.print(num);
  10. System.out.println(“小于2”); }

分析如上两个代码段,可以得出,代码段一的输出结果是“小于2”,代码段二没有任何输出。分析输出结果可以看出,代码段二的结果为正确结果,而代码段一输出的“小于2”是不应该存在的,出现这个问题的原因在于,在if语句之后没有添加“{}”,而java语法规定,当if语句块中只包含一条语句时,可以省略“{}”,但是if语句块也只能作用于它下面的一条语句。

看如上代码段一的if判断,只作用于第一个输出语句,因为num<2结果为false,所以第一个输出语句并未执行,而第二个输出语句“小于2”不属于if作用范围,所以无论条件满足与否,都会执行。故而,输出了“小于2”的结果。

所以,考虑到代码的可读性、扩展性,建议即便if语句块中只有一条语句,也不要省略“{}”。

2.3. if-else语句

2.3.1. if-else语句的执行逻辑

分析上面的案例,当计算出最终(打折前、打折后)的应收金额后,直接计算找零,这

个时候就出现了一个问题,如果收款的金额小于应收的金额,那么输出的找零就会为负数结果,这显然用户体验不好,下面对它做一下改进,要求考虑程序的异常情况,增加需求如下:

  1. 若收款金额大于等于应收金额,则计算找零后输出;
  2. 若收款金额小于应收金额,则输出错误提示信息,如何处理?

这种情况,单单使用if语句显然无法解决了,因为if语句用于解决的是,当某条件满足时执行某段业务处理的逻辑,而现在的逻辑时,当条件满足时执行某段业务逻辑,当条件不满足时需要执行另一段业务逻辑。看如下图 – 4所示的红色部分:

技术分享

若想实现这样的判断逻辑,可以考虑if-else语句。看一下下面的语法:

  1. 语句0;
  2. if(逻辑表达式){
  3.      语句块1;
  4. } else {
  5. 语句块2;
  6. }
  7. 语句3;

如上语句的执行步骤如下所示:

步骤一:执行语句0;

步骤二:判断if逻辑表达式的值:

  1. 若值为true,则执行语句块1;
  2. 若值为false,则执行语句块2;

步骤三:执行语句3语句。

2.3.2. if-else语句流程图

if-else语句的执行逻辑如下图 - 5所示:

技术分享

通过图-5可以看到:当条件满足时,执行语句块1,然后执行if-else语句下面的语句;否则执行语句块2,再执行if-else语句下面的语句。

2.3.3. if-else语句用于处理分支逻辑

通过下面的代码,可以解决新增加的异常情况处理问题:

  1. ……
  2. if( money >= totalPrice ) {     double change = money – totalPrice;
  3.     System.out.println("应收金额为:" + totalPrice +",找零为:" + change);
  4. } else {     System.out.println(“Error! 收款金额小于应收金额”);
  5. }

说明:money为收款金额,totalPrice为应收金额;当收款金额大于等于应收金额时,则计算找零并输出,否则,提示错误信息。

2.4. else if语句

2.4.1. if-else语句的嵌套

在日常生活中,很多情况并非进行一次逻辑判断就可以获取最终的结果, 如图– 6所示:

技术分享

可以看出,实现制作沙拉的过程进行了两次判断,首先判断是否有黄瓜,若有则直接制作黄瓜沙拉后结束,若没有黄瓜则判断是否有胡萝卜,若有则制作胡萝卜沙拉结束,没有则不能上菜结束。这种情况,单单使用if-else还无法实现,因为if-else只是判断了一次就结束了,而当前的情况需要判断两次。

在java程序中,当程序的分支数大于2时,可以用if-else嵌套的方式解决,即:else语句块中又包含if语句(或if-else语句),下面看一个实际的需求:

根据学员的成绩来输出等级:

  1. A(成绩大于等于90分);
  2. B(成绩小于90分且大于等于80分);
  3. C(成绩小于80分且大于等于60分);
  4. D(成绩小于60)。

此程序即为多路判断,如图– 7所示流程图:

技术分享

首先判断分数是否大于等于90,若为真则输出A终止,为假则再判断分数是否大于等于80,若为真输出B终止,为假则再判断分数是否大于等于60,若为真输出C终止,为假则输出D。分析可以看出,该程序经过了3次判断。需要在else中嵌套判断。代码如下所示:

2.4.2. else if语句执行逻辑

如下图 – 8所示,在else中再次进行if-else的判断:

技术分享

从上图中看出,当判断层数比较多时,代码清晰度不够好,在实际开发中常常使用如下图- 9的方式来实现,事实上,else if结束就是if-else嵌套的简便写法:

技术分享

实现该程序代码如下所示:

  1. … … ...
  2. if(score>=90) {
  3.     System.out.println("A");
  4. } else if (score>=80) {
  5.     System.out.println("B");
  6. } else if(score>=60) {
  7.     System.out.println("C");
  8. } else {
  9.     System.out.println("D");
  10. }

通过上面的代码可以看出,使用else if方式,程序逻辑更清晰,可读性更好。

2.5. switch-case语句

2.5.1. switch-case语句执行逻辑

switch-case是一种特殊的分支结构,与else if类似,但其应用面不如else if,只能用于特殊的情况之下, switch-case可以根据一个整数值的不同取值,从不同的程序入口开始执行。语法如下所示:

  1. switch(整型表达式) {
  2. case 整型常量值1: //入口1
  3. 语句1;
  4. 语句2;
  5. case 整型常量值2: //入口2
  6. 语句3;
  7. ……
  8. default: //默认入口
  9. 语句n;
  10. }

switch-case流程图见图 – 10所示:

技术分享

分析上图,可以看出其执行逻辑如下:

计算整型表达式的值:

  1. 若值等于整型常量值1,则从语句1开始执行,而后语句2、3,一直执行到语句n。
  2. 若值等于整型常量值2,则从语句3开始执行,一直执行到语句n。
  3. 若没有找到匹配的值,则只执行语句n。

通过分析可以看出,switch是以case后的整型常量值作为入口的,若值相等,即开始执行其后面的语句。

使用switch时需要注意两个问题,第一,case后面的常量值必须不同,第二,switch后面的整型表达式的值必须是整型或字符型。

2.5.2. switch-case和break联合使用

前面的代码中判断整型表达式的值,若其值等于某个整型常量值,则会以此作为入口,依次执行其后面所有的语句。但是在实际应用中,通常case1、case2、…、caseN对应完全不同的操作,即: 若表达式的值等于case1,则只执行case1后的语句,不会再执行case2、caseN等后面的语句。这种情况下可以和break语句配合使用,执行完相应语句后即退出switch块,不继续执行下面的语句。语法如下所示:

  1. switch(整型表达式) {
  2. case 整型常量值1: //入口1
  3. 语句1;
  4. 语句2;
  5.              break ;
  6. case 整型常量值2: //入口2
  7. 语句3;
  8.              break ;
  9. ……
  10. default: //默认入口
  11. 语句n;
  12. }

如上程序中的break语句的作用在于跳出switch结构,其执行逻辑如下:

  1. 计算整型表达式的值:
  2. 如果值等于整型常量值1,则执行语句1、语句2,跳出switch结构结束;
  3. 若值等于整型常量值2,则执行语句3,跳出switch结构结束;
  4. 如果没有找到匹配的值,则执行语句n,结束。default后可以不写break。

2.5.3. switch-case语句用于分支

在实际应用中,switch-case语句常常与break配合使用,参见下面的代码:

  1. int num = 2;
  2. switch(num) {
  3.      case 1:
  4.     System.out.println(“呼叫教学部”);
  5.     break;
  6.     case 2:
  7.     System.out.println(“呼叫人事部”);
  8.     break;
  9.     default:
  10.     System.out.println(“人工服务”);
  11. }

上面代码的输出结果为“呼叫人事部“,因为匹配case 2输出后,即break跳出switch语句了。

2.5.4. switch-case的优势

switch-case结构在实际应用中较广泛, 常常和break语句结合使用实现分支的功能。

在很多情况下,switch-case可以代替else if结构,而switch-case实现分支功能的效率要高于else if结构,并且结构更清晰,所以推荐使用。从JDK 7.0开始,switch-case可以支持字符串表达式,将更加方便程序的操作。

 

以上是关于运算符和表达式-2 与分支结构的主要内容,如果未能解决你的问题,请参考以下文章

运算符与分支结构

分支控制

C#中的分支结构与循环

java基础知识-----运算符表达式和分支结构

实验四——多分支结构及本章总结

分支结构