4
\$\begingroup\$

I feel like my code is too messy-Im looking for possible way to make it more readable/shorter. Goals:
1)Get three strings from user input. They have to be the same length.
a)First must contain only lowercase letters.
b)Second must contain only uppercase letters.
c)Third must have an even length and the same number of vowels and consonants.
Example1:

Input1: aaaa
Input2: BBBB
Input3: baba

2)Add to the first string all vowels from the third word (at the end of the word).
Example2:

Output: aaaaaa

3)Add to the second string all consonants from the third word (at the beginning of the word).
Example3:

Output:bbBBBB

4)Print the words:
a)with the most vowels.
b)with the most consonants.
I was thinking about ternary operator in "print the word with most vowels/consonants" phase but I failed.
Thank you for every advice.

import java.util.Scanner;

public class Main {
public static int countVowels(String str) {
    str.toLowerCase();
    int count = 0;
    for (int i = 0; i < str.length(); i++) {
        if (str.charAt(i) == 'a' || str.charAt(i) == 'e' || str.charAt(i) == 'i'
                || str.charAt(i) == 'o' || str.charAt(i) == 'u' || str.charAt(i) == 'y') {
            count++;
        }
    }
    return count;
}

public static int countConsonants(String str) {
    str.toLowerCase();
    String stringWithoutVowels = str.replaceAll("[aeiouyAEIOUY]", "");
    int numberOfConsonants = stringWithoutVowels.length();
    return numberOfConsonants;
}

public static void main(String[] args) {

    Scanner scn = new Scanner(System.in);
    while (true) {
        System.out.println("Provide 3 strings");
        String first = scn.next();
        String second = scn.next();
        String third = scn.next();
        String thirdWithoutVowels = third.replaceAll("[aeiouyAEIOUY]", "");
        String thirdWithoutConsonants = third.replaceAll("[BCDFGHJKLMNPQRSTVXZbcdfghjklmnpqrstvxz]", "");
        StringBuffer firstForAdding = new StringBuffer(first);
        StringBuffer thirdForAdding = new StringBuffer(thirdWithoutVowels);
        String firstRegex = "[a-z]+";
        String secondRegex = "[A-Z]+";
        if (third.length() % 2 == 0) {
            if (thirdWithoutVowels.length() == thirdWithoutConsonants.length())

                if ((first.matches(firstRegex) == true) &&
                        (second.matches(secondRegex)) == true) {
                    if (first.length() == second.length() && second.length() == third.length()) {
                        System.out.println("__________________________1.First with vowels from the third one(at the end).__________________________");
                        System.out.println(firstForAdding.append(thirdWithoutConsonants));
                        System.out.println("__________________________2.Second with consonants from the third one(at the begining).__________________________");
                        System.out.println(thirdForAdding.append(second));
                        if (countVowels(first) > countVowels(second) && countVowels(first) > countVowels(third)) {
                            System.out.println("Word with most vowels: " + first);
                        } else if (countVowels(second) > countVowels(first) && countVowels(second) > countVowels(third)) {
                            System.out.println("Word with most vowels: " + second);
                        } else {
                            System.out.println("Word with most vowels: " + third);
                        }
                        if (countConsonants(first) > countConsonants(second) && countConsonants(first) > countConsonants(third)) {
                            System.out.println("Word with most consonants: " + first);
                        } else if (countConsonants(second) > countConsonants(first) && countConsonants(second) > countConsonants(third)) {
                            System.out.println("Word with most consonants: " + second);
                        } else {
                            System.out.println("Word with most consonants: " + third);
                        }
                        break;
                    }
                }
        } else {
            System.out.println("Wrong");
        }

    }

}
}
\$\endgroup\$

3 Answers 3

5
\$\begingroup\$

The functions countVowels() and countConsonants() do very similar things, but are implemented in entirely different ways. Could they not be written using the same method? Could they be defined one in terms of the other, such as consonants = string_length - vowels?

The statement str.toLowerCase(); does nothing. Well, it does do something ... it computes a lowercase version of str ... but doesn’t assign the result to anything, so the result is lost. You probably wanted str = str.toLowerCase();.

The class StringBuffer is deprecated; StringBuilder should be used in its place.

The StringBuffer#append() function returns itself to facilitate chained operation, like sb.append(x).append(y).append(x). The value returned should not be used for other purposes, such as printing. System.out.println(thirdForAdding.append(second)) is a side-effect in a print statement - a dangerous practice; unlearn it.

Constructing a StringBuffer (or a StringBuilder) to append one value is overkill. Just use regular string addition.

Explicit equality tests with true are unnecessary. You could simply write:

if (first.matches(firstRegex) && second.matches(secondRegex)) { …

”Wrong” is only printed if the first test fails. If the second, third, or fourth tests fail, nothing is output.

The Scanner (and other Closable resources) should be closed to release resources immediately, instead of when garbage collected. The try-with-resources statement does this for you automatically & safely:

try (Scanner scn = new Scanner(System.in)) {
    ... use scanner here ...
}
... scanner has been closed after this point.
\$\endgroup\$
4
\$\begingroup\$

Avoiding nested if-else blocks would improve the code readability considerably , Instead of having the core logic inside the main I would delegate that to a function with multiple short functions for every rule which would return a boolean value .

So instead of

if(condition1){

   if(condition2){

       if(condition3){



    }

  }

}

I would prefer to have

if(!condition1){

//fail here   

}

if(!condition2){

//fail here   

}

if(!condition3){

//fail here   

}

```
\$\endgroup\$
4
\$\begingroup\$

I'm not sure my code is any less messy. Writing an application that checks for errors and allows a person to correct their errors is messy.

I followed the strategy of testing for each of the goals in a separate method.

The main method simply loops, receiving input and producing output, until the user just presses the Enter key when entering String 1.

The verifyInput method returns a code to let the calling method know what the result was.

The codes are:

0 - Valid input
1 - User pressed Enter key to exit application
2 - One of the three strings did not meet the criteria.
3 - The three strings are not of equal length.

I'm not thrilled to use a return code, but it was the only way I could check for a user exit, check validity, and repeat the process until the user exits.

The rest of the methods basically do what the name of the method says. The methods are coded in the order in which they are called. In other words, the reader of the code never has to page up to see what a method does.

Generally, you start with the high-level concepts, then work your way down to the details. Writing an application is a lot like writing an essay. You start with the main points and provide more details later.

Here's the code.

import java.util.Scanner;

public class TriString {

    private static String consonants = "[BCDFGHJKLMNPQRSTVXZ" + 
            "bcdfghjklmnpqrstvxz]";
    private static String vowels = "[aeiouyAEIOUY]";

    public static void main(String[] args) {
        Scanner scn = new Scanner(System.in);
        while (true) {
            int returnCode = verifyInput(scn);
            if (returnCode == 1) {
                break;
            } 
        }
        scn.close();
    }

    static int verifyInput(Scanner scn) {
        System.out.println("Provide 3 strings");
        String first = getFirstString(scn);

        if (first.equals("")) {
            return 1;
        }

        String second = getSecondString(scn);
        String[] third = getThirdStrings(scn);

        if (first == null || second == null ||
                third.length == 0) {
            return 2;
        } else if (!isInputEqualLength(
                first, second, third[0])) {
            return 3;
        } else {
            printOutput(first, second, third);
            return 0;
        }
    }

    static String getFirstString(Scanner scn) {
        String first = getInput(scn, "  String 1: ");
        if (first.equals("")) {
            return first;
        }

        String firstRegex = "[a-z]+";
        if (!first.matches(firstRegex)) {
            System.err.print("The first string must ");
            System.err.print(" be all lower case ");
            System.err.println("alphabetic characters.");
            return null;
        }
        return first;
    }

    static String getSecondString(Scanner scn) {
        String second = getInput(scn, "  String 2: ");
        String secondRegex = "[A-Z]+";
        if (!second.matches(secondRegex)) {
            System.err.print("The second string must ");
            System.err.print(" be all upper case ");
            System.err.println("alphabetic characters.");
            return null;
        }
        return second;
    }

    static String[] getThirdStrings(Scanner scn) {
        String third = getInput(scn, "  String 3: ");
        if (third.length() % 2 != 0) {
            System.err.print("The third string must ");
            System.err.print(" have an even number of ");
            System.err.println("characters.");
            return new String[0];
        }

        String thirdWithoutVowels = 
                third.replaceAll(vowels, "");
        String thirdWithoutConsonants = 
                third.replaceAll(consonants, "");
        if (thirdWithoutVowels.length() !=
                thirdWithoutConsonants.length()) {
            System.err.print("The third string must ");
            System.err.print(" have an equal number ");
            System.err.println("of consonants and vowels.");
            return new String[0];
        }

        String[] output = new String[3];
        output[0] = third;
        output[1] = thirdWithoutConsonants;
        output[2] = thirdWithoutVowels;
        return output;
    }

    static String getInput(Scanner scn, String text) {
        System.out.print(text);
        return scn.nextLine().trim();
    }

    static boolean isInputEqualLength(String... input) {
        int length = input[0].length();
        for (int i = 1; i < input.length; i++) {
            if (input[i].length() != length) {
                System.err.print("The three strings must ");
                System.err.println(" be the same length.");
                return false;
            }
        }
        return true;
    }

    static void printOutput(String first, String second,
            String[] third) {
        System.out.print("Output string 1: ");
        System.out.println(first + third[1]);
        System.out.print("Output string 2: ");
        System.out.println(third[2] + second);
        System.out.print("String with most consonants: ");
        String most = mostConsonants(first, second, third[0]);
        System.out.println(most);
        System.out.print("String with most vowels    : ");
        most = mostVowels(first, second, third[0]);
        System.out.println(most);
    }

    static String mostConsonants(String... input) {
        String test = input[0];
        int maxLength = countConsonants(test);
        for (int i = 1; i < input.length; i++) {
            int length = countConsonants(input[i]);
            if (maxLength < length) {
                maxLength = length;
                test = input[i];
            }
        }
        return test;
    }

    static String mostVowels(String... input) {
        String test = input[0];
        int maxLength = countVowels(test);
        for (int i = 1; i < input.length; i++) {
            int length = countVowels(input[i]);
            if (maxLength < length) {
                maxLength = length;
                test = input[i];
            }
        }
        return test;
    }

    static int countConsonants(String str) {
        String stringWithoutVowels = 
                str.replaceAll(vowels, "");
        return stringWithoutVowels.length();
    }

    static int countVowels(String str) {
        String stringWithoutConsonants = 
                str.replaceAll(consonants, "");
        return stringWithoutConsonants.length();
    }

}
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.