3

このプログラムは学校向けに書いたもので、ほとんど動作しますが、1 つ問題があります。プログラムの目標は、入力された文字列を取得し、母音で始まる入力内の各単語から新しい文字列を作成することです。

例:

入力: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) コードが子音で始まる単語をそのまま出力している理由と、
b) どうすれば修正できるか。

また、私が書いたクラスのメソッドは変更できません。

4

7 に答える 7

4

より良いアルゴリズムは次のとおりです。

  1. 入力を単語の配列に分割します
  2. 各単語を反復する
  3. 単語が母音で始まる場合は、それを出力に追加します

入力を分割する最も簡単な方法は、 を使用すること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 "";
}
于 2013-10-19T16:24:23.190 に答える
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
                }
            }
        }
    }

上記のように、これにはもっと良い方法があり、セットアップにはかなり明白な欠陥がいくつかありますが、答えが欲しかったので、ここに行きます

于 2013-10-19T16:32:20.343 に答える
1

begコードの問題は、単語にその母音がある場合に最初のものをオーバーライドすることです。たとえば、Applesbeg を使用する0と、それをキャッチするために呼び出す前に、 which のインデックスである でfindWordオーバーライドされます。そして、これがアルゴリズムを台無しにします。4e

を呼び出すまで母音をすでに見つけていることに注意する必要があります。finWordそのため、ブール変数を追加しhaveFirstVowelて、最初に見つかったときにそれを true に設定し、その変数を true に設定するためのブランチに入ることができます。まだ設定していません。呼び出した後、findWordそれを false に戻します。

次に、単語の開始を検出する必要があります。そうしないと、たとえばoofhotが最初の母音を誤って通知する可能性があります。

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();
于 2013-10-19T17:21:35.487 に答える
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);

}
于 2013-10-19T16:38:32.427 に答える
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.
}
于 2013-10-19T16:48:21.757 に答える
1

通常、コードを修正する場所を提案しますが、ここには多くの悪いコードの慣行があるようです。

  • Mass Concatenation は StringBuilder に適用する必要があります。
  • クラスを呼び出さないClass
  • 条件が長すぎるため、母音の静的文字列によって短くすることができ、.contains(Your-Char) を適用します
  • 読みやすくするために必要なスペース、インデント。
  • この問題に取り組む別の方法は、おそらく効率を加速する可能性があります。

別のアプローチSplit、スペースによるコードであり、結果の配列をループして母音文字を開始し、それらを結果の文字列に追加します。

于 2013-10-19T16:24:08.563 に答える
0

全体的にアルゴリズムは悪くないと思います。実装が確実に改善される可能性があるというだけです。

問題に関しては、次の場合にのみfindWord ()を呼び出す必要があります。

  1. 母音を見つけて、
  2. 単語の終わりに達しました。

あなたのコードはルール (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();
于 2013-10-19T16:52:04.213 に答える