Java进制转换程序异常:非法输入无报错且陷入死循环
解决Java进制转换程序非法输入时的无限循环与报错不显示问题
看起来你遇到的问题主要是几个关键疏漏导致的:验证逻辑没生效、非法基数触发死循环,以及输入异常未处理。咱们一步步拆解解决:
问题根源分析
- 验证方法未被调用:你写了
isValidInteger方法做合法性检查,但整个程序里完全没调用它!这就导致输入非法基数(比如1)或者含非法字符的数值时,根本没触发错误检查,直接进入转换逻辑埋下隐患。 - 非法基数引发无限循环:当
finalBase小于2时(比如输入1),convertInteger里的这段循环会无限执行:
因为int D = 1; for( ; Math.pow(finalBase, D) <= val; D++) {}Math.pow(1, D)永远等于1,只要转换后的十进制值val≥1,循环条件就一直成立,D会无限增大,程序直接陷入死循环,自然不会输出任何报错信息。 - 输入不匹配异常未处理:如果用户输入非整数(比如字符串)作为基数,
Scanner.nextInt()会抛出InputMismatchException,但你的程序没捕获这个异常,会直接终止,表现为控制台空白。
修复步骤
1. 启用验证逻辑
在转换前调用isValidInteger,同时补充对初始基数initialBase的合法性检查(原方法只验证了finalBase,初始基数也需要确保在2-36之间)。
2. 修复无限循环问题
在计算新基数位数前,先通过验证确保finalBase合法,同时用整数累乘代替Math.pow优化位数计算,避免浮点数精度问题和死循环。
3. 处理输入异常
给输入部分添加异常捕获,当用户输入非整数时,友好提示错误并终止程序。
修复后的完整代码
import java.util.InputMismatchException; import java.util.Scanner; public class BaseConversion { public static void main(String[] args) { Scanner s = new Scanner(System.in); String theValue; String newNum; int initialBase = 0; int finalBase = 0; try { System.out.println("Please enter a value: "); theValue = s.nextLine(); System.out.println("Please enter original base: "); initialBase = s.nextInt(); // 验证初始基数合法性 if (initialBase < 2 || initialBase > 36) { System.out.println("Error: Original base must be between 2 and 36"); System.exit(1); } // 验证输入数值在初始基数下是否合法 isValidInteger(theValue, initialBase); System.out.println("Please enter new base: "); finalBase = s.nextInt(); // 验证目标基数合法性 isValidInteger(theValue, finalBase); s.close(); newNum = convertInteger(theValue, initialBase, finalBase); System.out.println("new number: " + newNum); } catch (InputMismatchException e) { System.out.println("Error: Base must be an integer between 2 and 36"); System.exit(1); } } public static void isValidInteger(String num, int base) { if (base < 2 || base > 36) { System.out.println("Error: Base must be greater than or equal to 2 & less than or equal to 36"); System.exit(1); } char chDigit; for(int d = 0; d < num.length(); d++) { chDigit = num.toUpperCase().charAt(d); if(Character.isDigit(chDigit) && (chDigit - '0') >= base) { System.out.println("Error: Digit '" + chDigit + "' is invalid for base " + base); System.exit(1); } else if (Character.isLetter(chDigit) && (chDigit - 'A') + 10 >= base) { System.out.println("Error: Digit '" + chDigit + "' is invalid for base " + base); System.exit(1); } else if (!Character.isDigit(chDigit) && !Character.isLetter(chDigit)) { System.out.println("Error: Character '" + chDigit + "' is not a valid digit"); System.exit(1); } } } public static String convertInteger(String theValue, int initialBase, int finalBase) { long val = 0; // 用long代替double,避免精度丢失 long decDigit = 0; char chDigit; int L = theValue.length(); for(int p = 0; p < L; p++) { chDigit = Character.toUpperCase(theValue.charAt(L-1-p)); if(Character.isLetter(chDigit)) { decDigit = chDigit - 'A' + 10; } else if (Character.isDigit(chDigit)) { decDigit = chDigit - '0'; } else { System.out.println("Error: Invalid character in input"); System.exit(1); } // 用累乘代替Math.pow,避免精度问题 val += decDigit * power(initialBase, p); } // 计算新基数下的位数,处理0的特殊情况 int D = 1; long powerVal = finalBase; if (val != 0) { while (powerVal <= val) { powerVal *= finalBase; D++; } } char[] newNum = new char[D]; long currentVal = val; for(int p = D-1; p >= 0; p--) { long pwr = power(finalBase, p); decDigit = currentVal / pwr; currentVal -= decDigit * pwr; if(decDigit <= 9) { newNum[D-1-p] = (char) ('0' + decDigit); } else { newNum[D-1-p] = (char) ('A' + (decDigit - 10)); } } return new String(newNum); } // 自定义整数幂方法,避免Math.pow的精度问题 private static long power(int base, int exponent) { long result = 1; for (int i = 0; i < exponent; i++) { result *= base; } return result; } }
额外优化点
- 把
double类型的val改成long,避免浮点数精度丢失导致的大数值转换错误。 - 自定义
power方法代替Math.pow,确保整数计算的准确性。 - 增强错误提示信息,让用户明确知道具体错误原因。
- 处理了输入0的特殊情况,避免转换逻辑出错。
内容的提问来源于stack exchange,提问作者Austin Johnson
相关产品推荐
相关产品推荐

