setCharAt方法在for循环中没有按预期工作(Java)

时间:2017-07-05 00:54:21

标签: java string stack

我正在尝试开发一种方法来反转字符串中的元音。为此,我开发了自己的小堆栈。我正在向后遍历字符串两次,一次用我找到的每个元音填充堆栈,第二次用存储在堆栈顶部的元音替换元音。我添加了一堆print语句来确定它失败的地方,并且它似乎在setCharAt方法失败了。出于测试目的,我提供了一个字符串aeiou,我希望能够找回uoiea。在每次迭代过程中,字符都会被替换,但不幸的是,它们不会保持这种状态。从下一次迭代开始,在前一次迭代中替换的字符将返回到之前的字符。结果,我回到ueiou,其中只有字符串中的第一个字符符合预期(第三个字符是noop)。这是我的代码。任何提示都表示赞赏。

import java.util.*;

public class Solution {

    static String result;

    static class StackOfVowels {
        static Node top;

        public StackOfVowels() {
            Node top = null;
        }

        static class Node {
            Node next = null; 
            char vowel = '\0';
            Node(char value) {
                this.vowel = value;
            }
        }

        public void push(char item) {
            Node node = new Node(item);
            if (top == null) {
                top = node;
            }
            else { 
                node.next = top;
                top = node;
            }
        }

        public char top() {
            if (top == null) throw new EmptyStackException();
            return top.vowel; 
        }

        public void pop() {
            int result = -1;
            if (top != null) {
                result = top.vowel;
                top = top.next;
            }
        }
    }

    public static String reverseVowels(String s) {

        StackOfVowels stackOfVowels = new StackOfVowels();

        for(int i = s.length()-1; i >= 0; i--) {
            char c = s.charAt(i);
            if ((c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') || (c == 'u')) {
                System.out.println("Initial sequence of iterations identified vowel: " + c);
                stackOfVowels.push(c);
                System.out.println("Pushed to stack, current top is: " + stackOfVowels.top());
            }
        }

        for(int j = s.length()-1; j >= 0; j--) {
            char b = s.charAt(j);
            if ((b == 'a') || (b == 'e') || (b == 'i') || (b == 'o') || (b == 'u')) {
                System.out.println("Second sequence of iterations identified vowel: " + b);
                StringBuilder newstr = new StringBuilder(s);
                char d = stackOfVowels.top();
                System.out.println("Variable d set to top of: " + stackOfVowels.top());
                newstr.setCharAt(j, d);
                result = newstr.toString();
                System.out.println("Here is the new string: " + result);
                stackOfVowels.pop();
                System.out.println("Stack was popped");
            }
        }
        return result;
    }

    public static void main(String[] args) {
        String s = "aeiou";
        reverseVowels(s);
        System.out.println("Final result: " + result);
    }
}

3 个答案:

答案 0 :(得分:2)

使用StringBuilder newstr = new StringBuilder(s);在第二个循环中生成一个新的StringBuilder 但是你总是用's'而不是'结果'来构建你的新StringBuilder。

不管怎样,最好不要在每次迭代中创建一个新的StringBuilder对象。

同样令人困惑的是你的方法有一个从未使用过的返回值。

以下方法应该有效:

public static String reverseVowels(String s) {

    StackOfVowels stackOfVowels = new StackOfVowels();

    for(int i = s.length()-1; i >= 0; i--) {
        char c = s.charAt(i);
        if ((c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') || (c == 'u')) {
            System.out.println("Initial sequence of iterations identified vowel: " + c);
            stackOfVowels.push(c);
            System.out.println("Pushed to stack, current top is: " + stackOfVowels.top());
        }
    }
    StringBuilder result_builder = new StringBuilder(s);
    for(int j = s.length()-1; j >= 0; j--) {
        char b = s.charAt(j);

        if ((b == 'a') || (b == 'e') || (b == 'i') || (b == 'o') || (b == 'u')) {
            System.out.println("Second sequence of iterations identified vowel: " + b);
            char d = stackOfVowels.top();
            System.out.println("Variable d set to top of: " + stackOfVowels.top());
            result_builder.setCharAt(j, d);
            stackOfVowels.pop();
            System.out.println("Stack was popped");
        }
    }
    result = result_builder.toString();
    return result_builder.toString();
}

答案 1 :(得分:2)

我会稍微改变一下这个问题,首先我会使用正则表达式String中移除所有辅音以创建String vowels }。然后我将遍历String的字符,使用StringBuilder来构建输出(传递辅音,但使用之前创建的vowels String替换元音。像,

public static String reverseVowels(String s) {
    // Match all consonants, and remove them. Reverse that String.
    String vowels = new StringBuilder(s.replaceAll("[^AEIOUaeiou]", ""))
            .reverse().toString();
    StringBuilder sb = new StringBuilder();
    for (int i = 0, p = 0; i < s.length(); i++) {
        switch (Character.toLowerCase(s.charAt(i))) {
        // Note that these fall-through...
        case 'a': case 'e': case 'i': case 'o': case 'u':
            sb.append(vowels.charAt(p++));
            break;
        default:
            sb.append(s.charAt(i));
        }
    }
    return sb.toString();
}

这是可以利用switch和堕落行为的地方之一。

如果您使用的是Java 8+,则可以使用IntStream表达相同内容并映射字符;像

String vowels = new StringBuilder(s.replaceAll("[^AEIOUaeiou]", ""))
        .reverse().toString();
int[] counter = new int[1]; // <-- A bit of a kludge really.
return IntStream.range(0, s.length()).mapToObj(i -> {
    switch (Character.toLowerCase(s.charAt(i))) {
    case 'a': case 'e': case 'i': case 'o': case 'u':
        return Character.toString(vowels.charAt(counter[0]++));
    default:
        return Character.toString(s.charAt(i));
    }
}).collect(Collectors.joining());

答案 2 :(得分:2)

@Elliot答案略有改进(值得商榷)是使用原始StringBuilder创建String并仅在必要时替换

    String vowels = new StringBuilder(s.replaceAll("[^AEIOUaeiou]", ""))
            .reverse().toString();
    StringBuilder sb = new StringBuilder(s);
    for (int i = 0, p = 0; i < s.length(); i++) {
        switch (Character.toLowerCase(s.charAt(i))) {
        // Note that these fall-through...
        case 'a': case 'e': case 'i': case 'o': case 'u':
            sb.setCharAt(i, vowels.charAt(p++));
            break;
        default:
            break;
        }
    }
    return sb.toString();