【问题标题】:"Find substring in char[]" getting unexpected results“在 char[] 中查找子字符串”得到意想不到的结果
【发布时间】:2019-07-09 05:01:09
【问题描述】:

免责声明:这是一个家庭作业问题。我正在尝试编写一个 contains(java.lang.String subString) 方法,该方法返回一个 int 值,该值表示主字符串中比较字符串的索引,用于定制的 String 类。

一些规则:

  • 没有集合类
  • 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 [FAIL](应该是-1

主字符串:asasasf
比较字符串:asf
结果:0 [FAIL](应该是4

cmets 反映了代码的预期工作方式。然而很明显,当它到达第二个for 循环时,逻辑会以某种方式分解以给出上述结果。但我看不到问题所在。我可以再看看这个吗?

【问题讨论】:

  • 您的内部 for 循环只能迭代一次,因为其中的 if 语句的两个分支都返回索引。我认为您的意思是检查 for 循环是否在没有匹配的情况下终止,但您总是返回 -1 或 1,具体取决于第一个字符是否匹配。
  • 这很有意义。是用continue 替换其中一个返回语句的解决方案吗?
  • 我认为您可以将第二个 return index 移到 for 循环之外。只有在循环内的检查没有返回 -1 时,您才能达到此目的。不是在带有 IDE 的计算机上,所以我实际上无法尝试... ;-)
  • 旁注:我认为这是我见过的在作业中寻求帮助的最佳问题之一。这显示了相当程度的研究、反复试验和理解。也直接告诉我们这是分配任务。
  • 首先,对于某些失败的条件,只需返回一个常量-1(您可以在方法的开头声明一个final int)。对于内循环,你应该使用break在满足失败条件时跳出内循环,这将导致外循环继续。

标签: java arrays methods char


【解决方案1】:
//If we get here, it means whole subString match found
//Return the index (=i) we set earlier
else {
    return index;
}

不幸的是,这个假设是不正确的。如果到达那里,则意味着两个子字符串的第二个字符相同,因为if-else 语句只会执行一次,并且两端都包含return

既然我已经诊断出问题,解决这个问题的方法可能很容易,但我想更进一步。我们每天尝试编写代码的方式是让我们使用的代码可维护、可重用和可测试

这基本上意味着我们这里的函数可以很容易地分割成不同的小函数,一个接一个地调用,我们可以为此编写单元测试并接收关于一组逻辑语句是否适合的快速反馈。

【讨论】:

  • 谢谢亚辛。我能够使用其他人的 cmets 解决这个特定问题,但您的建议很有价值,将有助于我进一步的编码工作。
  • @Soundscape 很高兴我能帮上忙。祝你好运,写出这样干净的代码和问题;)。跟上
【解决方案2】:

在 cmets 中 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 新手,所以我希望这个解释是有道理的。

【讨论】:

  • 在比较子字符串的最后一个char 时需要返回index(它也必须是匹配的)。在执行"hello".contains("ll") 时,您当前的实现可能会失败。 (虽然我没有运行它来测试)
猜你喜欢
  • 1970-01-01
  • 2015-01-13
  • 2021-04-22
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
  • 1970-01-01
  • 2013-04-06
  • 2023-04-08
相关资源
最近更新 更多