【问题标题】:What is causing this StringIndexOutofBounds exception?是什么导致了这个 StringIndexOutofBounds 异常?
【发布时间】:2016-01-15 02:36:23
【问题描述】:

我有这段代码可以在下面找到一个回文;我需要能够从用户输入字符串中删除所有数字、空格和标点符号,所以我一直在使用replaceAll。当我的代码中只有String input = str.toLowerCase();String newInput = input.replaceAll("[0-9]+", ""); 时,没有问题。它删除数字并继续。但是,当我尝试添加标点符号或空格时,我得到了 StringIndexOutOfBoundsException。

示例:我输入 Anna.55

所有replaceAll 语句下方的行System.out.println(newestInput); 将打印出anna,但在到达while 循环时立即抛出错误并指出问题出在索引6 上。

据我了解(我仍在学习 Java 并且不熟悉 replaceAll)删除带有 replaceAll("\\s", "") 的空格将删除之前的 replaceAll 语句留下的空格,因此不会有索引 6(甚至4)。索引 6 不再存在时如何出现错误?

import java.util.Scanner;

public class PalindromeTester {
    public static void main (String[] args) {
        String str;
        String another = "y";
        int left;
        int right;
        Scanner scan = new Scanner (System.in);
        while (another.equalsIgnoreCase("y")) {
            System.out.println("Enter a potential palindrome:");
            str = scan.nextLine();  
            left = 0;
            right = str.length() - 1;           
            String input = str.toLowerCase(); 
            String newInput = input.replaceAll("[0-9]+", "");
            String newerInput = input.replaceAll("\\W", "");
            String newestInput = newerInput.replaceAll("\\s", "");           
            System.out.println(newestInput);
            while (newestInput.charAt(left) == newestInput.charAt(right) && left < right) {
                left++;
                right--;
            }
             System.out.println();
            if (left < right)
                System.out.println("That string is not a palindrome.");
            else 
                System.out.println("That string is a palindrome.");
            System.out.println();
            System.out.print ("Test another palindrome (y/n)? ");
            another = scan.nextLine();
        }
    }
}

【问题讨论】:

  • 首先input.replaceAll("\\W", "")不应该在这里使用newInput吗?第二:您认为在减小源字符串的大小之前计算right 是个好主意吗?
  • How is there an error at index of 6 when it no longer exists? 这样不是回答你的问题吗?您需要包含堆栈跟踪的相关部分,以便人们有更好的机会帮助您。

标签: java string indexing replaceall


【解决方案1】:

您正在使用right = str.length() - 1; 来确定输入的长度,但是您修改了它之后的输入内容(以及您比较的内容)...

String input = str.toLowerCase();
String newInput = input.replaceAll("[0-9]+", "");
String newerInput = input.replaceAll("\\W", "");
String newestInput = newerInput.replaceAll("\\s", "");

System.out.println(newestInput);
while (newestInput.charAt(left) == newestInput.charAt(right) && left < right) {

这意味着 String 不再是原始长度,在您的示例中,它的 1 字符更短

改为计算newestInput的长度

right = newestInput.length() - 1;
System.out.println(newestInput);
while (newestInput.charAt(left) == newestInput.charAt(right) && left < right) {

【讨论】:

  • “它短了 1 个字符” .. 这很有趣,应该短 3 个字符:D。但是解决这个问题很简单,所以它不再有趣了。
  • 输入 = Anna.55 输出 = anna55;事实上,OP 在 String 的错误实例上使用 repalceAll,好吧,鉴于问题的性质,我想他们会得到 1 张“免费调试”卡;)
  • 这是我的疏忽,抱歉。我确信问题在于我如何使用replaceAll 错误,我没有检查我的陈述的顺序/放置。谢谢!
  • @SarahDiri 使用旧代码来熟悉代码调试器。在那里你可以看到每个变量“包含”。了解调试器的工作原理对于解决此类问题非常有用。
【解决方案2】:

先做两件事:

我认为

input.replaceAll("\\W", "");

应该是

newInput.replaceAll("\\W", "");

并且权利应该在令牌被删除之后而不是之前计算,如下所示:

left = 0;
String input = str.toLowerCase(); 
String newInput = input.replaceAll("[0-9]+", "");
String newerInput = newInput.replaceAll("\\W", "");
String newestInput = newerInput.replaceAll("\\s", "");
right = newestInput.length() - 1;

否则right 可以大于newestInput 的长度,你会得到一个java.lang.StringIndexOutOfBoundsException

【讨论】:

    【解决方案3】:

    实际上,测试字符串是否为回文的一种更简单的方法是前后是否相同。

    【讨论】:

      猜你喜欢
      • 2014-11-07
      • 2010-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-10
      • 1970-01-01
      相关资源
      最近更新 更多