[笔记] 疯狂JAVA讲义(第3版)第4章 流程控制与数组

第4章 流程控制与数组

4.1 顺序结构

从上往下执行。没有流程控制的情况下,代码从第一行一直往下执行到最后一行,

4.2 分支结构

Java提供两种常见的分支结构:if语句和switch语句。

4.2.1 if条件语句

if语句使用布尔表达式或布尔值作为分支条件进行分支控制。if语句有3中形式:

if( expression){ //如果条件成立,则执行语句
statement...
}

2.

if(expression){ //如果条件成立,则执行语句
statement...
}
else{ //否则,执行else中语句
statement...
}

3

if(expression){ //如果条件成立,则执行语句
statement...
}
else if(expression){ //否则,如果下一个if成立执行else if中语句
statement...
}
//...可以有0个或多个else if语句
else{ //最后的else也可以省略
statement...
}

花括号括起来的部分作为代码块,将多行代码构成整体。

为了可读性和减少错误,建议if else语句中使用花括号,即使代码块只有一行。

@if else 的逻辑错误

public class IfErrorTest

{

	public static void main(String[] args){
	int age = 45;
	if(age>20){
	System.out.println("青年");
	}
	else if(age>40){
	System.out.println("中年");
	}
	else if(age>60){
	System.out.println("老年");	
	}
	}	
}

表面上没有问题,但是案例的45岁经过if(age>20)时会输出青年。

应该修改顺序,

if(age>60) //老年

else if(age>40)//中年

else if(age>20)//青年

在使用if else 时,有一条基本规则,应该优先处理包含范围小的条件。比如age>60和age>20,应该先处理范围较小的age>60。

4.2.2 Java 7 增强后的switch语句

switch语句由一个控制表达式和多个case标签组成。

switch的控制表达式只能是byte,short,char,int四个整数型,枚举、String类型(Java7开始允许)

switch语法:

switch(expression)
{
case condition1:
statemet;
break;
}
case condition2:
{
statemet;
break;
}
...
default:
{
statemet;
}

执行先对expression求值,然后依次匹配condition1、condition2、…遇到匹配的就执行对应的执行体。如果都不匹配,则执行default。

由于case标签使代码块非常清晰,可以省略花括号。

@注意不要漏写break,不然一遇到相等的值,程序就会一直执行完标签后面的所有语句。例如下面的例子,如果去掉break,程序输出夏天 秋天 冬天 季节输入错误。

例:

public class StringSwitchTest
{
public static void main(String\[\] args)
{
String season = "夏天";
switch(season)
{
	case "春天":
	System.out.println("春天");
	break;
	case "夏天":
	System.out.println("夏天");
	break;
	case "秋天":
	System.out.println("秋天");
	break;
	case "冬天":
	System.out.println("冬天");
	break;
	default"
	System.out.println("季节输入错误");
}
}
}

4.3 循环结构

在满足条件时,反复执行一段代码(循环体)。

在执行循环体时,需要在某些时候将条件改为假,否则就会一直执行循环体,形成死循环。

循环语句可能包含4个部分:

初始化,循环条件,循环体,迭代语句。

4.3.1 while循环

while语句语法

[init_statement]
while(expression)
{
statement;
[iteration_statement];
}

例:

public class WhileTest
{
public static void main(String[] args)
{
int count =0;
while(count<10)
{
System,out.println(count);
}
System.out.println("循环结束!");
}
}

@while陷阱 while后面紧跟一个;时,while后面的代码块和while没有关系。

4.3.2 do while

do while和while的区别是do while是先do,在判断

[init]
do{
statement;
[iteration_statement];
}while(expression);

do while的循环条件后面必须有一个分号,表明循环结束。

4.3.3 for循环

for循环是更加简洁的循环语句,大部分情况下,都可以使用for循环。

for([init_statemnet]; [test_expression;[iteration_stetement])
{
statement
}

在执行循环前,先执行初始化语句init_stetement;

每次循环前,先计算test_expression的值,如果true,则执行循环体,然后执行循环迭代语句。

@for循环的循环迭代语句没有和循环体放在一起,因此即使循环体遇到continue结束本次循环,循环迭代语句也会执行。这是while、do while语句不能做到的。

例:for循环

public static void main(String[] args){
for(int count =0;count<10;count++){
System.out.println(count);
}
System.out.println("循环结束!");
}

4.3.4 循环嵌套

把一个循环放入另一个循环体内,就可以形成循环嵌套。

for(int i=0;i<5;i++){
for(int j=0;j<3;j++){
System.out.println("i="+i+"j="+j);
}

4.4 控制循环结构

4.4.1 break结束循环

break用于完全结束一个循环,跳出循环体。

@break不仅可以结束其所在的循环,还可以直接结束外层循环,此时需要break后面跟一个标签,这个标签用于标识外层循环。

outer:
for(int i=0;i<5;i++){
for(int j=0;j<3;j++){
Suytem.out.println("i="+i+"j="+j);
if(j==1){
break outer;
}
}

4.4.2 使用continue忽略本次循环剩下语句

@与break类似,continue也可以跟一个标签,忽略标识循环的剩下语句,重新开始下一次循环。

4.4.3 使用return结束方法

return的功能是结束一个方法,如果循环在一个方法中,使用return结束方法,循环也随之结束。

4.5 数组类型

4.5.1 理解数组:数组也是一种类型

Java要求数组的数组元素具有相同的数据类型。

int[] 也是一种类型。

4.5.2 定义数组

type[] arrayName;

type arrayName[];

推荐第一种格式。

数组是一种引用类型的变量,定义时仅仅定义了一个引用变量,(也就是定义了一个指针),还没有指向有效内存。

只有初始化时后才能使用。

4.5.3 数组的初始化

1.静态初始化

arrayName = new type[] {element1,element2,…};

简化的格式

type[] arrayName = {element1,element2,…};

2.动态初始化

只指定数组长度,由系统指定初始值。

arrayName = new type[length];

@不要同时静态初始化和动态初始化。不要即指定长度,又同时指定初始值。

4.5.4 使用数组

访问元素arrayName[index]

索引是从0开始的。

数组提供了length属性,表示数组长度。可以利用length遍历数组

for(int i=0;i<prices.length;i++){
System.out.println(prices[i]);
}

4.5.5 foreach循环

用于遍历数组和集合。

for(type variableName : array|collection)
{
//varivableName自动迭代访问每个元素
}

例子:

//

String[] books = {"Bo1","Bo2"};
for(String book : books)
{
System.out,println(book);
}

@for each循环不能改变数组元素的值,因此不要用foreach进行赋值。

4.6 深入数组

4.6.1 内存中的数组

数组引用变量是一个引用,这个引用变量可以指向任何有效内存,然后访问数组元素。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LVPO4uLo-1588335970117)(media/image1.png)]{width=“5.433566272965879in” height=“3.0264884076990377in”}

只要类型兼容,可以让一个数组变量指向另一个实际的数组,这种操作会让人产生数组长度可变的错觉,但其实数组没变,只是引用变量指向另一个数组。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-d38TXVTh-1588335970119)(media/image2.png)]{width=“4.286713692038496in” height=“4.588170384951881in”}

4.6.2 基本类型数组的初始化

int [] iArr;
iArr = new int[5];
for(int i=0;i<iArr.length; i++){
iArr[i] = i+10;
}

4.6.3 引用类型数组的初始化

数组元素是引用时,情况变得复杂。

//Person类
//定义Person数组
Person[] students;
students = new Person[2];
//创建Person实例zhang
Person zhang = new Person();
zhang,age = 15;zhang,height = 158;
//创建Person实例Lee
Person lee = = new Person();
lee.age = 16;lee.height = 160;
//赋值给数组元素
student[0] = zhang;
student[1] = lee;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sLpVP9qC-1588335970123)(media/image3.png)]{width=“4.083916229221347in” height=“2.094316491688539in”}

4.6.4 “没有多维数组”

Java提供了支持多维数组的语法,但从数组底层来说,只有一维数组。

int[][] arrName; //二维数组的定义

它的本质还是一维数组,数组元素也是引用,元素保存的引用指向一维数组。

接着对二维数组进行初始化:

arrName = new type[length][];

同样可以当成是一维数组的初始化,这个一维数组的元素是引用类型(数组类型)的。

4.6.5 Java8增强的工具类 Arrays

Arrays类包含一些static方法可以直接操作数组。

二分查找binarySearch

复制数组 copyOf

判断相等equals

填充数组fill

排序 sort

转换字符串 toString

int binarySearch(type[] a, type key): 二分查找key在a数组出现的索引,如果不包含key,则返回负数。要求数组元素已经升序排列。

int binarySearch(type[] a,int fromIndex, int toIndex, type key) 只搜索从fromIndex到 toIndex的元素

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hx3uaxsu-1588335970128)(media/image4.png)]{width=“8.139860017497814in” height=“4.137016622922134in”}

@Arrays类 ,使用需要import java.util.Arrays类。

java8 为Arrays类增加的工具方法:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-61ThhsbZ-1588335970129)(media/image5.png)]{width=“7.311807742782152in” height=“4.916083770778653in”}

@parallel代表并行

Arrays类使用举例:

import java.util.Arrays;
public class ArraysTest
{
public static void main(String[] args){
int [] a = new int[]{3,4,5,6};
int [] a2 = new int[]{3,4,5,6};
System.out.println("a和a2是否相等:"+Arrays.equals(a,a2));
int []b = Arrays.copyOf(a,6);
System.out.println("a和b是否相等:"+Arrays.equals(a,b));
System.out.println("b数组元素:"+Arrays.toString(b));
Arrays.fill(b,2,4,1);
System.out.println("b数组元素:"+Arrays.toString(b));
Arrays.sort(b);
System.out.println("b数组元素:"+Arrays.toString(b));
}
}

Arrays类新增方法举例:

import java.util.*;
import java.util.function.IntBinaryOperator;
import java.util.function.IntUnaryOperator;
public class ArraysTest2 {
public static void main(String[] args) {
int[] arr1 = new int[] { 3, -4, 25, 16, 30, 18 };
Arrays.parallelSort(arr1);
System.out.println(Arrays.toString(arr1));
int[] arr2 = new int[] { 3, -4, 25, 16, 30, 18 };
Arrays.parallelPrefix(arr2, new IntBinaryOperator() {
public int applyAsInt(int left, int right) {
return left * right;
}
});
System.out.println(Arrays.toString(arr2));
int[] arr3 = new int[5];
Arrays.parallelSetAll(arr3,new IntUnaryOperator(){
@Override
public int applyAsInt(int operand) {
return operand*5;
}
});
System.out.println(Arrays.toString(arr3));
}
}

4.6.6 数组的应用举例

如果程序中有多个类型相同的变量,且它们具有逻辑的整体性,则可以将它们定义成一个数组。

例如,开发一个工具函数:将一个浮点数转换成人民币读法字符串,这个程序就很需要使用数组,

思路是将浮点数分成整数和小数部分,整数部分使用整数强制转换,小数部分用浮点数-整数部分即可。

整数部分需要考虑中国的数字习惯,4位一节,1个4位数字可以转换成几千几百几十几。

除此之外,还可以利用二维数组实现五子棋,连连看,俄罗斯方块等小游戏。

//五子棋,仅实现棋盘,胜负判定未实现

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.*;
public class Gobang
{
//棋盘大小
private static int BOARD_SIZE = 15;
//二维数组当棋盘
private String[][] board;
//初始化棋盘
public void initBoard(){
board = new String[BOARD_SIZE][BOARD_SIZE];
for(int i=0;i<BOARD_SIZE;i++){
for(int j=0;j<BOARD_SIZE;j++){
board[i][j] = "+";
}
}
}
//控制台输出棋盘

public void printBoard(){
for(int i=0;i<BOARD_SIZE;i++){
for(int j=0;j<BOARD_SIZE;j++){
System.out.print(board[i][j]);
}
System.out.print(\"\n");
}
}

public static void main(String[] args) throws Exception{
Gobang gb = new Gobang();
gb.initBoard();
gb.printBoard();
//获取键盘输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String inputStr = null;
while(( inputStr=br.readLine())!=null){
String[] posStrArr = inputStr.split(",");
int xPos = Integer.parseInt(posStrArr[0]);
int yPos = Integer.parseInt(posStrArr[1]);
gb.board[yPos-1][xPos-1] = "#";
gb.printBoard();
System.out.println("请输入下棋的坐标: x,y");
}
}
}

附录 本章练习

1.使用循环打印九九乘法表

//九九乘法表
package ch4;

public class Test1 {
	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+" ");
			}
			System.out.print("\n");
		}
	}	
}

2.使用循环输出等腰三角形。

//打印rows行的等腰三角形
package ch4;

public class Test2 {
	public static void main(String[] args) {
		final int rows = 4;
		for(int i=1;i<=rows;i++) {
			for(int j=0;j<rows-i;j++) {
				System.out.print(" ");
			}
			for(int j=0;j<2*i-1;j++) {
				System.out.print("*");
			}
			System.out.print("\n");
		}
	}
}

3.打印近似圆

//画圆
package ch4;

public class Test3 {
	public static void main(String[] args) {
		int r = 10 ;//半径
		for(int y=0;y<=2*r;y+=2) { //y+=2,如果是y++的话就会(因为精度)很难看
			int x1 = r-getX(r,y);
			int x2 = r+getX(r,y);
			for(int j=0-r;j<x1;j++) {
				System.out.print(" ");
			}
			System.out.print("*");
			for(int j=x1;j<x2;j++) {
				System.out.print(" ");
			}
			System.out.print("*");
			System.out.print("\n");

		}

	}
	public static int getX(int r,int y) {
		double tempX;
		tempX = Math.sqrt(r*r - (y-r)*(y-r));
		return (int)Math.round(tempX); 

	}
}

4.按字节截取字符串的子串。类似String类的substring()。

感觉这个题目有问题,略过

5.编写一个程序,将浮点数转换成人民币读法字符串,精确到分且不超过12位。例如。将1006.333转换为壹仟零陆元叁角叁分

重点是转换规律是每4位一转,然后根据位置加上元/万/亿。

另一个易错点是零的处理,连续零和末尾零以及全零数。

package ch4;
public class Test5 {
	public static String[] hanArr= {"零","壹","贰","叁","肆","伍","陆","柒","捌","玖"};
	public static String[] unitArr= {"十","百","千"};
	public static  String divide(double num) {
		long zheng = (long )num;//整数部分
		long xiao = Math.round((num-zheng)*100); //保留两位小数
		return new String(zheng+"#"+xiao);
	}
	//将4位及4位以内数字字符串转换成人民币读法
	public static String trans4(String s) {
		int len = s.length();
		if(len>4&&len<1) {
			System.out.println("传入参数错入,应该传入1-4位的数字字符串");
			return "";
		}
		String tmp = s;
		String result = "";
		if("0000".equals(tmp)||"000".equals(tmp)||"00".equals(tmp)||
				"0".equals(tmp)){
			return result = hanArr[0];
		}
		//去除前面的0
		while(tmp.charAt(0)=='0'&&len>1) {
			tmp = tmp.substring(1,len);
			len = len-1;
		}
		//转换...
		for(int i=0;i<len;i++) {
			int n = tmp.charAt(i)-48;
			//不为0且不是最后一位,直接转为数字+单位
			if( n !=0 && (i!=len-1)) {
				result+= hanArr[n]+unitArr[len-2-i];
			}else if(n==0) {
				//判断连续0,前面不是0时加'零',有连续的0过就跳过,末尾的0也跳过
				if((tmp.charAt(i-1)-48)!=0 && i!=len-1) {
					result+=hanArr[0];
				}			
			}else if(n!=0&&(i==len-1)) {
				result+=hanArr[n];
			}		
		}
		//末尾零,去掉
		if(result.charAt(result.length()-1)=='零') {
			result = result.substring(0,result.length()-1);
		}
		return result;
	}
	public static String transAll(String s) {
		String result = "";	
		//4位数以内
		if(s.length()<=4) {
			result = trans4(s);
		}
		//4位数以上8位数以内
		else if(s.length()<=8)
		{
			String s1 = trans4(s.substring(0,s.length()-4));//高位
			String s2 = trans4(s.substring(s.length()-4));//低位
			if("零".equals(s2)) {
				s2="";
			}	
			result = s1 +"万"+ s2;
		}
		else if(s.length()<=12) 
		{
			String s1 = trans4(s.substring(0,s.length()-8));//高位
			String s2 = trans4(s.substring(s.length()-8,s.length()-4)) ;//低位
			String s3 = trans4(s.substring(s.length()-4));		//最低位
			result += s1 +"亿";
			if(!"零".equals(s2)) {
				result += s2+"万";
			}
			if(!"零".equals(s3)) {
				result += s3;
			}
		}
		return result;
	}	
	public static void main(String[] args) {
		double num = 12301234000.11;
		String snum = divide(num);
		String zheng = snum.substring(0, snum.indexOf("#"));
		String xiao = snum.substring(snum.indexOf("#")+1);	
		//小数部分简单, 直接写在这里了
		String han_xiao ="";
		if(xiao.length()==1) {
			char c=xiao.charAt(0);
			han_xiao = hanArr[(c-48)]+"角";		
		}else if(xiao.length()==2) {
			char c=xiao.charAt(0);
			han_xiao += hanArr[(c-48)]+"角";		
			c = xiao.charAt(1);
			han_xiao += hanArr[(c-48)]+"分";		
		}
		System.out.println(transAll(zheng)+" "+han_xiao);
	}
}

6.控制台五子棋

/*实现了双人对战,未处理非法输入,
因为没找到合适的字符棋盘有点难看
*/
package ch4;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.*;

public class Gobang
{
    private static int BOARD_SIZE = 15;    	//棋盘大小
    private String[][] board;    			//二维数组当棋盘
    //初始化棋盘
    public void initBoard(){
        board = new String[BOARD_SIZE][BOARD_SIZE];
        for(int i=0;i<BOARD_SIZE;i++){
            for(int j=0;j<BOARD_SIZE;j++){
                board[i][j] = "十";
            }
        }
    }
    //控制台输出棋盘
    public void printBoard(){
        for(int i=0;i<BOARD_SIZE;i++){
            for(int j=0;j<BOARD_SIZE;j++){
                System.out.print(board[i][j]);
            }
            System.out.print("\n");
        }
    }
    public boolean judge(int y,int x,String s) {
    	int left  = (x-4>=0)?(x-4):0;
    	int right = (x+4<BOARD_SIZE)?x+4:BOARD_SIZE;
    	int up 	  = (y-4>=0)?(y-4):0;
    	int down  = (y+4<BOARD_SIZE)?y+4:BOARD_SIZE;
    	int tmpx = x;
    	int tmpy = y;
    	int zx = x;
    	int zx2 = x;
    	int zy = y;
    	int zy2 = y;
    	while(s.equals(board[y][tmpx])&&tmpx>left) {
    		tmpx--;
    	}
    	while(s.equals(board[tmpy][x])&&tmpy>up){
    		tmpy--;
    	}
    	while(s.equals(board[zy][zx])&&zx>left&&zy>up) {//左上
    		zy--;
    		zx--;
    	}
    	while(s.equals(board[zy2][zx2])&&zx>left&&zy<down) {//左下
    		zy2++;
    		zx2--;
    	}
    	int countx=0;
    	int county=0;
    	int countz1 = 0;
    	int countz2 = 0;
    	//x轴y轴判断
    	for(int i=tmpx;i<=right;i++) {
    		if(s.equals(board[y][i])) {
    			countx++;
    		}
    	}
    	for(int j=tmpy;j<=down ;j++) {
    		if(s.equals(board[j][x])) {
    			county++;
    		}
    	}  	
    	//斜线判断
    	for(int j=zy,i=zx;j<=down&&i<=right;j++,i++) {
    		if(s.equals(board[j][i])) {
    			countz1++;
    		}
    	}
    	for(int j=zy2,i=zx2;j>=up&&i<=right;j--,i++) {
    		if(s.equals(board[j][i])) {
    			countz2++;
    		}
    	}
    	
    	if(countx>=5||county>=5||countz1>=5||countz2>=5) {
    		return true;
    	}
    	
    	return false;
    }
    
    public static void main(String[] args) throws Exception{
        Gobang gb = new Gobang();
        gb.initBoard();
        gb.printBoard();
        //获取键盘输入
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String inputStr = null;
        System.out.println("请输入下棋的坐标: x,y");
        boolean meWin = false;
        boolean youWin = false;
        boolean myTurn = true;
        while(( inputStr=br.readLine())!=null ){
            String[] posStrArr = inputStr.split(",");
            int xPos = Integer.parseInt(posStrArr[0]);
            int yPos = Integer.parseInt(posStrArr[1]);
            if(myTurn) {
                gb.board[yPos-1][xPos-1] = "●";
                meWin = gb.judge(yPos-1,xPos-1,"●");
            }
            else {
            	 gb.board[yPos-1][xPos-1] = "○";
            	 youWin = gb.judge(yPos-1,xPos-1,"○");
            }
            gb.printBoard();
            if(meWin) {
            	System.out.println("meWin!");
            	break;
            }else if(youWin) {
            	System.out.println("youWin!");
            	break;
            }
            myTurn = !myTurn;
            System.out.println("请输入下棋的坐标: x,y");
        }

    }

}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只大鸽子

如有帮助,欢迎关注同名公众号

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值