在Java中解析负数的问题

时间:2019-09-28 12:15:58

标签: java parsing split

我有一个已解析的字符串,我可以拆分所有必要的项。我可以采用以下值: “ |您在一个黑暗的大房间中| false 1 -1 -1 2“,                 “ |您在黑暗的大房间中| false -1 0 -1 -1”,                 “ |您在一个大房间里,很暗| false 0 0 3 0”,                 “ |您在黑暗的房间里,很小| true 0 0 0 0“ 然后我可以获得描述,正确/错误值以及所有数字。但是,当我尝试将数字解析为整数值时,出现数字异常错误。

我最初尝试使用整数roomValue和扫描仪roomString将getNextInt()放入roomValue。那可怕地失败了。下面的代码将所有内容拆分开来,但是一旦我尝试分配字符串数组的整数值,就会收到错误消息。

        description = fullDesc.substring(1, fullDesc.indexOf("| "));
        gameRooms[roomNumber] = new Room(description);
        fullDesc = fullDesc.substring(fullDesc.indexOf("| ") + 2);

        if (fullDesc.contains("true")) 
            gameRooms[roomNumber].putGrail();
        fullDesc = fullDesc.substring(fullDesc.indexOf(" "));       
        String[] roomString = fullDesc.split(" ");
        Integer[] adjRoomNum = new Integer[roomString.length];
        for (int i = 0; i < roomString.length; i++) {
            //adjRoomNum[i] = Integer.parseInt(roomString[i]);
            //System.out.println(adjRoomNum[i]);
            System.out.println((roomString[i]));
        }

        /*
        roomValue = roomString.nextInt();
        if ((roomValue) >= 0)
            gameRooms[roomNumber].setAdjacent(0, gameRooms[Integer.valueOf(roomValue)]);
        else if ((roomValue) == -1)
            gameRooms[roomNumber].setAdjacent(0, null);
        roomString  
        roomValue = roomString.nextInt();
        if ((roomValue) >= 0)
            gameRooms[roomNumber].setAdjacent(1, gameRooms[Integer.valueOf(roomValue)]);
        else if ((roomValue) == -1)
            gameRooms[roomNumber].setAdjacent(1, null);
        roomValue = roomString.nextInt();
        if ((roomValue) >= 0)
            gameRooms[roomNumber].setAdjacent(2, gameRooms[Integer.valueOf(roomValue)]);
        else if ((roomValue) == -1)
            gameRooms[roomNumber].setAdjacent(2, null);
        roomValue = roomString.nextInt();
        if ((roomValue) >= 0)
            gameRooms[roomNumber].setAdjacent(3, gameRooms[Integer.valueOf(roomValue)]);
        else if ((roomValue) == -1)
            gameRooms[roomNumber].setAdjacent(3, null);

我收到以下错误:

Exception in thread "main" java.lang.NumberFormatException: For input string: ""
    at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.base/java.lang.Integer.parseInt(Integer.java:662)
    at java.base/java.lang.Integer.parseInt(Integer.java:770)
    at Controller.buildRoom(Controller.java:30)
    at Game.main(Game.java:67)

字符串的输出是


1
-1
-1
2

-1
0
-1
-1

0
0
3
0

0
0
0
0

我想要的是

1
-1
-1
2
-1
0
-1
-1
0
0
3
0
0
0
0
0

我看到有空格被读取到字符串数组的第一个值中,并将解析引发为数字格式异常。我试图删除空白,但是没有成功。

3 个答案:

答案 0 :(得分:0)

如果您的roomString数组包含类似“ 1”或“ -1”的字符串,则可以执行以下部分

for (int i = 0; i < roomString.length; i++) {
  if(roomString[i].charAt(0) == '-'){
    roomString[i] = roomString[i].substring(1);
    adjRoomNum[i] = Integer.parseInt(roomString[i]) * (-1);
  }else{
    adjRoomNum[i] = Integer.parseInt(roomString[i]);
  }
}

答案 1 :(得分:0)

您在减号和第一个数字之间有空格, 完成拆分后-String [] roomString = fullDesc.split(“”); 第一个字符串为空字符串 所以解析失败 您应该避免使用它,或者将其删除或拆分

if(fullDesc.startWith("")) {
//substring
}

答案 2 :(得分:0)

Integer.parseInt()方法接受带符号(负)整数值(如“-1024” )的字符串表示形式并将其转换字符串至 int 。实际上,它还会接受“ + 1024” 之类的内容。它不会转换的是Null,Null字符串(“”)或包含一个或多个字母字符(包括空格)的任何数字字符串。您显示的错误消息表示试图通过 Integer.parseInt()方法传递空字符串(“” )。

恕我直言,在执行转换之前验证字符串是一个好主意,从而消除了生成异常的烦恼,或者至少可以尝试捕获异常并加以处理。

使用String#matches()方法验证数字字符串:

在此示例中,String#matches()方法与Regular Expression(RegEx)一起使用以验证 roomString [i] 数组元素中包含的字符串确实是有符号或无符号整数数值的字符串表示形式。如果不是,则会向控制台显示错误消息,并继续处理下一个数组元素。

for (int i = 0; i < roomString.length; i++) {
    // Trim off an possible leading or trailing whitespaces.
    roomString[i] = roomString[i].trim();
    if (!roomString[i].matches("\\+?\\d+|\\-?\\d+")) {
        System.err.println("The value " + roomString[i] + " located at " + 
                           "index " + i + " can not be converted to Integer!");
        continue;  // continue processing the remaining array.
    }
    adjRoomNum[i] = Integer.parseInt(roomString[i]);
    System.out.println(adjRoomNum[i]);
    //System.out.println((roomString[i]));
}

使用的RegEx("\\+?\\d+|\\-?\\d+")表示:

  • \\+?\\d+如果字符串以字母 + 开头 然后是一个或多个0到9的数字
  • |
  • \\-?\\d+"如果字符串以文字-字符开头或 不,然后跟一个或多个0到9的数字。

您很可能不需要\\+?\\d+|部分,可以将其保留在表达式之外。

捕获NumberFormatException:

for (int i = 0; i < roomString.length; i++) {
    // Trim off an possible leading or trailing whitespaces.
    roomString[i] = roomString[i].trim(); 
    try {
        adjRoomNum[i] = Integer.parseInt(roomString[i]);
    }
    catch (NumberFormatException ex) {
        System.err.println("The value " + roomString[i] + " located at " + 
                           "index " + i + " can not be converted to Integer!");
        continue;  // continue processing the remaining array.
    }

    System.out.println(adjRoomNum[i]);
    //System.out.println((roomString[i]));
}

您是如何获取空字符串(“”)的?

基于空格分析字符串时,特别是如果来自用户输入的字符串,则总是有可能在某处提供了双空格,或者在您的情况下提供了单个前导空格(更多稍后)。要解决此难题,请始终使用String#trim()方法修剪字符串,以在分割字符串之前 删除前导空格和尾随空格。

解析和分割您的特殊字符串:

通常,您的解析工作正常,但是您会注意到在运行此代码行时:

fullDesc = fullDesc.substring(fullDesc.indexOf(" "));

fullDesc 变量将使用前导和尾随空格来保存字符串的整数值,例如:" 1 -1 -1 2 "。您不希望这样做,因为它会拆分为:"", "1", "-1", "-1", "2"。由于前导空格,您的 roomString 数组将包含一个Null String元素,并且 Integer.parseInt()方法将无法处理那些元素,因此抛出 NumberFormatException < / strong>。解决方案很简单,只需将 1 添加到子字符串索引或将 trim()方法添加到代码行的末尾。修改上面的代码行:

fullDesc = fullDesc.substring(fullDesc.indexOf(" ") + 1);

                          O R

// Covers almost all the 'just in case' situations.
fullDesc = fullDesc.substring(fullDesc.indexOf(" ")).trim(); 

但是,这并没有涵盖您想分割字符串时值之间双倍间隔的可能情况,例如:

    "1  -1 -1  2"

在这里,我们在1和-1之间有一个双倍空格,而在-1和2之间又是一个双倍空格。当根据单个空格(String[] roomString = "1 -1 -1 2".split(" ");)分割此字符串时,您将得到六个数组元素,其中两个将是Null字符串("1", "", "-1", "-1", "", "2"),再次,当Null字符串为时, Integer.parseInt()方法将最终抛出 NumberFormatException

该解决方案,请勿在split方法中使用" "。请改用"\\s+"。这个小的正则表达式告诉split()方法在 一个或多个 空格上分割字符串。

在处理字符串数字时,您想使用 Integer.parseInt() Double.parseDouble()或数字中的任何空格来解析它们字符串会造成严重破坏,无论您使用的分隔符是什么。以以下示例为例,用户在控制台应用程序中输入了以逗号(,)分隔的数字字符串:

"1, 2, 3,4,5 ,6 ,7,8 , 9 , 10"

这里有四种不同的定界情况:

1) 1, 2
2) 3,4
3) 5 ,6
4) , 9 ,

如果要拆分此字符串,请说:

String[] values = "1, 2, 3,4,5 ,6 ,7,8 , 9 , 10".split(",");

您的values数组将保存:

["1", " 2", " 3", "4", "5 ", "6 ", "7", "8 ", " 9 ", " 10"]

当您尝试通过 Integer.parseInt()方法解析这些元素时,所有其中包含空格的数组元素都将导致 NumberFormatException 。涵盖所有基础的解决方案可能是这样拆分的:

String[] values = "1, 2, 3,4,5 ,6 ,7,8 , 9 , 10".split("\\s{0,},\\s{0,}");

此正则表达式是什么意思:"\\s{0,},\\s{0,}"?即使在逗号之前或之后有0个或多个空格,也要对逗号进行分割。

您的代码可能看起来像这样:

String[] gameStrings = {
    "|You're in a large dark room| false 1 -1 -1 2 ",
    "|You're in a dark large room| false -1 0 -1 -1 ",
    "|You're in a large room, very dark| false 0 0 3 0 ",
    "|You're in a dark room, very small| true 0 0 0 0 "
};

for (int s = 0; s < gameStrings.length; s++) {
    String fullDesc = gameStrings[s];
    String description = fullDesc.substring(1, fullDesc.indexOf("| "));
    gameRooms[roomNumber] = new Room(description);
    fullDesc = fullDesc.substring(fullDesc.indexOf("| ") + 2);

    if (fullDesc.contains("true")) {
        gameRooms[roomNumber].putGrail();
    }
    fullDesc = fullDesc.substring(fullDesc.indexOf(" ")).trim();
    String[] roomString = fullDesc.split("\\s+");
    Integer[] adjRoomNum = new Integer[roomString.length];

    for (int i = 0; i < roomString.length; i++) {
        if (!roomString[i].trim().matches("\\+?\\d+|\\-?\\d+")) {
            System.err.println("The value " + roomString[i] + " located at "
                    + "index " + i + " can not be converted to Integer!");
            continue; // Continue processing array elements.
        }
        adjRoomNum[i] = Integer.parseInt(roomString[i]);
        System.out.println(adjRoomNum[i]);
    }
}