Roger Steinberg
Roger Steinberg

Reputation: 1604

Switch statement using substring of a user's input

Objective: I am trying to ouput a message based on a user's input.

Situation: Basically a user will input a few characters like 5r (5 Red) or 8y (8 Yellow). The notation expected is a digit first and a character after but it is possible that the user doesn't follow the rule.

I used switch statements (part of the exercise) but the output doesn't give me what I expect

Code:

        String input = reader.nextLine().toLowerCase();
        String firstChar = input.substring(0,1);
        String secondChar = input.substring(1);
        String answer = "";

        switch(firstChar)
        {
            case "0":
            {
                switch(secondChar)
                {
                    case "b":
                        answer = "Zero Blue";
                    case "r":
                        answer = "Zero Red";
                    case "g":
                        answer = "Zero Green";
                    case "y":
                        answer = "Zero Yellow";
                }
            }
            case "1":
            {
                switch(secondChar)
                {
                    case "b":
                        answer = "One Blue";
                    case "r":
                        answer = "One Red";
                    case "g":
                        answer = "One Green";
                    case "y":
                        answer = "One Yellow";
                }
            }
           ... other case statements....
           default:
              answer = "not valid";

When the user writes 0b, my output should be "Zero Blue" but currently it is displaying "not valid". Why?

Upvotes: 0

Views: 786

Answers (2)

Ali Ben Zarrouk
Ali Ben Zarrouk

Reputation: 2018

I suggest not using swich case at all, use hash maps:

package mypackage;

import java.util.*;

public class MyComputingClass {

    private static Map<Character, String> firstCharMapping;
    private static Map<Character, String> secondCharMapping;

    public static void main(String[] args) {
        initCharMappers();

        System.out.println("Mapping of 0Y : " + mapStuff("0Y"));
        System.out.println("Mapping of 0y : " + mapStuff("0y"));
        System.out.println("Mapping of 0YJ : " + mapStuff("0YJ"));
        System.out.println("Mapping of 2B : " + mapStuff("2B"));
        System.out.println("Mapping of eB : " + mapStuff("eB"));
    }

    private static void initCharMappers() {
        firstCharMapping = new HashMap<>();
        secondCharMapping = new TreeMap<>(Comparator.comparing(Character::toLowerCase));

        firstCharMapping.put('0', "Zero");
        firstCharMapping.put('1', "One");
        firstCharMapping.put('2', "Two");

        secondCharMapping.put('Y', "Yellow");
        secondCharMapping.put('B', "Blue");
        secondCharMapping.put('G', "Green");
    }

    private static String mapStuff(String str) {
        String INVALID_INPUT = "Invalid input";
        if (!str.matches("\\d[a-zA-Z]")) {
            return INVALID_INPUT;
        }

        Character firstChar = str.toCharArray()[0];
        Character secondChar = str.toCharArray()[1];

        if (!firstCharMapping.containsKey(firstChar) || !secondCharMapping.containsKey(secondChar)) {
            return INVALID_INPUT;
        }

        return firstCharMapping.get(firstChar) + " " + secondCharMapping.get(secondChar);
    }
}

Output :

Mapping of 0Y : Zero Yellow
Mapping of 0y : Zero Yellow
Mapping of 0YJ : Invalid input
Mapping of 2B : Two Blue
Mapping of eB : Invalid input

Upvotes: 1

Matthew
Matthew

Reputation: 1943

As @markspace mentioned you were missing a break statement. Here is a short excerpt from Java documentation on switch statements:

Each break statement terminates the enclosing switch statement. Control flow continues with the first statement following the switch block. The break statements are necessary because without them, statements in switch blocks fall through.

Also I recommend using a dedicated method and for loops for easier debugging.

The following code produces the result you want:

public static String getAnswer() {

        Scanner reader = new Scanner(System.in);
        String input = reader.nextLine().toLowerCase();
        String firstChar = input.substring(0, 1);
        String secondChar = input.substring(1);

        String[] chars = new String[] { "b", "r", "g", "y" };
        String[] answers1 = new String[] { "Zero Blue", "Zero Red", "Zero Green", "Zero Yellow" };
        String[] answers2 = new String[] { "One Blue", "One Red", "One Green", "One Yellow" };

        if ((firstChar.equals("0"))) {
            for (int i = 0; i < chars.length; i++) {
                if (secondChar.equals(chars[i])) {
                    return answers1[i];
                }
            }
        }
        else if ((firstChar.equals("1"))) {
            for (int i = 0; i < chars.length; i++) {
                if (secondChar.equals(chars[i])) {
                    return answers2[i];
                }
            }
        }
        return "not valid";
    }

    public static void main(String[] args) throws IOException {

        System.out.println(getAnswer());
    }

EDIT: In addition to the solution above I would like to offer a more sophisticated one that involves the use of enumerators. It should make your code feel more clean and to the point as well as being more modular:

public enum Answer {

    BLUE('b',"Blue"), RED('r',"Red"),
    GREEN('g',"Green"), YELLOW('y',"Yellow");

    private static final String[] prefix = new String[] {"Zero", "One"};

    char letter;
    String name;

    Answer(char letter, String name) {
        this.letter = letter;
        this.name = name;
    }

    public static String getForInput(char input, int index) {

        if (index > prefix.length)
            return "value out of range " + index;

        for (Answer answer : Answer.values()) {
            if (input == answer.letter)
                return prefix[index] + " " + answer.name;
        }
        return "unable to find answer for input " + input;
    }
}

public static String getAnswer() {

    System.out.println("Enter your input: ");
    Scanner reader = new Scanner(System.in);
    String input = reader.nextLine().toLowerCase();
    int number = Integer.valueOf(input.substring(0, 1));
    char letter = input.substring(1).charAt(0);

    return Answer.getForInput(letter, number);

}

Upvotes: 1

Related Questions