如何使用基于指定长度的空格格式化String?

时间:2016-09-20 23:34:27

标签: java string

尝试在Java中创建一个方法,通过根据长度拉伸缓冲区的内容(通过放入适当数量的空格)来格式化字符串。因此,根据给定的特定长度,字符串的第一个字符位于第一个索引中,最后一个字符位于实际的最后一个索引本身。

public static String format(String sentence, int length) {
    if (sentence.length() >= length) {
        return sentence;
    }
    StringBuilder sb = new StringBuilder();

    String[] words = sentence.split("\\s+");

    int usedCharacters = 0;

    for (String word : words) {
        usedCharacters += word.length();
    }

    int emptyCharacters = length - usedCharacters;
    int spaces = emptyCharacters / words.length - 1;

    for (String word : words) {
        sb.append(word);
        for (int i = 0; i <= spaces; i++) {
            sb.append(" ");
        }
    }
    return sb.toString();
}

对于此单元测试,这有效:

@Test
public void isCorrectLength() {
    String value = StringUtils.format("brown clown", 20);
    assert(value.length() == 20);
}

所以,这里,最大缓冲区大小为:20

使用的字符总数为:10

未使用的字符总数为:10

最终结果(如果您打印字符串)是:

brown     clown

&#34; n&#34;在小丑是指数20 ...

但是,存在以下测试的边缘情况(导致其中断):

@Test
public void isCorrectLengthWithLongerSentence() {
    String value = StringUtils.format("Love programming Java using Eclipse!", 50);
    assert(value.length() == 50);
}

缓冲区大小:50

使用的总字符数:25 总未使用字符数:25

空格:3

最终长度:48

最终结果(如果您打印字符串)是:

Love     programming    Java    using    Eclipse!

为什么最终指数48而不是50?

感叹号&#34;!&#34;在&#34; Eclipse&#34;之后,应该是50而不是48 ......

我怀疑它是由于我的空间计算被关闭了。

感谢您花时间阅读本文。

2 个答案:

答案 0 :(得分:2)

进行此测试

@Test
public void isCorrectLength() {
    String value = StringUtils.format("Went to the slope and snowboarded for hours., 103);
    assert(value.length() == 103);
}

这是因为你要划分:

int spaces = emptyCharacters / words.length - 1;

这导致(66/8) - 1)= 7.25,然后你有一个for循环,它没有考虑额外的.25这意味着你不会填充所需的缓冲区长度。

另外,既然你把它声明为int,你就不会得到额外的0.25,所以你应该把它改为double,并将其他人也加倍。

然后你可以计算单词并检查额外0.25乘以计数器是否达到1,你添加一个空格,然后重置计数器。

    double spaces = (double)emptyCharacters / (double)words.length - 1.0;

    double extraSpace = spaces % 1;
    double counter = 0;
    for (String word : words) {
        counter++;

        sb.append(word);
        for (int i = 0; i <= spaces; i++) {
            sb.append(" ");
        }

        if ((counter * extraSpace) >= 1) {
             sb.append(" "); // This is the extra space.
             counter = 0;
        }
    }

像这样的东西。问题在于并非所有单词都可以具有相同数量的空格。为了适应静态缓冲区长度,有些会有更多,有些会有更少。这也是一种特殊情况,因为余数为0.25,并且将产生恰好2个空格,您仍然需要适应余数的剩余部分。 (如果它没有达到1,你还有一个词。)

以下代码弥补了这一点。

    double spaces = (double)emptyCharacters / (double)words.length - 1.0;

    double extraSpace = spaces % 1;
    double counter = 0;
    int wordIndex = 0;
    for (String word : words) {
        counter++;
        wordIndex++;

        sb.append(word);
        for (int i = 0; i <= spaces; i++) {
            sb.append(" ");
        }

        if ((counter * extraSpace) >= 1) {
             sb.append(" "); // This is the extra space.
             counter = 0;
        }

        if ((wordIndex == words.length - 1) && (counter * extraSpace) > 0) {
            sb.append(" "); // This accounts for remainder.
        }
    }

这在任何方面都不是优雅的,但对于之前的测试,例如,对于这个新测试,它是有效的:

@Test
public void isCorrectLength() {
    String value = StringUtils.format("We went to the giant slope and snowboarded for hours., 103);
    assert(value.length() == 103);
}

答案 1 :(得分:1)

  1. 根据空白区域将字符串拆分为单词。
  2. 找到将单词填充到所需字符串长度所需的总空格数(字符串的总长度 - 单词长度)。
  3. 找到&#34;空格块的数量&#34;放在单词之间(单词数量 - 1)。
  4. 构建&#34;空间块&#34;通过迭代地向每个空间块添加空格,直到我们用完空格(参见步骤2)。
  5. 通过放置单词,空格,单词等重新组合句子

    private static String formatString(String sentence,int length){     //用空格解析单词     String [] words = sentence.split(&#34; \ s +&#34;);

    // calc the char length of all words
    int wordsLength = 0;
    for (String w: words) {
        wordsLength += w.length();
    }
    
    // find the number of space blocks and initialize them
    int spacesLength = length - wordsLength;
    String[] spaceBlocks = new String[words.length - 1];
    Arrays.fill(spaceBlocks, "");
    
    // distribute spaces as evenly as possible between space blocks
    int spacesLeft = spacesLength;
    int k = 0;
    while (spacesLeft > 0) {
        spaceBlocks[k++] += " ";
        if (k == spaceBlocks.length) {
            k = 0;
        }
        spacesLeft--;
    }
    
    // assemble the buffer: for each word, print the word, then a spaces block, and so on
    StringBuilder b = new StringBuilder();
    for (int i = 0; i < words.length; i++) {
        b.append(words[i]);
        if (i < spaceBlocks.length) {
            b.append(spaceBlocks[i]);
        }
    }
    return b.toString();
    

    }

    public static void main(String [] args){     字符串s;     字符串t;

    s = "Hello, spaces.";
    t = formatString(s, 50);
    System.out.println(String.format("\"%s\" (length=%d)", t, t.length()));
    
    s = "Hello, spaces.";
    t = formatString(s, 51);
    System.out.println(String.format("\"%s\" (length=%d)", t, t.length()));
    
    s = "Good day, spaces.";
    t = formatString(s, 52);
    System.out.println(String.format("\"%s\" (length=%d)", t, t.length()));
    
    s = "The quick brown fox.";
    t = formatString(s, 53);
    System.out.println(String.format("\"%s\" (length=%d)", t, t.length()));
    
    s = "Ask not what your country can do for you.";
    t = formatString(s, 54);
    System.out.println(String.format("\"%s\" (length=%d)", t, t.length()));
    
    s = "Ask not what your country can do for you, Bob.";
    t = formatString(s, 55);
    System.out.println(String.format("\"%s\" (length=%d)", t, t.length()));
    

    }

  6. 输出,

    "Hello,                                     spaces." (length=50)
    "Hello,                                      spaces." (length=51)
    "Good                   day,                  spaces." (length=52)
    "The            quick            brown            fox." (length=53)
    "Ask   not   what   your   country   can  do  for  you." (length=54)
    "Ask  not  what  your  country  can  do  for  you,  Bob." (length=55)
    

    如果空间不会产生所有偶数长度的空间块,则代码有利于将它们放置在较早出现的空间块中。

    为清楚起见,我没有编码边缘情况(单字符串,零长度输出,空输入,不适合缓冲区的单词等)。这留下了作为读者的练习。