Java编程:将每个单词的除第一个和最后一个字母之外的所有字母替换为“ _”

时间:2019-03-07 22:56:23

标签: java

此方法的目的是将每个单词的除第一个和最后一个字母以外的所有字母替换为“ _”。我是编码方面的新手,因此可以肯定我的代码是不正确的。我认为我的代码开始无法正常运行的地方是while循环。

编辑:如何在不使用数组或其他方法(例如split方法)的情况下制作此方法?

public static String blankWords(String s1) {

    StringBuilder sb = new StringBuilder();
    if(s1.length() > 2) {
      sb.append(s1.charAt(0));
      for(int x = 1; x < s1.length() - 1; x = x + 1) {
        char y = ' ';
        while(y != s1.charAt(x)) {
          sb.append("_");
          x = x + 1;
        }
      }
      sb.append(s1.charAt(s1.length() - 1));
      return sb.toString();
    }
    return s1;
  }

我的代码输出什么:

  

HW2.blankWords(“这是一个测试。”)   java.lang.StringIndexOutOfBoundsException:字符串索引超出范围:15       在java.lang.String.charAt(未知来源)       在HW2.blankWords(HW2.java:73)

我的代码应输出什么:

  

HW2.blankWords(“这是一个测试。”)   “ T__s是T__t。”

4 个答案:

答案 0 :(得分:0)

这是一个非常简单的解决方案:

class Scratch {
    public static void main(String[] args) {
        System.out.println(blankWords("My name is sam orozco"));
    }

    public static String delim = "_";

    public static String blankWords(String s1) {
        // this split arg on one or more space
        String[] words = s1.split("\\s+");
        StringBuilder response = new StringBuilder();
        for (String val : words) {
            val = convertWord(val);
            response.append(val).append(" ");
        }
        return response.toString().trim();
    }


    public static String convertWord(String val) {
        int len = val.length();
        StringBuilder bldr = new StringBuilder();
        int index = 0;
        for (char ch : val.toCharArray()) {
            if (index == 0 || index == len - 1) {
                bldr.append(ch);
            } else {
                bldr.append(delim);
            }
            index++;
        }
        return bldr.toString();
    }
}

答案 1 :(得分:0)

您可以使用StringTokenizer执行此操作,该操作将基于定界符列表提取单词。由于要将这些定界符保留在输出中,因此将指示令牌化程序将其作为令牌返回:

String blankWords(String s) {
    // build a tokenizer for your string, listing all special chars as delimiters. The last argument says that delimiters are going to be returned as tokens themselves (so we can include them in the output string)
    StringTokenizer tokenizer = new StringTokenizer(s, " .,;:?!()[]{}", true);
    // a helper class to build the output string; think of it as just a more efficient concat utility
    StringBuilder sb = new StringBuilder();
    while (tokenizer.hasMoreTokens()) {
        String blankWord = blank(tokenizer.nextToken());
        sb.append(blankWord);
    }
    return sb.toString();
}

/**
 * Replaces all but the first and last characters in a string with '_'
 */
private String blank(String word) {
    // strings of up to two chars will be returned as such
    // delimiters will always fall into this category, as they are always single characters
    if (word.length() <= 2) {
        return word;
    }
    // no need to iterate through all chars, we'll just get the array
    final char[] chars = word.toCharArray();
    // fill the array of chars with '_', starting with position 1 (the second char) up to the last char (exclusive, i.e. last-but-one)
    Arrays.fill(chars, 1, chars.length - 1, '_');
    // build the resulting word based on the modified array of chars
    return new String(chars);
}

以下是使用TestNG验证此实现的测试内容:

@Test(dataProvider = "texts")
public void testBlankWords(String input, String expectedOutput) {
    assertEquals(blankWords(input), expectedOutput);
}

@DataProvider
public Object[][] texts() {
    return new Object[][] {
            {"This is a test.", "T__s is a t__t."},
            {"This one, again, is (yet another) test!", "T__s o_e, a___n, is (y_t a_____r) t__t!"}
    };
}

此实现的主要缺点是StringTokenizer要求您手动列出所有定界符。使用更高级的实现,您可以将定界符视为返回falseCharacter.isAlphabetic(c)的任何字符,或者决定定义非单词字符。


P.S。 如上所述,这可能是“更高级的实现”:

static String blankWords(String text) {
    final char[] textChars = text.toCharArray();
    int wordStart = -1; // keep track of the current word start position, -1 means no current word
    for (int i = 0; i < textChars.length; i++) {
        if (!Character.isAlphabetic(textChars[i])) {
            if (wordStart >= 0) {
                for (int j = wordStart + 1; j < i - 1; j++) {
                    textChars[j] = '_';
                }
            }
            wordStart = -1; // reset the current word to none
        } else if (wordStart == -1) {
            wordStart = i;  // alphabetic characters start a new word, when there's none started already
        } else if (i == textChars.length - 1) { // if the last character is aplhabetic
            for (int j = wordStart + 1; j < i; j++) {
                textChars[j] = '_';
            }
        }
    }
    return new String(textChars);
}

答案 2 :(得分:-1)

不需要while循环!

向前看1个字符以查看它是否为空格,或者当前字符是否为空格,在这种情况下,请附加它。否则,请确保添加下一个字符(skipNext false)。

总是添加最后一个字符

public static String blankWords(String s1) {
    StringBuilder sb = new StringBuilder();
    if(s1.length() > 2) {
      Boolean skipNext = false;
      for(int x = 0; x < s1.length() - 1; x = x + 1) {
        if(s1.charAt(x) == ' ' || s1.charAt(x + 1) == ' ') {
            sb.append(s1.charAt(x));
            skipNext = false;
        }
        else {
            if(skipNext) {
                sb.append('_');
            }
            else {
                sb.append(s1.charAt(x));
                skipNext = true;
            }
        }

      }
      sb.append(s1.charAt(s1.length() - 1));
      return sb.toString();
    }
    return s1;
}

答案 3 :(得分:-2)

对于更高级的程序员,请使用正则表达式。

public static String blankWords(String s1) {
    return s1.replaceAll("\\B\\w\\B", "_");
}

这可以正确保留最后的t,即blankWords("This is a Test.")返回"T__s is a T__t."