4

I am a beginner at java and I am doing this course an needed some help with this. Basically, a user will input a string and then the program will print out only the vowels on one line.

import java.util.Scanner; 

class Main {
  public static void main(String[] args) {
    Scanner inp = new Scanner(System.in);
    System.out.print("In:");
    String word = inp.nextLine();
    //write your code below
    for(int whatsat = 0; whatsat < word.length(); whatsat++){
      if (word.charAt(whatsat).equals("a")){  //how to declare mutiple letters?
        System.out.print(word.charAt(whatsat));
      }

  }
}
}
nabster
  • 1,561
  • 2
  • 20
  • 32
Rick
  • 75
  • 2
  • 4
  • 2
    Note that `charAt()` returns a `char`, which does not have an `equals()` method (or any methods). – Logan Mar 09 '19 at 01:49
  • Research java regular expressions, which in this case would allow quick extraction of only the vowels. 'Pattern' is an important part of Java's regular expression capabilities. – Adrian M. Mar 09 '19 at 01:50

5 Answers5

1

I agree with @Logan. You don't use equals() to compare primitive type values (int, char, boolean, etc.), just use simple == expression.

import java.util.Scanner; 

class Main {
  public static void main(String[] args) {
    Scanner inp = new Scanner(System.in);
    System.out.print("In:");
    String word = inp.nextLine();
    //write your code below
    for(int whatsat = 0; whatsat < word.length(); whatsat++){
      char c = Character.toLowerCase(word.charAt(whatsat));
      if (c == 'a' || c == 'e'|| c == 'i' || c == 'o' || c == 'u'){
        System.out.print(word.charAt(whatsat));
      }

  }
}
}
VietHTran
  • 2,233
  • 2
  • 9
  • 16
1

A simple way to do this (intentionally avoiding complex regex options) would be to use the String.indexOf() method within your loop.

In the example below, we basically check if "AEIOUaeiou" contains the char that we're pulling from the user's input. If so, we extract it:

public static void main(String[] args) {
    Scanner inp = new Scanner(System.in);
    System.out.print("In:");
    String word = inp.nextLine();

    //write your code below

    // This will hold any matching vowels we find
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < word.length(); i++) {

        // Check if our list of vowels contains the current char. If the current char exists in the String of vowels, it will have an index of 0 or greater.
        if ("AEIOUaeiou".indexOf(word.charAt(i)) > -1) {

            // If so, add it to our StringBuilder
            sb.append(word.charAt(i));
        }
    }

    // Finally, print the result
    System.out.println(sb.toString());

}

The Result:

With test input of "This is my test input. Did it work?" the output is: iieiuiio

Zephyr
  • 9,885
  • 4
  • 28
  • 63
  • You could simplify this by using `indexOf > -1` and avoid the `String.valueOf` – Minn Mar 09 '19 at 05:21
  • I'm not sure which method is "simpler," but yes, that would work too :) – Zephyr Mar 09 '19 at 05:30
  • In terms of the check it certainly is simpler to search a char in a string compared to searching a string in a string, as a matter of branching/looping – Minn Mar 09 '19 at 05:31
  • This is still an O(n^2) solution because of inner function `indexOf` – Mahadeva Mar 09 '19 at 05:34
0

So there's two issues here:

  1. Characters are compared differently from Strings.
  2. Checking for multiple characters.

To compare characters, do something like:

if (word.charAt(whatsat) == 'a') {
    ...
}

Note the single quotes! 'a' not "a"!

If you're asking "why are comparisons for strings and characters different?", that's a good question. I actually don't know the reason, so we should both research it. Moving on.

To check for multiple characters:

for(int whatsat = 0; whatsat < word.length(); whatsat++){
    if (word.charAt(whatsat) == 'a' || word.charAt(whatsat) == 'e' || word.charAt(whatsat) == 'i'){
        System.out.print(word.charAt(whatsat));
    }
  }

Note that if you're input has capital letters, you'll need to either:

  • Convert your input to lowercase so you can just check for lowercase letters, or
  • Explicitly check for capital letters in your if statement, e.g
if (...word.charAt(whatsat) == 'A' ...)

Longterm, you'll want to research regular expressions like a Adrian suggested in the comments. It may be complicated for a beginning student, but if you're interested you should look into it.

Hope this helps.

broAhmed
  • 192
  • 1
  • 2
  • 16
  • 2
    Don't take offence, but if your next task will be to write out all the consonants instead of vowels, what will you do then? Surely not write out 21 or (||) statements... Unfortunately, your solution is not good practice or very scalable for multiple characters. – vs97 Mar 09 '19 at 03:26
  • @vs97 None taken! Absolutely agree. Would I do this professionally? No, of course not. But if I'm giving advice to a beginning CS student who's just learning the difference between strings and characters, I'm going to tailor my answer to their level. I wouldn't be surprised if they've just learned what `if` does; would I expect them to know about enums and sets? – broAhmed Mar 09 '19 at 07:12
0

I am really surprised nobody has suggested using Enums... Cleanest way and simplest way, in my opinion.

Simply define an Enum with all the vowels, go through the String and compare each character to the values inside of Enum, ignoring the case - note the cast of char into String. If it is present in the Enum, print it out.

public class VowelFind  {

    enum Vowels {
        A, E, I, O, U
    }

    public static void main(String[] args) {
        Scanner inp = new Scanner(System.in);
        System.out.print("In:");
        String word = inp.nextLine();

        for (int i = 0; i < word.length(); i++) { //loop through word
            for (Vowels v : Vowels.values()) { //loop through Enum values
                if((word.charAt(i)+"").equalsIgnoreCase(v.name())) { //compare character to Enum value, ignoring case
                    System.out.print(word.charAt(i));
                }
            }
        }
    }
}

Input: Hello World
Output: eoo

vs97
  • 5,765
  • 3
  • 28
  • 41
  • You realize it is O(n^2) solution, which is worse than O(n) i.e. you can do the same in one loop instead of two. – Mahadeva Mar 09 '19 at 04:10
  • If that's not how big-O works, consider running the same code against 1 million letter word. – Mahadeva Mar 09 '19 at 05:36
  • Using nested loops is certainly not the cleanest or simplest way of accomplishing this... – Zephyr Mar 09 '19 at 05:38
  • O(n²) implies you have 2 nested loops that grow based on inputs, however the nested loop does not grow based on inputs because it has a constant set of iterations. This means its an O(1) loop. In turn the entire algorithm becomes O(n) – Minn Mar 09 '19 at 05:41
  • @Minn check it out https://stackoverflow.com/questions/27089438/complexity-of-enum-values – Mahadeva Mar 09 '19 at 05:47
  • Ok, you seem to have a fundamental misunderstanding of how big-O notation works. O(n) means your algorithm grows in complexity based on the input arguments in linear time, if you have 2 nested loops that both iterate the entire input you have n * n operations aka O(n²). In this case you have a nested loop that always has the same amount of iterations no matter the input. That means its constant, which is denoted as O(1). The input here is the word not the values array. It would be O(n²) if both loops were on the input but they are not. – Minn Mar 09 '19 at 05:53
  • I guess you still didn't got what I am trying to say. Even if `Vowels.values()` seems like a constant operation, it is worse because each time you call `Vowels.values()`, new array is being created; which is still an O(n) operation. This scenario is similar to concatenating Strings inside a loop. – Mahadeva Mar 09 '19 at 06:17
  • That does not make it O(n²), which is what you claimed. – Minn Mar 09 '19 at 06:30
0

I prefer to use Hashmap as lookup is O(1)

    public class PrintVowelsInWord {

    public static Map<Character, Character> vowels;

    public static void main(String[] args) {
        loadMap();
        // for simplicity sake I am not using Scanner code here
        getVowels("wewillrockyou");
    }

    public static void loadMap() {
        if (vowels == null) {
            vowels = new HashMap<>();
            vowels.put('a', 'a');
            vowels.put('e', 'e');
            vowels.put('i', 'i');
            vowels.put('o', 'o');
            vowels.put('u', 'u');
        }
    }

    public static void getVowels(String input) {
        for (Character letter : input.toCharArray()) {
            if (vowels.containsKey(letter)) {
                System.out.print(letter);
            }
        }
    }
}
nabster
  • 1,561
  • 2
  • 20
  • 32
  • This might be O(1) but that constant is pretty bad in terms of performance due to both hashing and lookup but also the overhead due to the boxing of chars – Minn Mar 09 '19 at 05:27
  • Consider the case if he wants to search some random letters. Your map will indeed grow and code might become polluted. – Mahadeva Mar 09 '19 at 05:32
  • @Minn Lets assume the input is entire prose of Shakespeare, hashing for 5 vowels will be done once and Map can be made static. This map is not constantly growing as (there are only 5 possible vowels). – nabster Mar 09 '19 at 05:34
  • @Pant Why map would need to grow? For random letters, the requirements are different and hence a different solution :) – nabster Mar 09 '19 at 05:34
  • I guess my proof of concept in main() confused the point I was trying to convey. Here edited my code. – nabster Mar 09 '19 at 05:41