第二章 Java流程控制

1.程序流程控制

        流程控制语句是用来控制程序中各语句执行的顺序,可以把语句组合成能完成一定功能的逻辑模块;流程控制采用了结构化程序设计中规定的三种基本流程。

顺序结构

        程序从上到下逐步执行,中间无任何跳转和判断。

分支结构

        根据条件,选择性执行某段代码;有if...else和switch-case两种分支语句。

循环结构

        根据循环条件,重复性的执行某段代码;有while、do...while和for三种循环;JDK1.5之后添加了foreach循环,方便遍历集合、数组元素。

2.顺序结构

        Java中定义成员变量时采用合法的前向引用。

public class Test{
    // 顺序执行,先赋值,后计算num2的值
    int num1 = 12;
    int num2 = num1 + 4;
}

3.分支结构

3.1.if-else分支结构的方式

// if结构
if(条件表达式){
    语句块;
}

// if-else结构
if(条件表达式){
    语句块1;
}else{
    语句块2;
}

// 多条件if-else if语句
if(表达式1){
    语句1;
}else if(表达式2){
    语句2;
}else if(表达式3){
    语句3
}else{
    语句n;
}

// 嵌套if结构
if(条件表达式){
    if(条件表达式){
        语句块;
    }
}else{
    语句块2;
}

3.2.if-else使用说明

        条件表达式必须是布尔表达式(关系表达式或逻辑表达式)、布尔变量;语句块只有一条执行语句时,一对{}可以省略,但建议保留;if-else语句结构,根据需要可以嵌套使用;当if-else结构是“多选一”时,最后的else是可选的,根据需要可以省略。

public static void main(String[] args) {
		int heartBeat = 79;// 健康
		int score = 88;// 成绩
		
		if(score > 80){
			System.out.println("优秀");
		}
		
		if(heartBeat < 60){
			System.out.println("进一步检查");
		}else if(heartBeat > 100){
			System.out.println("尽快去检查");
		}else {
			System.out.println("检查结束");
		}
	}

        如果多条件表达式之间是”互斥“(或没有交集的关系),那么各判断执行语句声明上下顺序无所谓; 如果多条件表达式之间有交集关系,需要根据实际情况,考虑各结构声明在上下顺序;如果多条件表达式之间有包含的关系,就需将范围小的声明在范围大的上面,否则范围小的就没机会执行。

    // if的条件有交集,范围小的在上方
	public static void main(String[] args) {
		Scanner input =  new Scanner(System.in);
		System.out.println("请输入小鹏成绩:(0-100)");
		double sorce = input.nextDouble();
		if(sorce == 100.0){
			System.out.println("奖励一辆BWM");
		}else if(sorce >= 80){
			System.out.println("奖励一台iphone");
		}else if(sorce >= 60){
			System.out.println("奖励一个iPad");
		}else{
			System.out.println("没有奖励");
		}
	}

public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("请输入年份:");
        int year = input.nextInt();
        if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0){
            System.out.println(year + "是闰年");
        }else {
            System.out.println(year + "不是闰年");
        }
        System.out.print("请输入成绩:");
        double score = input.nextDouble();
        if (score >= 90 && score <= 100){
            System.out.print("A");
        } else if (score >= 80) {
            System.out.print("B");
        } else if (score >= 70) {
            System.out.print("C");
        } else if (score >= 60) {
            System.out.print("D");
        } else {
            System.out.print("E");
        }
    }

        if-else结构可以嵌套使用;if-else结构只有一条可以省略括号。

// if-else结构嵌套使用把三个数按从大到小排序
public class IfTest02 {
	public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.println("请输入三个整数:");
		int num1 = input.nextInt(), num2 = input.nextInt(), num3 = input.nextInt();
		int temp;
		if(num1 >= num2){
			if(num3 >= num1){
				System.out.println(num3+","+num1+","+num2);
			}else if(num3 <= num2){
				System.out.println(num1+","+num2+","+num3);
			}else {
				System.out.println(num1+","+num3+","+num2);
			}
		}else {
			if(num3 >= num2){
				System.out.println(num3+","+num2+","+num1);
			}else if(num3 <= num1){
				System.out.println(num2+","+num1+","+num3);
			}else {
				System.out.println(num2+","+num3+","+num1);
			}
		}		
	}

3.3.Scanner和Random

        从键盘获取不同类型的变量,需要使用Scanner类,使用步骤如下:

        导包:impot java.util.scanner;
        Scanner的实例化:Scanner scan = new Scanner(System.in);
        获得键盘输入的数据(int now  =  input.newtInt();(String next()获得一个字符串;int nextInt()获得一个整型数值),来获取指定类型的变量。
         注意:需要根据相应的方法,来输入指定类型的值,如果输入的数据类型与要求的类型不匹配时,会报异常:InputMisMatchExcetion导致程序终止。

package com.dhangguogu.test;
//1.导包:import java.util.Scanner;
import java.util.Scanner;

public class ScannerTest {

	public static void main(String[] args) {
		// 2.Scanner的实例化
		Scanner input = new Scanner(System.in);
		// 3.调用Scanner类的相关方法
		System.out.println("输入你的名字:");
		String name = input.next();// 获取String类型的字符串
		System.out.println("请入你的年龄:");
		int age = input.nextInt();// 获取int类型的整数
		System.out.println("请入你的体重:");
		double weight = input.nextDouble();// 获取double类型的浮点数
		System.out.println("请入你的是否看中我(false/true):");
		boolean blean = input.nextBoolean();// 获取boolean值
		System.out.println("名字:" + name + "\t年龄:" + age + "\t体重:" + weight + "\t看中:" + blean);
		// 对于char型的获取,Scanner没有提供相关的方法。只能获取一个字符串
		System.out.println("请输入你的性别:(男/女)");
		String gender = input.next();// "男"
		char genderChar = gender.charAt(0);// 获取gender索引为0位置上的字符
		System.out.println(genderChar);
	}
}

        需要获取随机数使用Random类。
        获取[a,b]区间的随机整数公式:(int)(Math.random() *  (b - a + 1) + a)。

public static void main(String[] args) {
		//获取一个随机数:10-99
		int value = (int)(Math.random()*90 + 10);//[0.0,1.0]-->[0.0,90]-->[10-99]
		System.out.println(value);
		//公式随机数区间:[a,b]:(int)(Math.random() * (b - a + 1) + a)
	}

3.4.Switch-case分支结构

switch(表达式){
 case 常量1:
        执行语句1;
        //break;
  case 常量2:
         执行语句2;
         //break;
  ...
 case 常量n:
         执行语句n;
         //break;
  default:
       语句:
        //break;
 }

3.4.1.Switch-case结构相关规则

        switch(表达式)中表达式的值必须是下述几种类型之一:byte,short,char,int,枚举 (jdk 5.0),String (jdk 7.0);case子句中的值必须是常量,不能是变量名或不确定的表达式值;同一个switch语句,所有case子句中的常量值互不相同;break语句用来在执行完一个case分支后使程序跳出switch语句块;如果没有break,程序会顺序执行到switch结尾;default子句是可任选的。同时,位置也是灵活的。当没有匹配的case时,执行default。

public static void main(String[] args) {
		String season = "summer";
		switch (season) {
		case "spring":
			System.out.println("春暖花开");
			break;
		case "summer":
			System.out.println("夏日炎炎");
			break;
		case "autumn":
			System.out.println("秋高气爽");
			break;
		case "winter":
			System.out.println("白雪皑皑");
			break;
		default:
			System.out.println("输入有误");
			break;
		}
	}

        根据switch表达式中的值,依次匹配各个case中的常量。一旦匹配成功,则进入相应的case结构中,调用其执行语句;当调用完执行语句以后,则仍然继续向下执行其他case结构中的执行语句,直遇到break关键字或此switch-case结构末尾为止结束。

// 输入年、月、日,判断是当年第几天
public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.println("请输入年份");
		int year = input.nextInt();
		System.out.println("请输入月份");
		int month = input.nextInt();
		System.out.println("请输入日期");
		int day = input.nextInt();
		int sumDays = 0;
		switch (month) {
		case 12:
			sumDays += 30;
		case 11:
			sumDays += 31;
		case 10:
			sumDays += 30;
		case 9:
			sumDays += 31;
		case 8:
			sumDays += 31;
		case 7:
			sumDays += 30;
		case 6:
			sumDays += 31;
		case 5:
			sumDays += 30;
		case 4:
			sumDays += 31;
		case 3:
			//sumDays += 28;
			if((year % 4 == 0 && year % 100 != 0)||year % 400 == 0){
				sumDays += 29;
			}else {
				sumDays += 28;
			}
		case 2:
			sumDays += 31;
		case 1:
			sumDays += day;
		}
		System.out.println(year+"年"+month+"月"+day+"日是第"+sumDays+"天");
	}

3.5.if-else和switch-case比较

        凡是使用switch-case的结构,都可以转化为if-else。反之,不成立;我们写分支结构时,既可以使用switch-case(switch的取值较少),又可以使用if-else时,优先选择使用switch-case,执行效率稍高。
        相同点:都能处理多分支条件的结构。
        不同点:switch结构只能处理等值条件的判断,多重if结构适合变量处于某个连续区间的情况,判断条件是离散值,用switch。如果判断分支多,用switch。否则用if - else if。

/*
根据出生日期计算星座。
白羊:0321~0420 天秤:0924~1023
金牛:0421~0521 天蝎:1024~1122
双子:0522~0621 射手:1123~1221
巨蟹:0622~0722 摩羯:1222~0120
狮子:0723~0823 水瓶:0121~0219
处女:0824~0923 双⻥:0220~0320
例如:出生日期:0609(6月9日),则对应的是双子座。
铺垫:一个四位数,怎么求出前两位和后两位。
/100结果就是前两位,%100结果就是后两位。
*/
public static void main(String[] args) {
    System.out.println("请输入您的出生日期(如0123表示1月23日)");
    Scanner sc = new Scanner(System.in);
    int monthday = sc.nextInt();//0123
    int month = monthday/100;//月份
    int day = monthday%100;//日期
    String xingzuo = "";
    switch (month) {
        case 1:
            xingzuo = day < 21 ?"摩羯座" : "水瓶座";
            break;
        case 2:
            xingzuo = day < 20 ?"水平座" : "双⻥座";
            break;
        case 3:
            xingzuo = day < 21 ?"双⻥座" : "白羊座";
            break;
        case 4:
            xingzuo = day < 21 ?"白羊座" : "金牛座";
            break;
        case 5:
            xingzuo = day < 22 ?"金牛座" : "双子座";
            break;
        case 6:
            xingzuo = day < 22 ?"双子座" : "巨蟹座";
            break;
        case 7:
            xingzuo = day < 23 ?"巨蟹座" : "狮子座";
            break;
        case 8:
            xingzuo = day < 24 ?"狮子座" : "处女座";
            break;
        case 9:
            xingzuo = day < 24 ?"处女座" : "天秤座";
            break;
        case 10:
            xingzuo = day < 24 ?"天秤座" : "天蝎座";
            break;
        case 11:
            xingzuo = day < 23 ?"天蝎座" : "射手座";
            break;
        case 12:
            xingzuo = day < 22 ?"射手座" : "摩羯座";
            break;
        default:
            break;
}

4.循环结构

        在某些条件满足的情况下,反复执行特定代码的功能。
        循环语句分为:for循环、while循环和do-while循环。
        循环语句有四部分组成:初始化部分、循环条件部分、循环体部分和迭代部分。

4.1.for循环

for(①初始化条件;②循环条件;④迭代条件){
       ③循环体
}

        ①初始化条件;②循环条件;③循环体;④迭代条件。

         执行过程:①-②-③-④-②-③-④-...-②

说明:
        ②循环条件为boolean类型表达式,值为false时,退出循环;

        ①初始化部分可以声明多个变量,但变量的类型必须一样,用逗号隔开;

        ④可以有多个变量更新,用逗号隔开。

public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.println("请输入m");
		int m = input.nextInt();
		System.out.println("请输入n");
		int n = input.nextInt();
		int min = (m <= n)? m : n;
		for(int i = min;i >= 1;i--){
			if(m % i == 0 && n % i == 0){
				System.out.println("最大公约数:"+i);
				break;
			}
		}
		int max = (n >= m)? n : m;
		for(int i = max;i <= m*n;i++){
			if(i % m == 0 && i % n == 0){
				System.out.println("最小公倍数:"+i);
				break;
			}
		}
	}

4.2.while循环

①初始化条件
while(②循环条件){
      ③循环体;
      ④迭代条件;
}

        ①初始化条件;②循环条件;③循环体;④迭代条件。
        执行过程:①-②-③-④-②-③-④-...-②
说明:

        写while循环不要少了迭代条件。否则,循环不能结束,变成死循环;

        for循环和while循环可以相互转换。
区别:

        for和while循环的初始化条件部分的作用范围不同。

        public static void main(String[] args) {
		// 1-100的和
		int sum = 0, i = 0;
		while (i <= 100) {
			sum += i;
			i++;
		}
		System.out.println("sum = " + sum);
		// while练习
		Scanner input = new Scanner(System.in);
		System.out.print("合格了吗?(y/n)");
		String anString = input.next();
		while (!"y".equals(anString)) {
			System.out.println("需要重新开始");
			System.out.print("合格了吗?(y/n)");
			anString = input.next();
		}
		System.out.println("完成任务");
	}

4.3.do-while循环的使用

  ①初始化条件
  do{
       ③循环体部分;
       ④迭代部分;
}while(②循环条件);

        ①初始化条件;②循环条件;③循环体;④迭代条件
        执行过程:①-③-④-②-③-④-...-②
        说明:先执行一遍循环操作,在判断循环条件是否满足,满足则继续执行,否则循环结束,注意:循环条件后括号后的分号不可少;开发中,较多使用for和while。

   public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		String anString = "";
		do{
			System.out.println("你测试了吗");
			System.out.print("合格了吗?(y/n)");
			anString = input.next();
		}while (!"y".equals(anString));
		System.out.println("恭喜,你测试通过了");
	}

          while和do-while循环的区别:执行顺序不同;初始情况不满足循环条件时,while循环一次都不执行,do-while循环不管任何情况都至少执行一次。
        for循环和while循环、do-while循环的区别:执行顺序:while循环先判断后执行,do-while循环先执行后判断,for循环先判断在执行。适用情况:循环次数确定的情况,通常选用for循环,循环次数不确定的情况,通常选用do-while循环和while循环

    //求平均分
    public static void main(String[] args) {
		Scanner input = new Scanner(System.in);
		System.out.print("请输入姓名:");
		String name = input.next();
		double sum = 0;
		for (int i = 0; i < 5; i++) {
			System.out.print("请输入第" + (i + 1) + "门成绩:");
			double score = input.nextDouble();
			sum += score;
		}
		System.out.println(name + "的平均成绩为: " + (sum / 5));
	}
// 增强for循环
// 语法
for(类型 变量名 : 集合){
    语句块;
}
// 例如
int[] nums = {43,32,53,54,75};//整型数组
    for(int n : nums) {
        System.out.println(n);
    }

4.4.嵌套循环的使用

        将一个循环放在另一个循环体内,构成了嵌套循环。其中,for ,while ,do...while均可以作为外层循环或内层循环,嵌套循环就是把内层循环当成外层循环的循环体。
        当内层循环的循环条件为false时,才会跳出内层循环,结束外层的当次循环。内层循环遍历一遍,只相当于外层循环体执行了一次;外层循环循环m次,内层循环n次,总共执行了m*n次;外层控制行数,内存控制列数

public static void main(String[] args) {
		// 100以内的素数
		for(int i = 2;i <= 100;i++){
			for(int j = 2;j < i;j++){
				 if(i % j == 0){
					 isFlag = false;
				 }
			}
			if(isFlag == true){
				System.out.print(i+"\t");
			}
			isFlag = true;
		}
		System.out.println();
		//获取当前时间距离1970-01-01 00:00:00 的毫秒数
		long start = System.currentTimeMillis();
		for(int i = 2;i <= 100;i++){
			for(int j = 2;j <= Math.sqrt(i);j++){//优化:开方,对本身是指数的自然数
				 if(i % j == 0){
					 isFlag = false;
					 break;//优化:只对本身非直属的自然数
				 }
			}
			if(isFlag == true){
				System.out.print(i + "\t");
			}
			isFlag = true;
		}
		//获取当前时间距离1970-01-01 00:00:00 的毫秒数
		long end = System.currentTimeMillis();
		System.out.println("花费时间:"+(end - start));
		
		System.out.println("-------------------");
		//获取当前时间距离1970-01-01 00:00:00 的毫秒数
				long start1 = System.currentTimeMillis();
				lebel:for(int i = 2;i <= 100;i++){
					for(int j = 2;j <= Math.sqrt(i);j++){//优化:开方,对本身是指数的自然数
						 if(i % j == 0){
							 continue lebel;
						 }
					}
					System.out.print(i + "\t");
				}
				//获取当前时间距离1970-01-01 00:00:00 的毫秒数
				long end1 = System.currentTimeMillis();
				System.out.println("花费时间:"+(end1 - start1));
	}

①引入:一共有三个班,求没个班四名同学的平均分,要求学生成绩从键盘输入。

for (int j = 0; j < 3; j++) {
    System.out.println("请输入 " + (j + 1) + "班的学生成绩:");
    //输入每个班的学生成绩
    double sum = 0.0;
    double socre = 0.0;
    Scanner sc = new Scanner(System.in);
    for (int i = 0; i < 4; i++) {
        System.out.println("请输入第" + (i +1) + "名同学的成绩:");
        socre = sc.nextDouble();
        sum = sum + socre;
    }
    System.out.println("平均分:" + sum / 4);
}

②执行过程:外层循环执行一次,内存循环执行一轮

public static void main(String[] args) {
    for (int j = 0; j < 3; j++) {//外层
        System.out.println("外。。。层循环执行!");
        for (int i = 0; i < 4; i++) {//内层循环
            System.out.println("内层循环执行!");
        }
    }
}

③打印图像:外层循环控制行号,内层循环控制每一行的具体实现。请打印一个菱形:

public static void main(String[] args) {
    //正立的等腰三⻆形
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 3-i; j++) {//打印空格
            System.out.print(" ");
        }
        for (int j = 0; j < 2* i +1; j++) {//打印
            System.out.print("*");
        }
        System.out.println();
    }
    //倒立的等腰三⻆形
    for (int i = 2; i >=0; i--) {
        for (int j = 0; j < 3-i; j++) {//打印空格
            System.out.print(" ");
        }
        for (int j = 0; j < 2* i +1; j++) {//打印
            System.out.print("*");
        }
        System.out.println();
    }
}

④打印九九乘法表、杨辉三角和百元百鸡:

    // 九九乘法表
	public static void main(String[] args) {
		for (int i = 1; i <= 9; i++) {
			for (int j = 1; j <= i; j++) {
				System.out.print(j + "*" + i + "=" + (i * j) + "\t");
			}
			System.out.println();
		}
	}
// 打印杨辉三⻆
/*
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
*/
public static int num(int x,int y) {
    if (y ==1 || y ==x ) {
        return 1;
    }
    int c = num(x-1,y-1) + num(x-1,y);
    return c;
}
public static void main(String[] args) {
    for (int i = 1; i <= 7; i++) {
        for (int j = 0; j < 6-i; j++) {//打印空格
            System.out.print(" ");
        }
        for (int j = 1; j <= i ; j++) {//打印
            System.out.print(num(i,j) + " ");
        }
        System.out.println();
    }
}
    /*
 * 100元买100只鸡,公鸡5元每只,母鸡3元每只,小鸡1元3只
 * 有多少方案
 */
public class BaiDemo {
	public static void main(String[] args) {
		int mj, gj, xj;
		for (gj = 0; gj <= 20; gj++) {
			for (mj = 0; mj <= 33; mj++) {
				for (xj = 0; xj <= 100; xj++) {
					if ((gj * 5 + mj * 3 + xj / 3 == 100) && (mj + gj + xj == 100) && (xj % 3 == 0)) {
						System.out.println("公鸡" + gj + "只,母鸡" + mj + "只,小鸡" + xj + "只");
					}
				}
			}
		}
	}

4.5.for和while说明

        不在循环条件部分限制次数的结构:for(;;)或while(true)
        结束循环的方式:方式一:循环条件部分返回false;方式二:在循环体中,执行break。

Scanner input = new Scanner(System.in);
int count1 = 0,count2 = 0;
while(true){
	int number = input.nextInt();
	if(number > 0){
		count1++;
	}else if(number < 0){
		count2++;
	}else {
		break;
	}
}
System.out.println(count1);
System.out.println(count2);

5.特殊流程控制语句

5.1.break和continue

        break语句用于终止某个语句块的执行;break语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块。

// 结束代码块
{ ......
    break;
    ......
}

// 结束某个循环
label1: { ......
    label2: { ......
        label3: { ......
            break label2;// 结束label2语句块
            ......
        }
    }
}

        continue只能使用在循环结构中;用于跳过其所在循环语句块的一次执行,继续下一次循环;出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环。

public static void main(String[] args) {
		 for(int i = 1;i < 10;i++){
			 if(i % 4 == 0){
				// break;//123
				 continue;//12356789
			 }
			 System.out.println(i);
		 }
		 System.out.println("-------------");
		 laber:for(int i = 1;i <= 4;i++){
			 for(int j = 1;j <= 10;j++){
				 if(j % 4 == 0){
					 //break;//默认跳出包裹此关键字最近的一层循环
					 //break laber;// 输出123,程序结束,结束指定标识的for循环结构
					 System.out.println();
					 continue laber;// 输出123123123,结束指定标示的一层循环结构档次循环
				 }
				System.out.print(j);
			 }	 
		 }
	}

        continue和break的对比,使用场合:break可用于switch结构和循环结构中,continue只能用于循环结构中。作用(循环结构中):break语句终止某个循环,程序跳转到循环块外的下一条语句,continue跳出本次循环,进入下一次循环。
        二重循环里的break和continue:在二重循环中,如果break加在了内层循环,只会对内层循环起作用,不会影响外层循环;如果break加在外层循环中,在条件触及时,会终止内外循环;如果continue加在内层循环,只对内层起作用。

5.2.return

        return并非专门用于结束循环的,它的功能是结束一个方法;当一个方法执行到一个return语句时,这个方法将被结束。与break和continue不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。

5.3.特殊流程控制语句的说明

名称不同点相同点
break只能用于switch语句和循环语句,终止本层循环break、continue之后不能有其他的语句,因为程序永远不会执行其后的语句。标号语句必须紧接在循环的头部,标号语句不能用在非循环语句的前面。
continue只能用于循环语句中,只能终止本次循环

        很多语言都有goto语句,goto语句可以随意将控制转移到程序中的任意一条语句上,然后执行它。

6.综合练习

        需求说明:模拟实现基于文本界面的《家庭记账软件》;该软件能够记录家庭的收入、支出,并能够打印收支明细表;项目采用分级菜单方式。主菜单如下:

        假设家庭起始的生活基本金为10000元;每次登记收入(菜单2)后,收入的金额应累加到基本金上,并记录本次收入明细,以便后续的查询;每次登记支出(菜单3)后,支出的金额应从基本金中扣除,并记录本次支出明细,以便后续的查询;查询收支明细( 菜单1)时,将显示所有的收入、支出名细列表;“登记收入”的界面及操作过程如下所示:

        “登记支出”的界面及操作过程如下所示:

        “收支明细”的界面及操作过程如下所示:

        提示:明细表格的对齐,可以简单使用制表符‘\t’来实现;“退 出”的界面及操作过程如下所示:

        基本金和收支明细的记录:基本金的记录可以使用int类型的变量来实现:int balance = 10000;收支明细记录可以使用Sting类型的变量来实现,其初始值为明细表的表头。例如:String details = "收支\t账户金额\t收支金额\t说 明\n";在登记收支时,将收支金额与balance相加或相减,收支记录直接串接到details后面即可。
6.1.工具类

package com.shangguigu.project;
import java.util.Scanner;
/**
 * Utility工具类: 将不同的功能封装为方法,就是可以直接通过调用方法使用它的功能,而无需考虑具体的功能实现细节。
 */
public class Utility {
	private static Scanner scanner = new Scanner(System.in);
	/**
	 * 用于界面菜单的选择。该方法读取键盘,如果用户键入’1’-’4’中的任意字符,则方法返回。返回值为用户键入字符。
	 */
	public static char readMenuSelection() {
		char c;
		for (;;) {
			String str = readKeyBoard(1);
			c = str.charAt(0);
			if (c != '1' && c != '2' && c != '3' && c != '4') {
				System.out.print("选择错误,请重新输入:");
			} else
				break;
		}
		return c;
	}
	/**
	 * 用于收入和支出金额的输入。该方法从键盘读取一个不超过4位长度的整数,并将其作为方法的返回值。
	 */
	public static int readNumber() {
		int n;
		for (;;) {
			String str = readKeyBoard(4);
			try {
				n = Integer.parseInt(str);
				break;
			} catch (NumberFormatException e) {
				System.out.print("数字输入错误,请重新输入:");
			}
		}
		return n;
	}
	/**
	 * 用于收入和支出说明的输入。该方法从键盘读取一个不超过8位长度的字符串,并将其作为方法的返回值。
	 */
	public static String readString() {
		String str = readKeyBoard(8);
		return str;
	}

	/**
	 * 用于确认选择的输入。该方法从键盘读取‘Y’或’N’,并将其作为方法的返回值。
	 */
	public static char readConfirmSelection() {
		char c;
		for (;;) {
			String str = readKeyBoard(1).toUpperCase();
			c = str.charAt(0);
			if (c == 'Y' || c == 'N') {
				break;
			} else {
				System.out.print("选择错误,请重新输入:");
			}
		}
		return c;
	}
	private static String readKeyBoard(int limit) {
		String line = "";
		while (scanner.hasNext()) {
			line = scanner.nextLine();
			if (line.length() < 1 || line.length() > limit) {
				System.out.print("输入长度(不大于" + limit + ")错误,请重新输入:");
				continue;
			}
			break;
		}
		return line;
	}
}

6.2.实现类

package com.shangguigu.project;

public class FamilyAccount {

	public static void main(String[] args) {
        String details = "收支\t账户金额\t收支金额\t说    明\n";
        int balance = 10000;

        boolean loopFlag = true;
        do {
		    System.out.println("\n-----------------家庭收支记账软件-----------------\n");
            System.out.println("                   1 收支明细");
            System.out.println("                   2 登记收入");
            System.out.println("                   3 登记支出");
            System.out.println("                   4 退    出\n");
            System.out.print("                   请选择(1-4):"); 
            char key = Utility.readMenuSelection();
            System.out.println();
            switch (key) {
                case '1':
                    System.out.println("-----------------当前收支明细记录-----------------");
                    System.out.println(details);
                    System.out.println("--------------------------------------------------");
                    break;
                case '2':
                    System.out.print("本次收入金额:");
                    int amount1 = Utility.readNumber();
                    System.out.print("本次收入说明:");
                    String desc1 = Utility.readString();
                    balance += amount1;
                    details += "收入\t" + balance + "\t" +
                               amount1 + "\t" + desc1 + "\n";
                    System.out.println("---------------------登记完成---------------------");
                    break;
                case '3':
                    System.out.print("本次支出金额:");
                    int amount2 = Utility.readNumber();
                    System.out.print("本次支出说明:");
                    String desc2 = Utility.readString();

                    balance -= amount2;
                    details += "支出\t" + balance + "\t" +
                               amount2 + "\t" + desc2 + "\n";
                    System.out.println("---------------------登记完成---------------------");
                    break;
                case '4':
                    System.out.print("确认是否退出(Y/N):");
                    char yn = Utility.readConfirmSelection();
                    if (yn == 'Y') loopFlag = false;
                    break;
            }
        } while (loopFlag);
	}    
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值