【问题标题】:Why do I get NumberFormatException while converting String Array to int Array?为什么在将 String Array 转换为 int Array 时出现 NumberFormatException?
【发布时间】:2019-03-11 16:06:36
【问题描述】:

当我在 IntelliJ 上运行我的代码时,我没有收到错误消息。但是,当我尝试提交我正在处理的作业的代码时,我得到了两个测试用例的 NFE。我删除了我的所有代码,只让下面的代码在测试用例中运行。这里的某个地方一定是NumberFormatException

public class Search {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        sc.nextLine();
        int[] list = new int[n];
        String [] tokens = sc.nextLine().trim().split(" ");

        for (int i=0; i<tokens.length;i++){
            list[i]=Integer.parseInt(tokens[i]);
        }
    }
}

我阅读了有关双空格的信息并通过以下方式进行了检查:System.out.println(Arrays.asList(tokens).contains("")); 输出为假,所以这不是一个选项。如您所见,我已经在使用trim()。 我会很感激你的帮助。 路易斯

编辑: 好吧,这里有些可疑。我加了

System.out.println(Arrays.asList(tokens).contains(""));
    System.out.println(Arrays.toString(tokens));

到我的代码并把它交给测试用例。虽然 IntelliJ 会传递 false 后跟整数数组,但测试用例输出: 真的 [] . 因此,你们都是对的,我只是错误地假设我的测试用例中的输入与我在作业中给出的示例输入相似。

编辑2:

好的! 我想到了。测试用例的输入与我的测试输入中的格式完全不同,看起来有点像这样:

10
8 8 9 12 110 111 117 186 298 321
2
8 13

我假设我包含的 sc.nextLine() 跳过了我需要制作列表的整数。 所以实际的问题不是多余的空格或任何东西,只是我通过使用 sc.nextLine() 超越了我想要的输入。 给出了我需要的提示的答案,即使我认为这不是有意的,来自 Andronicus。 无论如何都要感谢其他人。

【问题讨论】:

  • 在解析之前尝试记录tokens[i]。你会知道,是什么导致了 NFE。
  • 是的,您的令牌中有一个非整数,这会导致 NFE。可能有某种测试用例正在针对您的代码运行,这些代码传入非数字。
  • 使用这个split("\\s+") 而不是split(" ")
  • 这也是我想出的解释。但是请看一下输入的 Im:10 8 8 9 12 110 111 117 186 298 321 这是我输入的前两行。对我来说,这看起来没有任何非整数标记。我还尝试打印出我的令牌数组。结果如下所示:[8, 8, 9, 12, 110, 111, 117, 186, 298, 321] 也没有非整数成员
  • 上述输入适用于您发布的代码。这意味着这不是整个代码(所以问题出在其他地方)或者这不是您传递的输入。

标签: java regex string numberformatexception parseint


【解决方案1】:

如果您知道将有一个整数作为输入并且您不担心解析,为什么不改用它呢?

int input = sc.nextInt();

在您的解决方案中,您必须这样做:

Arrays.stream(sc.nextLine().trim().split(" ")).filter(s -> !s.matches("\\s")).toArray(String[]::new);
\\ or simplier
sc.nextLine().trim().split("\\s+")

【讨论】:

  • 这是一个很好的观点。我什至可能会这样做,但我仍然想了解为什么我的版本不起作用。
  • 因为那些空白你需要去掉
  • @Louis 我已经添加了一些解释
  • 正如我在编辑中提到的,问题是 InputFormat 与预期不同。输入中的换行符可能比我预期的要少。因此,我通过使用 sc.nextLine() 跳过了部分输入。我只使用 sc.nextInt() 解决了这个问题。你的回答是正确的。
【解决方案2】:

有很多可能的原因:

  1. tokens 中有一个非数字——例如。 9 1! 3 x 3 ...
  2. 令牌被多个空格分开——例如9 3

您应该能够通过数字格式异常的文本来判断。例如,在多个空格的情况下,您会得到:

线程“main”java.lang.NumberFormatException 中的异常:对于输入字符串:“”

对于非数字(例如“a”),你会得到:

线程“main”java.lang.NumberFormatException 中的异常:对于输入字符串:“a”

当然,有许多可能的解决方案取决于您在遇到无效输入时想要做什么(您是否忽略它?抛出一个特殊异常?尝试去除非数字?)

当您知道输入由空格分隔,但不知道有多少空格时,您可以使用正则表达式在 split 命令中定位多个空格:

str.split("\\s+"); // splits on one or more whitespace including tabs, newlines, etc.

然后,要处理令牌列表中的非数字,您可以在 for 循环中添加检查:

for(int i = 0; i < tokens.length; i++) {
  if(tokens[i].matches("\\d+")) {
    list[i] = Integer.parseInt(tokens[i]);
  } else {
    // Handle error case for non-digit input
  }
}

【讨论】:

    【解决方案3】:

    这可能是由于数字之间有多余的空格。

    例如,

    9    8 7 9    1
      ^^       ^^
    *Note: You have more than one spaces here.
    

    这就是你的数组在拆分后的样子,

    tokens = {"9", "", "", "", "8", "7", "9", "", "", "", "1"}
    

    由于多余的空格,上面会抛出NumberFormatException

    你可以再试试trimming的内容,

    int i = 0;
    for (String token : tokens){
        token = token.trim();
        if (!"".equals(token)) {
            list[i++] = Integer.parseInt(token);
        }
    }
    

    【讨论】:

    • 这是错误的。该数组将如下所示:{"9","","","8","7",...}。我知道这一点,因为我试过了。 ;)
    • @RoddyoftheFrozenPeas 是的,你是对的。我已经编辑了我的答案以反映这一点。
    • 因为我打印出数组,它看起来像这样: [8, 8, 9, 12, 110, 111, 117, 186, 298, 321] 我确信多余的空格不会是我的问题的原因。
    • 它仍然关闭。令牌数组中永远不会有 any 空格,因为那是您的拆分字符。将有一个空字符串代替每个双倍空格。
    【解决方案4】:

    请将您的代码修改为:

    public class Example {
    
        public static void main(String[] args) {
            Scanner sc = new Scanner(System.in);
            System.out.println("Enter the size of the array : ");
            int n = sc.nextInt();
            sc.nextLine();
            int[] list = new int[n];
            System.out.println("Enter a string : ");
            /** This regex will work for string having more than one space. */ 
            String trimmedToken = sc.nextLine().replaceAll("\\s+", " ");
            String[] tokens = trimmedToken.split(" ");
            for (int i = 0; i < tokens.length; i++) {
                list[i] = Integer.parseInt(tokens[i]);
                System.out.println(list[i]);
            }
            sc.close();
        }
    
    }
    

    控制台输入:

    Enter the size of the array : 
    5
    Enter a string : 
    1       2     3      4    5
    

    输出:

    1
    2
    3
    4
    5
    

    【讨论】:

    • 输入仍然失败:1 2 3 x y z
    • 这失败了,因为 String 到 int 的显式类型转换是在他的代码中完成的。因此,您不能发送不可转换为整数的字符串值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 2019-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多