Day3 : Scanner对象 / 顺序结构 / 选择结构 / 循环结构 / break&continue / 练习
Scanner s = new Scanner(System.in);
通过Scanner类的next() 与 nextLine() 方法获取输入的字符串,在读取前我们一般需要使用hasNext() 与 hasNextLine() 判断是否还有输入的数据。
next():
-
一定要读取到有效字符后才可以结束输入
-
对输入有效字符之前遇到的空白,next()方法会自动将其去掉
-
只有输入有效字符后才将其后面输入的空白作为分隔符或这结束符
-
next()不能得到带有空格的字符串。
nextLine();
-
以Enter为结束符,也就是说 nextLine()方法返回的是输入回车之前的所有字符
-
可以获得空白
使用 next 方法:
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
//首先创建一个扫描器,用于接收键盘数据
Scanner scanner = new Scanner(System.in);
System.out.println("请输入数据:");
if (scanner.hasNext()) {
//使用next方式接收
String str = scanner.next();
System.out.println("收到的数据为:" + str);
}
//凡是属于IO流的类,如果不关闭,会一直占用资源。
scanner.close();
}
}
结果
请输入数据:
hello world
收到的数据为:hello
使用 nextLine 方法:
import java.util.Scanner;
public class ScannerNextLine {
public static void main(String[] args) {
//从键盘接收数据
Scanner sc = new Scanner(System.in);
System.out.println("请输入数据:");
//判断是否还有输入
if (sc.hasNextLine()) {
String str = sc.nextLine();
System.out.println("收到的数据为:" + str);
}
sc.close();
}
}
结果
请输入数据:
hello world
收到的数据为:hello world
Scanner进阶用法(输入基本数据类型)
如果要输入 int 或 float 类型的数据,在 Scanner 类中也有支持,
但是在输入之前最好先使用 hasNextXxx() 方法进行验证,再使用 nextXxx() 来读取:
比如输入int类型的数据
if (sc.hasNextInt()) {
int i = sc.nextInt();
System.out.println("收到的数据为:" + i);
}
练习
输入多个数字,并求其总和与平均数,通过输入非数字来结束输入并输出执行结果:
import java.util.Scanner;
public class Sum {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int sum = 0;
int count = 0;
while (sc.hasNextInt()) {
int num = sc.nextInt();
sum += num;
count++;
}
System.out.println("总和:" + sum);
System.out.println("平均:" + (1.0 * sum / count));
sc.close();
}
}
结果·
1 2 3 4 5 q
总和:15
平均:3.0
注意
当使用nextLine()方法之前,使用过其他的方法,需要多使用一次nextLine()方法
如下代码,先输入一个年龄,再输入姓名
import java.util.Scanner;
public class ScannerBug {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = 0;
String str = null;
if (sc.hasNextInt()) {
num = sc.nextInt();
}
if (sc.hasNextLine()) {
str = sc.nextLine();
}
System.out.println("---------输出结果-------");
System.out.println("年龄" + num);
System.out.println("姓名" + str);
sc.close();
}
}
结果
18
---------输出结果-------
年龄18
姓名
分析
在输入18按下回车之后,直接打印结果。跳过了姓名的输入,不妨试试使用空格分离输入的参数。
18 ljh
---------输出结果-------
年龄18
姓名 ljh
发现姓名后面多了个空格才打印输入的名字,说明nextInt()方法只读取到18。
18往后的数据都被nextLine()接收,正好nextLine()方法可以接收空白,所以包含了空格。
如果将nextLine()方法改成next()方法,不包含空白,可以解决以上问题。
package com.study.scanner;
import java.util.Scanner;
public class ScannerBug {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = 0;
String str = null;
if (sc.hasNextInt()) {
num = sc.nextInt();
}
if (sc.hasNext()) {
str = sc.next();
}
System.out.println("---------输出结果-------");
System.out.println("年龄" + num);
System.out.println("姓名" + str);
sc.close();
}
}
结果
18 ljh
---------输出结果-------
年龄18
姓名ljh
18
ljh
---------输出结果-------
年龄18
姓名ljh
那么就是要求nextLine()读取下一行数据怎么办呢?
如新增一个需求再读取一个电话号码,要求区号和尾号用空格隔开
public class ScannerBug {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = 0;
String str = null;
String phone = null;
if (sc.hasNextInt()) {
num = sc.nextInt();
}
if (sc.hasNext()) {
str = sc.next();
}
if (sc.hasNextLine()) {
phone = sc.nextLine();
}
System.out.println("---------输出结果-------");
System.out.println("年龄" + num);
System.out.println("姓名" + str);
System.out.println("电话" + phone);
sc.close();
}
}
结果
18
ljh
---------输出结果-------
年龄18
姓名ljh
电话
18 ljh 0771 1234
---------输出结果-------
年龄18
姓名ljh
电话 0771 1234
两种输入方式,第一种 nextLine()方法又读取了ljh后面的数据,导致第三个数据不能输入。
第二种输入方式多了个空格
考虑应该把ljh后面的数据给吃掉。再接收第三个数据
import java.util.Scanner;
public class ScannerBug {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num = 0;
String str = null;
String phone = null;
if (sc.hasNextInt()) {
num = sc.nextInt();
}
if (sc.hasNext()) {
str = sc.next();
}
if (sc.hasNextLine()) {
sc.nextLine();// 去除前一行多余的数据
phone = sc.nextLine();
}
System.out.println("---------输出结果-------");
System.out.println("年龄" + num);
System.out.println("姓名" + str);
System.out.println("电话" + phone);
sc.close();
}
}
结果
18
ljh
0771 1234
---------输出结果-------
年龄18
姓名ljh
电话0771 1234
最终达到想要的效果。
总结
nextXxx()方法只读取到相应的数值就停止,不含换行操作。
nextLine()方法在后面使用时,注意前面的方法是否含有换行处理。
2.顺序结构
java的基本结构,除非特别指明,否则按照顺序一句一句执行。
最简单的算法结构
它是任何一个算法都离不开的一种基本算法结构
public class SequenceFlow {
public static void main(String[] args) {
System.out.println("从上到下执行");
System.out.println("先输出1");
System.out.println("2");
System.out.println("3");
System.out.println("4");
System.out.println("最后输出5");
System.out.println("结束");
}
}
3.选择结构
-
if单选择结构
if(布尔表达式){ //如果布尔表达式为true将执行语句 }
public class IfDemo01{ public stati void main(String[] args){; Scanner scanner = new Scanner(System.in); System.out.println("请输入内容:"); String s = scanner.nextLine(); //equals: 判断字符串是否想等 If(s.equals("Hello")){ System.out.println(s); } System.out.println("End"); scanner.close(); } }
-
if双选择结构
if(布尔表达式){ //如果布尔表达式为true将执行语句 }else{ //如果布尔表达式为false将执行语句 }
-
if多选择结构
if(布尔表达式 1){ 如果布尔表达式 1的值为true执行代码 }else if(布尔表达式 2){ 如果布尔表达式 2的值为true执行代码 }else if(布尔表达式 3){ 如果布尔表达式 3的值为true执行代码 }else{ 如果以上布尔表达式都不为true执行代码 }
-
嵌套的if结构
if(布尔表达式 1){ //如果布尔表达式 1的值为true执行代码 if(布尔表达式 2){ //如果布尔表达式 2的值为true执行代码 } }
-
switch多选择结构
switch case语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。
switch语句中的变量类型可以是:
-
byte、short、int或者char
-
从Java SE 7 开始switch支持字符串String 类型了
-
同时 case 标签必须为字符串常量或字面量。
switch(expression){ case value: //语句 break;//可选 case value: //语句 break;//可选 //可以有任意数量的case语句 default://可选 //语句 }
-
switch case 语句有如下规则:
-
switch 语句中的变量类型可以是: byte、short、int 或者 char。
从 Java SE 7 开始,switch 支持字符串 String 类型了,同时 case 标签必须为字符串常量或字面量。
-
switch 语句可以拥有多个 case 语句。每个 case 后面跟一个要比较的值和冒号。
-
case 语句中的值的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量。
-
当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句。
-
当遇到 break 语句时,switch 语句终止。程序跳转到 switch 语句后面的语句执行。case 语句不必须要包含 break 语句。如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句。
-
switch 语句可以包含一个 default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句。
switch case 执行时,一定会先进行匹配,匹配成功返回当前 case 的值,再根据是否有 break,判断是否继续输出,或是跳出判断。
SwitchDemo.java
import javax.sound.midi.Soundbank;
public class SwitchDemo {
public static void main(String[] args) {
char grade = 'A';
switch (grade) {
case 'A':
System.out.println("优秀");
break;
case 'B':
System.out.println("良好");
break;
case 'C':
System.out.println("及格");
break;
case 'D':
System.out.println("难顶");
break;
default:
System.out.println("GG");
}
System.out.println("---------Java7之后支持字符串判断-----------");
String evaluate = "良好";
switch (evaluate) {
case "优秀":
System.out.println('A');
break;
case "良好":
System.out.println('B');
break;
case "及格":
System.out.println('C');
break;
case "难顶":
System.out.println('D');
break;
default:
System.out.println("GG");
}
}
}
结果
优秀
---------Java7之后支持字符串判断-----------
B
*反编译
通过IDEA查看.class文件
将该文件复制到源码文件目录下
SwitchDemo.class
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.study.control;
public class SwitchDemo {
public SwitchDemo() {
}
public static void main(String[] args) {
char grade = 65;
switch(grade) {
case 65:
System.out.println("优秀");
break;
case 66:
System.out.println("良好");
break;
case 67:
System.out.println("及格");
break;
case 68:
System.out.println("难顶");
break;
default:
System.out.println("GG");
}
System.out.println("---------Java7之后支持字符串判断-----------");
String evaluate = "良好";
byte var4 = -1;
switch(evaluate.hashCode()) {
case 658856:
if (evaluate.equals("优秀")) {
var4 = 0;
}
break;
case 691634:
if (evaluate.equals("及格")) {
var4 = 2;
}
break;
case 1058030:
if (evaluate.equals("良好")) {
var4 = 1;
}
break;
case 1235320:
if (evaluate.equals("难顶")) {
var4 = 3;
}
}
switch(var4) {
case 0:
System.out.println('A');
break;
case 1:
System.out.println('B');
break;
case 2:
System.out.println('C');
break;
case 3:
System.out.println('D');
break;
default:
System.out.println("GG");
}
}
}
可以看到class文件自动生成了一个无参构造器
public SwitchDemo() {}
进行String匹配时,先用hasCode进行比较,再通过第二轮常规的switch匹配。
反编译以后再深入。
4.循环结构
1.while循环
//while是最基本的循环
while(布尔表达式){
//循环的内容
}
//- 只要布尔表达式为true,循环就会一直执行下去。我们大所属情况是会让循环停下来,我们需要一个让表达式失效的方式来结束循环。
//- 少部分情况需要循环一直执行,如服务器的请求相应监听等。
//- 循环条件为true就会造成无限循环【死循环】,一般情况下需避免死循环
//- 思考:1+2+3+...+100=?
public class WhileDemo{
public static void main(String[] args){
int i=0;
int sum=0;
while(i<=100){
sum = sum + i;
i++;
}
System.out.println("sum:"+sum);
}
}
2.do...while循环
do{
//代码语句
}while(布尔表达式);
while 和 do...while 的区别
-
-
对于while语句而言,如果不满足条件,则不能进入循环。而do...while循环和while循环相似,不同的是,do...while循环至少会执行一次。
-
while是先判断后执行;do...while 是先执行后判断。do...while总是保证循环体会被至少执行一次!这是他们的主要区别。
-
注意:布尔表达式在循环体的后面,所以语句块在检测布尔表达式之前已经执行了。
如果布尔表达式的值为 true,则语句块一直执行,直到布尔表达式的值为 false。
最后的分号不要忘记!
do...while适用于先输入再判断的情况。
如输入一串数据,遇到‘-1’结束
//输入一串数字,遇到 -1 结束
Scanner sc = new Scanner(System.in);
int num = 0;
do {
num = sc.nextInt();
System.out.println(num);
} while (num != -1);
结果
1 2 3 4 -1 5 6 7
1
2
3
4
-1
3.for循环
for(初始化;布尔表达式;更新){
//代码语句
}
/*
最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
然后,检测布尔表达式的值。如果为true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
执行一次循环后,更新循环控制变量(迭代因子控制循环变量的增减)再次检测布尔表达式。循环执行上面的过程。
*/
//死循环
for(; ; ){
}
for循环语句是支持迭代的一种通用结构,是最有效、最灵活的循环结构。
关于 for 循环有以下几点说明:
- 最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
- 然后,检测布尔表达式的值。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
- 执行一次循环后,更新循环控制变量。
- 再次检测布尔表达式。循环执行上面的过程。
4.在java5中引入了一种主要用于数组的增强型for循环
主要用于数组或集合的增强型for循环
for(声明语句 : 表达式){
//代码语句
}
声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。
表达式:表达式是要访问的数组名,或者是返回值为数组的方法。
public class EnhanceFor {
public static void main(String[] args) {
int[] numArray = {1, 2, 3, 4, 5, 6, 7, 8};
// numArray.for tab键
for (int i : numArray) {
System.out.println(i);
}
}
}
5.break&continue
-
break在任何循环语句的主体部分,均可用break控制循环的流程。break用于强行退出循环,不执行循环中剩余的语句。(breakl语句也在switch语句中使用)
-
continue语句用在循环语句体中,用于终止某次循环过程,及跳过循环体中尚未执行的语句,接着进行下一次是否执行循环的判定。
-
break在任何循环语句的主体部分,均可用break
1.break关键字
break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。
break 跳出最里层的循环,并且继续执行该循环下面的语句。
语法
break 的用法很简单,就是循环结构中的一条语句:
break;
public class BreakDemo {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
if (i > 50) {
break;//i=51时就跳出循环,结束
}
System.out.println(i);
}
}
}
2.continue 关键字
continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。
在 for 循环中,continue 语句使程序立即跳转到更新语句。
在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。
语法
continue 就是循环体中一条简单的语句:
continue;
public class ContinueDemo {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
if (i % 10 == 0) {
System.out.println();
continue;
}
// 每次遇到整除10的数就换行,同时跳出循环继续下一轮,略过整10的打印
System.out.print(i + "\t");
}
}
}
*GOTO语句(了解)
goto 关键字很早就在程序设计语言中出现。
事实上,goto 是汇编语言的程序控制结构的始祖:“若条件 A,则跳到这里;否则跳到那里”。
若阅读由几乎所有编译器生成的汇编代码,就会发现程序控制里包含了许多跳转。
然而,goto 是在源码的级别跳转的,所以招致了不好的声誉。
若程序总是从一个地方跳到另一个地方,还有什么办法能识别代码的流程呢?
随着 Edsger Dijkstra 著名的“Goto 有害”论的问世,goto 便从此失宠。
事实上,真正的问题并不在于使用 goto ,而在于 goto 的滥用。而且在一些少见的情况下,goto 是组织控制流程的最佳手段。
尽管 goto 仍是 Java 的一个保留字,但并未在语言中得到正式使用;Java 没有 goto 。
然而,在 break 和continue 这两个关键字的身上,我们仍然能看出一些 goto 的影子。
它并不属于一次跳转,而是中断循环语句的一种方法。之所以把它们纳入 goto 问题中一起讨论,是由于它们使用了相同的机制:标签。
“标签”是后面跟一个冒号的标识符,就象下面这样:
label1:
对 Java 来说,唯一用到标签的地方是在循环语句之前。进一步说,它实际需要紧靠在循环语句的前方——在
标签和循环之间置入任何语句都是不明智的。而在循环之前设置标签的唯一理由是:我们希望在其中嵌套另
一个循环或者一个开关。这是由于 break 和 continue 关键字通常只中断当前循环,但若随同标签使用,它们
就会中断到存在标签的地方。
下面是 for 循环的一个例子:
LabelDemo.java
package com.study.control;
/**
* 求100-1000的质素
*/
public class LabelDemo {
public static void main(String[] args) {
label:for (int i = 100; i <= 1000; i++) {
for (int j = 2; j <= i / 2; j++) {
if (i % j == 0) {
continue label; // 如果不是质素,跑到外层循环继续下一个数的判断
}
}
System.out.println(i);
}
}
}
6.练习
1.计算:1+2+3+...+100=?
publilc class WhileDemo03{
public static void main(String[] args){
int i=0;
int sum=0;
while(i<=100){
sum= i + sum; //这句和i++顺序问题
i++;
}
System.out.println("sum="+sum);
}
}
2.分别计算0~100之间的奇数和偶数的和
public class ForDemo02{
public static void main(String[] args){
int oddSum = 0;
int evenSum = 0;
for(int i=0; i<=100; i++){
if(i%2!=0){
//oddSum = i + oddSum;
oddSum+=i;
}else {
//evenSum = i + evenSum;
evenSum+=i;
}
}
System.out.println("oddSum="+oddSum);
System.out.print("evenSum="+evenSum);
}
}
3.用while或for循环输出1~1000之间能被5整除的数,且每行输出10个
public class ForDemo03{
public static void main(String[] args){
for(int i=1; i<=1000; i++){
if(i%5==0){
System.out.print(i+" ");
}
if(i%(5*10)==0){
System.out.print("\n");
}
}
}
}
publlic class ForDemo03{
public static void main(String[] args){
int i=0;
while(i<=1000){
i++;
if(i%5==0){
System.out.print(i+" ");
}
if(i%(5*10)==0){
System.out.print("\n");
}
}
}
}
4.打印九九乘法表
public class ForDemo04{
public static void main(String[] args){
for(int j=1; j<=9; j++){
for(int i=1; i<=j; i++){
System.out.print(i+"*"+j+"="+(i*j)+"\t");
}
System.out.println();
}
}
}
5.打印三角形,5行
public class TestDemo{
public static void main(String[] args){
//1 3 5 7 9
/*for(int i=1; i<=5; i++){
for(int j=5; j>=i; j--){
System.out.print(" ");
}
for(int j=1; j<=i; j++){
System.out.print("*");
}
for(int j=1; j<i; j++){
System.out.print("*");
}
System.out.println();
}*/
//1 2 3 4 5
for (int i=1; i<=5; i++) {
for (int j=5; j>=i; j--){
System.out.print(" ");
}
for (int j=1; j<=i; j++){
System.out.print("* ");
}
System.out.println();
}
}
}