在char[]中查找子字符串,得到了意外的结果。

6
免责声明:这是一道做作业的问题。我正在尝试编写一个contains(java.lang.String subString)方法,该方法为自定义的String类返回表示比较字符串在主字符串内的索引的int值。
一些规则:
  • 不使用集合类
  • 仅允许使用java String类中的charAt()和toCharArray()(但允许使用其他类的方法)
  • 假设length()返回主字符串的长度(这正是它所做的)
我的代码:
public int contains(java.lang.String subString) {
    this.subString = subString;
    char[] arrSubStr = this.subString.toCharArray();
    //Create initial fail
    int index = -1;
    //Make sure comparison subString is the same length or shorter than the primary string
    if(arrSubStr.length > length()) {
        return index;
    }
    //Steps to perform if initial conditions are met
    else {
        //Compare first character of subString to each character in primary string
        for(int i = 0; i < length(); i++) {
            //When a match is found...
            if(arrSubStr[0] == this.content[i]) {
                //...make sure that the subString is not longer than the remaining length of the primary string
                if(arrSubStr.length > length() - i) {
                    return index;
                }
                //Proceed matching remainder of subString
                else {
                    //Record the index of the beginning of the subString contained in primary string
                    index = i;
                    //Starting with second character of subString...
                    for(int j = 1; j < arrSubStr.length;) {
                        //...compare with subsequent chars of primary string, 
                        //and if a failure of match is found, reset index to failure (-1)
                        if(arrSubStr[j] != this.content[j+i]) {
                            index = -1;
                            return index;
                        }
                        //If we get here, it means whole subString match found
                        //Return the index (=i) we set earlier
                        else {
                            return index;
                        }
                    }
                }
            }
        }
    }
return index;
}

测试结果:

原始字符串: asdfg
比较字符串: donkey
结果: -1 [通过]

原始字符串: asdfg
比较字符串: asdfg
结果: 0 [通过]

原始字符串: asdfg
比较字符串: g
结果: 4 [通过]

原始字符串: asasasf
比较字符串: asd
结果: 0 [失败] (应该是-1)

原始字符串: asasasf
比较字符串: asf
结果: 0 [失败] (应该是4)

注释反映了代码的意图。但很明显,当它达到第二个for循环时,逻辑出现了问题,导致上面的结果。但我看不出问题所在。能否请您再看一下?


2
你的内部for循环只能迭代一次,因为if语句中的两个分支都返回索引。我认为你的意思是要检查for循环是否在没有匹配的情况下终止,但你总是返回-1或1,具体取决于第一个字符是否匹配。 - azurefrog
这非常有道理。解决方案是用 continue 替换其中一个 return 语句吗? - Soundscape
1
我认为你可以将第二个 return index 移到 for 循环之外。只有在循环内部的检查没有返回 -1 时,才会到达该语句。我现在没有带有 IDE 的电脑,所以无法实际尝试...;-) - azurefrog
4
旁注:我认为这是我看过的关于作业求助中最好的问题之一。这表明提问者进行了相当程度的研究、尝试和理解。而且他们直截了当地告诉我们这是为了作业。 - Jai
1
首先,对于一些必定失败的情况,只需返回一个常量“-1”(您可以在方法开头声明一个final int)。对于内部循环,当遇到失败条件时,应使用“break”跳出内部循环,这将导致外部循环继续执行。 - Jai
解决了!我会发布解决方案。感谢azurefrog和Jai,你们都非常有帮助。 - Soundscape
2个回答

1
//If we get here, it means whole subString match found
//Return the index (=i) we set earlier
else {
    return index;
}

很不幸,这个假设是不正确的。如果你到达那里,意味着两个子字符串的第二个字符是相同的,因为if-else语句只会执行一次且两端都包含一个return
解决这个问题的方法可能很容易,现在我已经诊断出了问题,但我想进一步探讨这个问题。我们日常编写代码的方式是让我们使用的代码易于维护、重用和可测试。
这基本上意味着我们这里的函数可以轻松分解成不同的小函数,依次调用,我们可以编写单元测试,并快速获得逻辑语句集是否适合的反馈。

1
谢谢Yassin。我已经通过其他人的评论解决了这个具体问题,但是您的建议非常有价值,将有助于我的进一步编码工作。 - Soundscape
1
@Soundscape 很高兴我能帮到你。祝你好运,并且写出如此干净的代码和问题非常棒;)。继续保持! - Yassin Hajaj

1

在Jai和azurefrog的评论建议下,我重写了逻辑,以下是缩略版:

    if(arrSubStr.length > length()) {
        return index;
    }
    //Steps to perform if initial conditions are met
    else {
        //Compare first character of subString to each character in primary string
        for(int i = 0; i < length(); i++) {
            //When a match is found...
            if(arrSubStr[0] == this.content[i]) {
                //...make sure that the subString is not longer than the remaining length of the primary string
                if(arrSubStr.length <= length() - i) {
                    //Record the index of the beginning of the subString contained in primary string
                    index = i;
                    //Starting with second character of subString...
                    for(int j = 1; j < arrSubStr.length; j++) {
                        //...compare with subsequent chars of primary string, 
                        //and if a failure of match is found, reset index to failure (-1)
                        if(arrSubStr[j] != this.content[j+i]) {
                            index = -1;
                            break;
                        }
                    }
                }
            }
        }
    }
return index;

基本上,我从循环中删除了所有的return语句。只需适当设置index值并利用最终(外部)return语句是正确解决问题的方式。然后,我还在内部for循环中添加了一个break;,以确保无法匹配会继续循环。我相信仍然存在不必要的代码,但只要它仍然通过必要的测试,我就鼓励将其留下来。 :)
我仍然是Java的新手,所以希望这个解释有意义。

当你比较子字符串的最后一个字符时(它也必须匹配),你需要返回index。你当前的实现可能在执行"hello".contains("ll")时失败。(虽然我没有运行测试) - Jai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接