Java输入多词字符串触发java.lang.NumberFormatException的问题
问题描述
在Java费用统计程序中输入带空格的项目名称(如Chicken rice)时,程序会把第二个词识别成金额输入,调用Integer.valueOf()时抛出NumberFormatException:
Exception in thread "main" java.lang.NumberFormatException: For input string: "rice" at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67) at java.base/java.lang.Integer.parseInt(Integer.java:668) at java.base/java.lang.Integer.valueOf(Integer.java:999) at Sampleproject1/t4.Main.main(Main.java:65)
当前使用的代码如下:
import java.util.*; class Expense implements Comparable<Expense>{ String expenseCategory; Integer amount; public String getExpenseCategory() { return expenseCategory; } public void setExpenseCategory(String expenseCategory) { this.expenseCategory = expenseCategory; } public Integer getAmount() { return amount; } public void setAmount(Integer amount) { this.amount = amount; } public Expense(String expC , Integer amount) { this.expenseCategory=expC; this.amount = amount; } public String toString() { return expenseCategory+ " " +amount; } public int compareTo(Expense e) { if(amount>e.amount){ return 1; }else if(amount<e.amount){ return -1; }else{ return 0; } } } public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); TreeSet<Expense> set1 = new TreeSet<Expense>(); int tamount=0; while(true) { System.out.println("Enter item"); String expC = sc.next(); System.out.println("Enter amount(Dinar)"); String amt = sc.next(); tamount = tamount + Integer.valueOf(amt); set1.add(new Expense(expC,Integer.valueOf(amt))); System.out.println("Do you want to continue(yes/no):"); String cond = sc.next(); if(cond.equals("no")) { break; }else {continue;} } System.out.println("Total dinar required is:"); System.out.println("Category Amount(Dinar)"); Iterator x = set1.descendingIterator(); while(x.hasNext()) { System.out.println(x.next()); } System.out.println("Total amount needed in Dinar:"+ tamount); System.out.println("Total amount needed in Rupees:"+ tamount*18.565); } }
期望实现的输出效果:
Enter item Fried Rice Enter amount(Dinar) 20 Do you want to continue(yes/no): yes Enter item Chicken Lollipop Enter amount(Dinar) 25 Do you want to continue(yes/no): yes Enter item Coffee Enter amount(Dinar) 5 Do you want to continue(yes/no): no Total dinar required is: Item Amount(Dinar) Chicken Lollipop25 Fried Rice 20 Coffee 5 Total amount needed in Dinar: 50 Total amount needed in Rupees: 928.25
尝试用Scanner.nextLine()解决多词输入问题时,出现部分输入被跳过的情况,需要解决该问题。
问题原因
sc.next()默认以空格作为分隔符,只能读取到空格前的第一个词,后续内容会被当成下一个输入项,导致金额读取到项目名的后续词,触发类型转换异常。- 当
next()和nextLine()混用时,next()读取完内容后会留下换行符在输入缓冲区,后续的nextLine()会直接读取这个空换行符,导致输入被跳过。
解决方案
统一使用nextLine()读取输入,同时增加输入合法性校验提升程序健壮性,修改后的完整代码如下:
import java.util.*; class Expense implements Comparable<Expense> { String expenseCategory; Integer amount; public String getExpenseCategory() { return expenseCategory; } public void setExpenseCategory(String expenseCategory) { this.expenseCategory = expenseCategory; } public Integer getAmount() { return amount; } public void setAmount(Integer amount) { this.amount = amount; } public Expense(String expC, Integer amount) { this.expenseCategory = expC; this.amount = amount; } @Override public String toString() { // 格式化输出实现对齐效果 return String.format("%-15s %d", expenseCategory, amount); } @Override public int compareTo(Expense e) { // 直接复用Integer的compareTo方法更简洁 return amount.compareTo(e.amount); } } public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); TreeSet<Expense> set1 = new TreeSet<>(); int tamount = 0; while (true) { System.out.println("Enter item"); // 读取完整项目名称,去除前后空格 String expC = sc.nextLine().trim(); // 处理空输入情况 while (expC.isEmpty()) { System.out.println("Item name cannot be empty, please enter again"); expC = sc.nextLine().trim(); } System.out.println("Enter amount(Dinar)"); Integer amt = null; // 循环直到输入合法正整数 while (amt == null) { String amtStr = sc.nextLine().trim(); try { amt = Integer.valueOf(amtStr); if (amt <= 0) { System.out.println("Amount must be positive, please enter again"); amt = null; } } catch (NumberFormatException e) { System.out.println("Invalid amount, please enter an integer"); } } tamount += amt; set1.add(new Expense(expC, amt)); System.out.println("Do you want to continue(yes/no):"); String cond = ""; // 确保输入只能是yes/no while (!cond.equalsIgnoreCase("yes") && !cond.equalsIgnoreCase("no")) { cond = sc.nextLine().trim(); if (!cond.equalsIgnoreCase("yes") && !cond.equalsIgnoreCase("no")) { System.out.println("Please enter yes or no"); } } if (cond.equalsIgnoreCase("no")) { break; } } System.out.println("Total dinar required is:"); System.out.println(String.format("%-15s %s", "Item", "Amount(Dinar)")); Iterator<Expense> x = set1.descendingIterator(); while (x.hasNext()) { System.out.println(x.next()); } System.out.println("Total amount needed in Dinar: " + tamount); // 格式化输出卢比金额保留两位小数 System.out.printf("Total amount needed in Rupees: %.2f%n", tamount * 18.565); } }
关键修改点
- 全部替换
sc.next()为sc.nextLine(),配合trim()读取完整的带空格项目名称。 - 增加输入校验:项目名非空、金额为正整数、继续指令只能是yes/no,避免非法输入导致的异常。
- 重写
toString()方法用String.format()格式化输出,实现项目与金额的对齐效果。 - 简化
compareTo()方法,直接调用Integer的内置比较方法,代码更规范。
内容的提问来源于stack exchange,提问作者Tharun S M
相关产品推荐
相关产品推荐

