执行简单字符串操作的Java程序无法正常工作

时间:2013-10-19 16:13:54

标签: java

我为学校写了这个程序,它几乎可以工作,但有一个问题。该程序的目标是获取一个输入的字符串并从元音开始用元音开始创建一个新的字符串。

示例:

输入:It is a hot and humid day.
输出:Itisaand.

这是驱动程序:

public class Driver {

public static void main(String[] args) {

    Scanner console = new Scanner(System.in);
    System.out.print("Input: ");
    String input = console.nextLine();
    Class strings = new Class(input);
    int beg=0;
    for(int j=0;j<input.length();j++)
    {
        if(strings.isVowel(j)&&(j==0||input.charAt(j-1)==' '))
            beg=j;
        else if(strings.endWord(j)&&(beg==0||input.charAt(beg-1)==' '))
        {
            strings.findWord(beg, j);       
        }
    }
    System.out.print("Output: ");
    strings.printAnswer();
}

}

这是班级:

public class Class {

    String input="",answer="";
    public Class(String input1)
    {
        input = input1;
    }


    public boolean isVowel(int loc)
    {
        return (input.charAt(loc)=='U'||input.charAt(loc)=='O'||input.charAt(loc)=='I'||input.charAt(loc)=='E'||input.charAt(loc)=='A'||input.charAt(loc)=='a'||input.charAt(loc)=='e'||input.charAt(loc)=='i'||input.charAt(loc)=='o'||input.charAt(loc)=='u');
    }
    public boolean endWord(int loc)
    {
        return (input.charAt(loc)==' '||input.charAt(loc)=='.'||input.charAt(loc)=='?'||input.charAt(loc)=='!');
    }
    public void findWord(int beg,int end)
    {
        answer = answer+(input.substring(beg,end));
    }
    public void printAnswer()
    {
        System.out.println(answer+".");
    }
}

使用此代码,我得到输出:
Itisaa hotandand humidand humid summerand humid summer day.

删除这段代码:

&& (j == 0 || input.charAt(j-1) == ' ')

我得到了正确的输出,但是如果输入的单词中有多个元音,则它不起作用。

例如:

输入:Apples and bananas.
输出:and.

有人可以解释一下:
a)为什么代码打印出以辅音开头的单词和as b)我如何解决它。

此外,我写的课程中的方法无法更改。

7 个答案:

答案 0 :(得分:4)

这是一个更好的算法:

  1. 将输入拆分为单词数组
  2. 遍历每个单词
  3. 如果单词以元音开头,则将其附加到输出
  4. 分割输入的最简单方法是使用String.split()

    这是一个简单的实现:

    public static void main(String[] args) {
        Scanner console = new Scanner(System.in);
        String input = console.nextLine();
        String[] words = input.split(" ");
        StringBuilder output = new StringBuilder();
        for (String s : words) {
            if (startsWithVowel(s)) {
                output.append(s);
            }
            else {
                output.append(getPunc(s));
            }
        }
        System.out.println(output.toString());
    }
    
    public static boolean startsWithVowel(String s) {
         char[] vowels = { 'a', 'e', 'i', 'o', 'u' };
         char firstChar = s.toLowerCase().charAt(0);
         for (char v : vowels) {
             if (v == firstChar) {
                 return true;
             }
         }
         return false;
     }
    
    public static String getPunc(String s) {
        if (s.matches(".*[.,:;!?]$")) {
            int len = s.length();
            return s.substring(len - 1, len);
        }
        return "";
    }
    

答案 1 :(得分:2)

您的代码存在以下问题: 它多次计算同一个单词,因为它找到了元音并重新开始了单词搜索过程。

这是我如何解决问题,同时仍然保持你的代码看起来相对相同:我改变的只是你的循环

for(int i=0;i<input.length();i++)
    {
        if(strings.isVowel(i) &&(i==0 || strings.endWord(i-1))){ 
            beg = i;
            for(int j = i; j < input.length();j++) //look for end of word
            {
                if(strings.endWord(j)) //word has ended
                {
                    i = j; //start from end of last word
                    strings.findWord(beg, j);         
                    break; //word done, end word search
                }
            }
        }
    }

如上所述,有更好的方法可以解决这个问题,并且设置中存在一些非常明显的缺陷,但是你想要一个答案,所以你去吧

答案 2 :(得分:1)

通常情况下我会建议你在哪里修复你的代码,但似乎这里有很多不好的代码实践。

  • Mass Concatenation应该适用于StringBuilder。
  • 从不致电课程Class
  • 条件太长,可以通过静态字符串元组缩短并应用.contains(Your-Char)
  • 可读性所需的空格,缩进。
  • 攻击此问题的另一种方法可能会提高您的效率。

另一个approch Split代码按空格并循环显示结果数组以启动元音字母,然后将它们附加到结果字符串。

答案 3 :(得分:1)

我认为最佳方法是分割输入,然后检查每个单词是否以元音开头。

public static void main(String[] args)
{

  Scanner console = new Scanner(System.in);
  System.out.print("Input: ");
  String str = console.next();

  String[] input = str.split(" ");

  StringBuilder s = new StringBuilder();

  String test;

  for (int i = 0; i < input.length; i++)
  {
      test = input[i];

      if (test.charAt(0) == 'U' || test.charAt(0) == 'O'
          || test.charAt(0) == 'I' || test.charAt(0) == 'E'
          || test.charAt(0) == 'A' || test.charAt(0) == 'a'
          || test.charAt(0) == 'e' || test.charAt(0) == 'i'
          || test.charAt(0) == 'o' || test.charAt(0) == 'u')
     {
           s.append(input[i]);

     }

   }
   System.out.println(s);

}

答案 4 :(得分:1)

更好的可读性和更易维护的版本,可以满足您的需求:

public static String buildWeirdSentence(String input) {
    Pattern vowels = Pattern.compile("A|E|I|O|U|a|e|i|o|u");
    Pattern signs = Pattern.compile("!|\\.|,|:|;|\\?");
    StringBuilder builder = new StringBuilder();

    for (String word : input.split(" ")) {
        String firstCharacter = word.substring(0, 1);
        Matcher vowelMatcher = vowels.matcher(firstCharacter);
        if (vowelMatcher.matches()) {
            builder.append(word);
        } else {
            // we still might want the last character because it might be a sign
            int wordLength = word.length();
            String lastCharacter = word.substring(wordLength - 1, wordLength);
            Matcher signMatcher = signs.matcher(lastCharacter);
            if (signMatcher.matches()) {
                builder.append(lastCharacter);
            }
        }
    }

    return builder.toString();
}

使用中:

public static void main(String[] args) {
    System.out.println(buildWeirdSentence("It is a hot and humid day.")); // Itisaand.
}

答案 5 :(得分:1)

您的代码存在的问题是,当一个单词有更多元音时,您会覆盖第一个beg。例如,Apples请求0,然后您可以调用findWord来捕获它,它会被4覆盖,efinWord的索引。这就是搞砸你的算法的原因。

你需要注意的是,在你调用haveFirstVowel之前你已经找到了一个元音,因为你可以添加一个布尔变量findWord并在你第一次找到它时设置它为真,如果尚未设置该变量,则仅输入用于将该变量设置为true的分支。调用o后将其设置为false。

接下来,您需要检测单词的开头,否则例如hot的{​​{1}}可能会错误地发出第一个元音的信号。

Class strings = new Class(input);
int beg = 0;
boolean haveFirstVowel = false;
for (int j = 0; j < input.length(); j++) {
    boolean startOfWord = (beg == 0 || input.charAt(j - 1) == ' ');
    if (startOfWord && ! haveFirstVowel && strings.isVowel(j)) {
        beg = j;
        haveFirstVowel = true;
    }
    else if (strings.endWord(j) && haveFirstVowel) {
        strings.findWord(beg, j);
        haveFirstVowel = false;
    }
}
System.out.print("Output: ");
strings.printAnswer();

答案 6 :(得分:0)

我认为整体算法并不差。只是实施肯定会更好。

关于问题,您只需在以下情况下调用 findWord ():

  1. 你找到了一个元音,
  2. 你已经到了一个字的末尾。
  3. 您的代码忘记了规则(1),因此main()可以修改如下:

    Scanner console = new Scanner(System.in);
    System.out.print("Input: ");
    String input = console.nextLine();
    Class strings = new Class(input);
    int beg = 0;
    boolean foundVowel = false; // added a flag indicating whether a vowel has been found or not
    for (int j = 0; j < input.length(); j++) {
        if (strings.isVowel(j) && (j == 0 || input.charAt(j - 1) == ' ')) {
            beg = j;
            foundVowel = true;
        } else if (strings.endWord(j) && (beg == 0 || input.charAt(beg - 1) == ' ')) {
            if (foundVowel) { // only call findWord() when you have found a vowel and reached the end of a word
                strings.findWord(beg, j);
                foundVowel = false; // remember to reset the flag
            }
        }
    }
    System.out.print("Output: ");
    strings.printAnswer();