使用Scanner循环输入并校验时出现的问题

问题一:循环创建Scanner对象并使用close()方法

菜鸟想要用Scanner达到循环输入的目的,没有直接百度而是“自以为是”的在循环里写创建Scanner类,并且还“体贴”的在使用完毕后close()掉:

		for(int i = 0; i < 3; i++) {
			System.out.println("第"+(i+1)+"次输入");
			Scanner sc = new Scanner(System.in);
			String strInput = sc.next();
			sc.close();
		}

然而,在循环到第二次的时候就不对了:
第一段代码的报错信息
试了半天,最后老实问度娘:Scanner + java.util.NoSuchElementException
原来是因为第二次循环sc.next()找不到下一个元素,找不到的原因是因为上次循环结束时关闭了System.in。

System.in 在java中是静态变量,当前类所有的scanner对象共享它,当一个scanner对象执行close()操作后,其他所有的scanner对象都不可用了。

—— Scanner 的执行错误NoSuchElementException

正确姿势:

		Scanner sc = new Scanner(System.in);
		for(int i = 0; i < 3; i++) {
			System.out.println("第"+(i+1)+"次输入");
			String strInput = sc.next();
		}
		sc.close();

把开头结尾丢循环外面就对了~

问题二:循环输入校验时不处理校验失败的部分

之所以要循环输入是因为想要做校验,输入不通过就继续输入。比如:判断输入的类型;输入是否在规定范围内等。
判断输入的类型可以用Scanner的hasNextInt()、hasNextDouble()等,其中hasNext()就是判断是否有下一次输入的内容,不管类型,其他的都是判断是否有下一个相应类型的输入。比如输入一个整数:

		Scanner sc = new Scanner(System.in);
		while(true) {
			System.out.println("请输入一个整数:");
			if(sc.hasNextInt()) {
				int intInput = sc.nextInt();
				System.out.println("输入的整数为:"+intInput);
				break;
			}
		}
		sc.close();

问题不是有值怎样,而是没有值怎么处理,如果输入的是"abc",我以为的结果是接着下一次输入就好了,然而事实是:
死循环了
进入了死循环…我在sc.hasNextInt()那行打了断点,发现进入if之后,第一次程序会等待我输入内容,后面就不等我输入了,直接判断不符合if条件。

遇到hasNext()时,Scanner也会阻塞,等待你输入,等你输入后返回true。查看jdkapi,你会发现该方法当Scanner缓存区中有值可读时,会返回true,若没有,会一直阻塞等待你输入。
hasNextInt()函数大体意思表示scanner当前的标记的输入是否为int,并不会自动的移动标记。

——《Scanner的hasNext、hasNextInt用法》

也就是说,若输入的是整数,进入if代码块,执行了hasNextInt()方法会改变读取的标记位置;若输入的不是整数,没有执行类似hasNext()之类的方法,缓存区里将会放着上次的输入内容,从而一直if条件不满足。
解决方法就是:hasNext()之类的方法,要和next()之类的方法搭配使用

		Scanner sc = new Scanner(System.in);
		while(true) {
			System.out.println("请输入一个整数:");
			if(sc.hasNextInt()) {
				int intInput = sc.nextInt();
				System.out.println("输入的整数为:"+intInput);
				break;
			}else {
				sc.next();
			}
		}
		sc.close();

搞定~

其他用法

  1. 终止输入:要么在控制台 ctrl+z,要么约定一个输入的字符串作为终止符,写在循环条件里
  2. 实际上每行输入结尾应该都带着"\n",通过nextInt()、nextDouble()等只能读取数值,是不包含那个回车的,这时候再接一个nextLine()你将成功获取到一个回车~
  3. next()方法由第一个有效字符(非空格,非换行符) 开始,到第一个分隔符或结束符(空格或换行符) 结束,从而获得第一个扫描到的不含空格、换行符的单个字符串。换言之,如果想要获取带空格的内容,就用nextLine()
  4. 关于光标cursor位置:
    nextInt() - 光标位置在数值后面,"\n"前面;
    next() - 光标指向本行;
    nextLine() - 光标指向下一行
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是 Java 代码实现: ```java import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.util.Scanner; public class DateDifferenceCalculator { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd"); LocalDate date1 = null; LocalDate date2 = null; while (true) { // 输入第一个日期 System.out.print("请输入第一个日期(yyyyMMdd,例如:20220101):"); String input1 = scanner.nextLine(); // 输入 0 退出程序 if (input1.equals("0")) { System.exit(0); } // 校验第一个日期格式和合法性 try { date1 = LocalDate.parse(input1, formatter); if (date1.isBefore(LocalDate.of(1970, 1, 1))) { System.out.println("输入错误:日期必须大于19700101!"); continue; } } catch (DateTimeParseException e) { System.out.println("输入错误:日期格式不正确!"); continue; } // 输入第二个日期 System.out.print("请输入第二个日期(yyyyMMdd,例如:20221231):"); String input2 = scanner.nextLine(); // 输入 0 退出程序 if (input2.equals("0")) { System.exit(0); } // 校验第二个日期格式和合法性 try { date2 = LocalDate.parse(input2, formatter); if (date2.isBefore(LocalDate.of(1970, 1, 1))) { System.out.println("输入错误:日期必须大于19700101!"); continue; } if (date2.isBefore(date1.plusYears(4))) { System.out.println("输入错误:两个日期相差必须大于4年!"); continue; } } catch (DateTimeParseException e) { System.out.println("输入错误:日期格式不正确!"); continue; } // 两个日期都合法,跳出循环 break; } // 计算两个日期之间相差的天数 long days = date2.toEpochDay() - date1.toEpochDay(); System.out.println("两个日期之间相差 " + days + " 天。"); } } ``` 代码中使用Java 提供的日期间类 `LocalDate` 和 `DateTimeFormatter` 来进行日期格式化和计算。程序使用 `Scanner` 类来进行用户输入,并对输入进行校验,保证输入的日期格式合法且符合题目要求。最后,程序输出两个日期之间相差的天数。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值