day05流程控制学习笔记
1.流程控制小练习
1.1改写语句
/*
使用switch语句改写下列if语句:
int a = 3;
int x = 100;
if(a==1)
x+=5;
else if(a==2)
x+=10;
else if(a==3)
x+=16;
else
x+=34;
*/
class Exam{
public static void main(String[] args){
int a = 3;
int x = 100;
switch(a){
case 1 : //不等同于case '1':
x += 5;
break;
case 2:
x += 10;
break;
case 3:
x += 16;
break;
default:
x += 34;
//break;
}
}
}
1.2 if语句练习
/*
编写程序从1循环到150,并在每行打印一个值,
另外在每个3的倍数行上打印出“foo”,
在每个5的倍数行上打印“biz”,
在每个7的倍数行上打印输出“baz”。
*/
class ForExer {
public static void main(String[] args) {
for(int i = 1;i <= 150;i++){
System.out.print(i + "\t");
if(i % 3 == 0){
System.out.print("foo" + '\t');
}
if(i % 5 == 0){
System.out.print("biz" + '\t');
}
if(i % 7 == 0){
System.out.print("baz" + '\t');
}
System.out.println();//换行
}
}
}
2.for(;;)或while(true)
/*
题目:
从键盘读入个数不确定的整数,并判断读入的正数和负数的个数,输入为0时结束程序。
说明:关于while(true) 或 for(;;)结构的使用
程序中要避免出现死循环!
如果程序中出现了循环结构,但是又没法确定循环的次数时,可以考虑使用上述结构。
只要使用上述结构,就需要通过break的方式结束循环。
*/
import java.util.Scanner;
class ForWhileTest{
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int positiveNumber = 0;//记录正数的个数
int negativeNumber = 0;//记录负数的个数
while(true){//for(;;){
System.out.println("请输入一个整数:");
int num = scan.nextInt();
if(num == 0){
break;
}else if(num > 0){
positiveNumber++;
}else{ //num < 0
negativeNumber++;
}
}
System.out.println("正数的个数为:" + positiveNumber);
System.out.println("负数的个数为:" + negativeNumber);
}
}
如果我们在开发中使用循环结构时,如果不确定循环的次数。则可以使用如下的结构:
方式一:for(;;){} 或 while(true),同时在内部使用break
方式二:
boolean isFlag = true;
while(isFlag){
if(...){
isFlag = false;
}
}
3.嵌套循环
- 将一个循环结构1声明在另一个循环结构2中,就构成了嵌套循环
循环结构1:内层循环
循环结构2:外层循环
- 如果外层循环执行m次,内层循环执行n次,则程序一共需要执行 m * n次
-
- 技巧:外层循环控制行数,内层循环控制列数
/*
**********
**********
**********
**********
**********
*/
for(int j = 1;j <= 5;j++){ //外层循环
for(int i = 1;i <= 10;i++){//内层循环
System.out.print("*");
}
System.out.println();
}
/*
i j的最大值 j的最大值 == i
* 1 1
** 2 2
*** 3 3
**** 4 4
***** 5 5
****** 6 6
*/
for(int i = 1;i <= 6;i++){
for(int j = 1;j <= i;j++){
System.out.print("*");
}
System.out.println();
}
/*
i j的最大值 j的最大值 == 6 - i
***** 1 5
**** 2 4
*** 3 3
** 4 2
* 5 1
*/
for(int i = 1;i <= 5;i++){
for(int j = 1;j <= 6 - i ;j++){
System.out.print("*");
}
System.out.println();
}
/*
----*
---* *
--* * *
-* * * *
* * * * *
* * * *
* * *
* *
*
*/
//上半部分
for(int i = 1;i <= 5;i++){
//输出-
for(int j = 1;j <= 5 - i;j++){
System.out.print(" ");
}
//输出*
for(int j = 1;j <= i;j++){
System.out.print("* ");
}
System.out.println();
}
开发中,如果使用嵌套循环(或多重循环)的话,一般就两层循环。通常超不过三层。
3.1嵌套循环的练习——九九乘法表
/*
嵌套循环的练习:九九乘法表
1 * 1 = 1
2 * 1 = 2 2 * 2 = 4
...
9 * 1 = 9 ... 9 * 9 = 81
*/
class NinetyNineMultiplicationTables {
public static void main(String[] args) {
for(int i = 1;i <= 9;i++){
for(int j = 1;j <= i;j++){
System.out.print(i + " * " + j + " = " + i * j + "\t");
}
System.out.println();
}
}
}
3.2 打印『X』对称图形
- 开发提示:平面图形涉及到有行有列,考虑到嵌套for循环
- 一个外循环控制行,一个内循环控制输出内容
- 在内循环中,根据变量的变化规律,判断输出"O"还是"*"
public class Test15 {
public static void main(String[] args){
for(int i=1; i<=7; i++){//控制行数
//(1)打印该行的*或o
/*
发现O+*的总个数是7个
当i=1, 当j=1和j=7的时候是O,其余的是*
当i=2, 当j=2和j=6的时候是O,其余的是*
当i=3, 当j=3和j=5的时候是O,其余的是*
当i=4, 当j=4的时候是O,其余的是*
当i=5, 当j=5和j=3的时候是O,其余的是*
当i=6, 当j=6和j=2的时候是O,其余的是*
当i=7, 当j=7和j=1的时候是O,其余的是*
*/
for(int j=1; j<=7; j++){
if(i==j || i==8-j){
System.out.print("O");
}else{
System.out.print("*");
}
}
//(2)每一行的最后一件事是换行
System.out.println();
}
}
}
3.3 打印菱形
- 开发提示:
- 平面图形涉及到有行有列,考虑到嵌套for循环
- 一个外循环控制行,两个内循环控制输出内容
- 一个内循环负责输出空格,另一个内循环输出"*"
public class Test16{
public static void main(String[] args){
//上半部分:正的等腰三角形
//5行
for(int i=1; i<=5; i++){
//(1)打印空格
/*
当i=1,打印4个空格,j=4,3,2,1 j>=i
当i=2,打印3个空格,j=4,3,2
当i=3,打印2个空格,j=4,3
当i=4,打印1个空格,j=4
当i=5,打印0个空格,j=4,让循环条件一次都不满足
*/
for(int j=4; j>=i; j--){
System.out.print(" ");
}
//(2)打印*
/*
当i=1,打印1个,j=1 j<=2*i-1
当i=2,打印3个,j=1,2,3,
当i=3,打印5个,j=1,2,3,4,5
当i=4,打印7个,j=1,2,3,4,5,6,7
当i=5,打印9个,j=1,2,3,4,5,6,7,8,9
*/
for(int j=1; j<=2*i-1; j++){
System.out.print("* ");
}
//(3)换行
System.out.println();
}
//下半部分:倒立的等腰三角形
//4行
for(int i=1; i<=4; i++){
//(1)打印空格
/*
当i=1,1个空格,j=1 j<=i
当i=2,2个空格,j=1,2
当i=3,3个空格,j=1,2,3
当i=4,4个空格,j=1,2,3,4
*/
for(int j=1; j<=i; j++){
System.out.print(" ");
}
//(2)打印*
/*
当i=1,7个*,j=1,2,3,4,5,6,7 j<=9-2*i;
当i=2,5个*,j=1,2,3,4,5
当i=3,3个*,j=1,2,3
当i=4,1个*,j=1
*/
for(int j=1; j<=9-2*i; j++){
System.out.print("* ");
}
//(3)换行
System.out.println();
}
}
}
public class Test16 {
public static void main(String[] args){
//上半部分:正的等腰三角形
//5行
for(int i=1; i<=5; i++){
//(1)打印空格
/*
当i=1,打印4个空格,j=4,3,2,1 j>=i
当i=2,打印3个空格,j=4,3,2
当i=3,打印2个空格,j=4,3
当i=4,打印1个空格,j=4
当i=5,打印0个空格,j=4,让循环条件一次都不满足
*/
for(int j=4; j>=i; j--){
System.out.print(" ");
}
//(2)打印*
/*
当i=1,打印1个,j=1 j<=2*i-1
当i=2,打印3个,j=1,2,3,
当i=3,打印5个,j=1,2,3,4,5
当i=4,打印7个,j=1,2,3,4,5,6,7
当i=5,打印9个,j=1,2,3,4,5,6,7,8,9
*/
for(int j=1; j<=2*i-1; j++){
//不是全部打印*
if(j==1 || j==2*i-1){
System.out.print("* ");
}else{
System.out.print(" ");
}
}
//(3)换行
System.out.println();
}
//下半部分:倒立的等腰三角形
//4行
for(int i=1; i<=4; i++){
//(1)打印空格
/*
当i=1,1个空格,j=1 j<=i
当i=2,2个空格,j=1,2
当i=3,3个空格,j=1,2,3
当i=4,4个空格,j=1,2,3,4
*/
for(int j=1; j<=i; j++){
System.out.print(" ");
}
//(2)打印*
/*
当i=1,7个*,j=1,2,3,4,5,6,7 j<=9-2*i;
当i=2,5个*,j=1,2,3,4,5
当i=3,3个*,j=1,2,3
当i=4,1个*,j=1
*/
for(int j=1; j<=9-2*i; j++){
//不是全部打印*
if(j==1 || j==9-2*i){
System.out.print("* ");
}else{
System.out.print(" ");
}
}
//(3)换行
System.out.println();
}
}
}
4.质数的输出
- 优化前
/*
题目:100以内质数的输出
质数:素数,只能被1和它本身整除的自然数。 最小的质数是2
--> 意味着:从2开始到这个数-1为止,这个范围内的数都不能被此整除n的话,则此整数n是一个质数
说明:通过此题目,体会不同的算法实现的效率的差别!
*/
class PrimeNumberTest {
public static void main(String[] args) {
//获取系统当前的时间
long start = System.currentTimeMillis();
int count = 0;//记录质数的个数
boolean isFlag = false;//标识,用于记录i是否被j除尽
for(int i = 2;i <= 100000;i++){//判断i是否是质数
//boolean isFlag = false;
for(int j = 2;j < i;j++){ //遍历2 到 i-1 范围的自然数
if(i % j == 0){
isFlag = true;
}
}
//判断此标识是否被更改过
if(!isFlag){//if(isFlag == false){
//System.out.println(i);
count++;
}
//重置isFlag
isFlag = false;
}
//获取系统当前的时间
long end = System.currentTimeMillis();
//System.out.println(start);
//System.out.println(end);
System.out.println("花费的时间为:" + (end - start)); //遍历到100000:14894
System.out.println("质数的个数为:" + count);
}
}
- 优化方式一
/*
题目:100以内质数的输出的算法优化
方式一:
*/
class PrimeNumberTest1 {
public static void main(String[] args) {
//获取系统当前的时间
long start = System.currentTimeMillis();
int count = 0;//记录质数的个数
boolean isFlag = false;//标识,用于记录i是否被j除尽
for(int i = 2;i <= 100000;i++){//判断i是否是质数
for(int j = 2;j <= Math.sqrt(i);j++){ //优化二:遍历的临界值的修改
if(i % j == 0){
isFlag = true;
break;//优化一:跳出内层循环结构
}
}
//判断此标识是否被更改过
if(!isFlag){//if(isFlag == false){
//System.out.println(i);
count++;
}
//重置isFlag
isFlag = false;
}
//获取系统当前的时间
long end = System.currentTimeMillis();
System.out.println("花费的时间为:" + (end - start)); //遍历到100000:14894 -- 加上break:2072 --改为Math.sqrt(i):1048
System.out.println("质数的个数为:" + count);
}
}
- 优化方式二
/*
题目:100以内质数的输出的算法优化
方式二:使用continue+标签的方式
*/
class PrimeNumberTest2 {
public static void main(String[] args) {
//获取系统当前的时间
long start = System.currentTimeMillis();
l:for(int i = 2;i <= 100;i++){//判断i是否是质数
for(int j = 2;j <= Math.sqrt(i);j++){ //优化二:遍历的临界值的修改
if(i % j == 0){
continue l;
}
}
//能执行到此位置的,一定是质数
System.out.println(i);
}
//获取系统当前的时间
long end = System.currentTimeMillis();
System.out.println("花费的时间为:" + (end - start));
}
}
开发中,不同的算法的实现,可能效率千差万别。我们要追求更高效的实现。
衡量算法的优劣:
① 时间复杂度 (更关心)
② 空间复杂度
5.break和continue的使用
- break和continue关键字的使用
使用范围 | 在循环结构中使用的作用 | 相同点 | |
---|---|---|---|
break | switch-case、循环结构 | 跳出(或结束)当前循环 | 在其直接的后面,不能声明执行语句 |
continue | 循环结构 | 跳出(或结束)当次循环 | 在其直接的后面,不能声明执行语句 |
- 注:带标签的break 和 continue的使用也需要了解。
- return:并非专门用于结束循环的,它的功能是结束一个方法。当一个方法执行到一个return语句时,这个方法将被结束(不论return处于多少层循环之内)。
- 代码演示
class BreakContinueTest {
public static void main(String[] args) {
for(int i = 1;i <= 10;i++){
if(i % 4 == 0){
break;
//continue;
//编译不通过:不可以编写执行语句
//System.out.println("今晚有约会!");
}
System.out.print(i);//break:123 continue:123567910
}
//在嵌套循环中的使用
System.out.println();
label:for(int i = 1;i <= 4;i++){
for(int j = 1;j <= 10;j++){
if(j % 4 == 0){
//break;
//continue;
//break label;
continue label;
}
System.out.print(j);
}
System.out.println();
}
}
}
6.流程控制应用练习——项目一:家庭收支记账系统
- 创建FamilyAccount的类,完成4个功能
- 收支明细的显示
- 登记收入
- 登记支出
- 退出
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("输入有误,请重新输入1-4:");
} 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;
}
}
import java.util.Scanner;
public class FamilyAccount {
public static void main(String[] args) {
boolean isExit = true;
int balance = 1000;//初始额度
String details = "收支\t\t账户金额\t\t支出金额\t\t说 明\n";
do {
System.out.println("-------------家庭收支记账软件-------------\n");
System.out.println(" 1 显示收支明细");
System.out.println(" 2 登记收入");
System.out.println(" 3 登记支出");
System.out.println(" 4 退 出");
System.out.print(" 请输入选项(1-4):");
char menu = Utility.readMenuSelection();//此时的menu只能是1、2、3或4
switch (menu) {
case '1':
System.out.println("----------------账目清单----------------");
// System.out.println("显示收支明细");
System.out.println(details);
System.out.println("---------------------------------------\n");
break;
case '2':
// System.out.println("登记收入");
System.out.print("请输入收入金额:");
int addMoney = Utility.readNumber();
balance += addMoney;
System.out.print("请输入收入明细:");
String addInfo = Utility.readString();
details += "收入" + "\t\t" + balance + "\t\t" + addMoney + "\t\t\t" + addInfo + "\n";
System.out.println("----------------登记完成----------------");
break;
case '3':
// System.out.println("登记支出");
System.out.print("请输入支出金额:");
int minusMoney = Utility.readNumber();
if (balance >= minusMoney) {
balance -= minusMoney;
System.out.print("请输入支出明细:");
String minusInfo = Utility.readString();
details += "支出" + "\t\t" + balance + "\t\t" + minusMoney + "\t\t\t" + minusInfo + "\n";
System.out.println("----------------登记完成----------------");
} else {
System.out.println("余额不足");
break;
}
break;
case '4':
// System.out.println("退出");
System.out.print("确认是否退出(Y/N):");
char selection = Utility.readConfirmSelection();
if (selection == 'Y') {
isExit = false;
System.out.println("退出成功!");
} else {
System.out.println("退出失败,程序继续");
break;
}
}
} while (isExit);
}
}