3

I wrote this program for school and it almost works, but there is one problem. The goal of the program is to take an inputted string and create a new string out of each word in the input beginning with a vowel.

Example:

input: It is a hot and humid day.
output: Itisaand.

Here is the driver:

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();
}

}

And here is the class:

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+".");
    }
}

With this code, i get the output:
Itisaa hotandand humidand humid summerand humid summer day.

By removing this piece of code:

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

I get the proper output, but it doesn't work if an inputted word has more than one vowel in it.

For example:

input: Apples and bananas.
output: and.

Can someone please explain:
a) why the code is printing out words beginning with consonants as it is and
b) how I could fix it.

Also, the methods in the class I've written can't be changed.

4
  • 11
    Please don't name a class Class... Commented Oct 19, 2013 at 16:19
  • I know I've been told that before but I started this program a while ago and I just never changed it. Commented Oct 19, 2013 at 16:21
  • 2
    It would take 3 seconds to change it now... Commented Oct 19, 2013 at 16:28
  • Yes, it's a very quick fix, especially if you're using Netbeans or the like, Find and Replace! Commented Oct 19, 2013 at 16:33

7 Answers 7

4

Here's a better algorithm:

  1. split the input into an array of words
  2. iterate over each word
  3. if the word begins with a vowel, append it to the output

The easiest way to split the input would be to use String.split().

Here's a simple implementation:

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 "";
}
Sign up to request clarification or add additional context in comments.

4 Comments

This does not keep the punctuation marks... So it is not exactly what he wanted input: It is a hot and humid day. output: Itisaand. <-- see the dot
@noone - FIXED. Thanks, I didn't see that.
Yep, but now it's not really much different from my version. +1 ;)
@noone - Then I'll upvote your answer and remove my way over-critical comments ;-)
2

The problem with your code was: It was counting the same word multiple times, due to it finding vowels and starting the word search process over again.

Heres how I went about solving the problem, while still keeping your code looking relatively the same: All I changed was your loop

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
                }
            }
        }
    }

As mentioned above, there are better ways to go about this, and there are some pretty glaring flaws in the setup, but you wanted an answer, so here you go

Comments

1

Normally i would suggest you where to fix your code, but it's seems there is a lot of bad code practice in here.

  • Mass Concatenation should be apply be StringBuilder.
  • Never call a class Class
  • Conditions are too long and can be shorten by a static string of Vowels and apply .contains(Your-Char)
  • Spaces, Indentations required for readability purposes.
  • A different way of attacking this problem, may probably accelerate your efficiency.

Another approch will be Split the code by spaces and loop through the resulted array for starting vowels letters and then Append them to the result string.

Comments

1

A better readable and more maintainable version doing what you want:

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();
}

In use:

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

Comments

1

I think best approach is to split input and then check each word if it starts with vowel.

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 Comments

Your code would be a lot more readable if you stored the first character in a variable rather than repeating input[i].charAt(0) ten times! I also don't see why you would append an empty string... that makes no sense.
modified as per comments :) Thanks
How about char c = input[i].toLowerCase().charAt(0); ?
that's great too. there's a lot to learn for me also. Thanks again :)
1

The problem with your code is that you override the first beg when a word has more that vowel. for example with Apples beg goes to 0 and before you could call findWord to catch it, it gets overridden with 4 which is the index of e. And this is what screws up your algorithm.

You need to note that you have already found a vowel until you have called finWord, for that you can add a boolean variable haveFirstVowel and set it the first time you have found one to true and only enter the branch for setting that variable to true if you haven't already set it. After you have called findWord set it back to false.

Next you need to detect the start of a word, otherwise for example the o of hot could wrongly signal a first vowel.

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();

Comments

0

I think overall the algorithm is not bad. It's just that the implementation can definitely be better.

Regarding to the problem, you only need to call findWord() when:

  1. You have found a vowel, and
  2. You have reached the end of a word.

Your code forgot the rule (1), therefore the main() can be modified as followed:

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();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.