Search code examples
javaalgorithmloopserror-handlingnested-loops

Restaurant Menu: how to efficiently implement a nested loop to collect user input and conduct error checking


I have these two methods which I cant quite figure out the best way to go about their algorithm. I am writing a program that acts like a restaurant menu and collects user order.

The implementation is,
welcome user and present him with the menu
while the user has not entered 'q', send the user input to a method called getGoodOrderLine(String str)
this method will then check the input for the following,
- First, it must check that a number is present before trying to read it; if there is no number, the entry is an error unless it starts with ‘q’ or ‘Q’, which tells the program to quit.
- then, determine which item the user is asking for by looking at just the first letter. So an input “2 Hello” means 2 hamburgers. the assumption is that if there is a digit in the string, the digit appears before the word, for simplicity
- finally, if the first letter is not (H,C,F or D), print an error message and ask that it be re-entered.

My problem is that, I created a while loop that should loop until the user input is valid, but it doesn't seem to be working, here is my code:

 import java.util.*;
    public class MenuApp
    {
      //global variables
      public static double HAM  = 3.75;
      public static double CHEESE  = 4.10;
      public static double FRIES  = 2.50;
      public static double DRINKS  = 1.75;

      public static void main(String [] args)
      {
        //variables
        String order;
        double total = 0.0;
        boolean stopLoop;
        //print welcome message && collect order
        welcomeCustomer();
        order = collectItem();
        order = getGoodOrderLine(order);
        stopLoop = order.equalsIgnoreCase("q");


        while(!stopLoop)//while user hasnt typed q
        {
          if(order.equalsIgnoreCase("q"))
          {
            break;
          }
          order = getGoodOrderLine(order);
          //will add the value of user order to total here if order is valid
          //leave loop if useer inputs q
        }


        //ending program
        Date today = new Date();
        System.out.println("Date: " + today);
        System.out.println("Please pay " + total + "\n");
        System.out.println("End of processing");
      }
      public static void welcomeCustomer()
      {
        System.out.println("Welcome to QuickieBurger!");
        System.out.println("Hamburgers \t\t $" + HAM);
        System.out.println("cheeseBurgers\t\t $" + CHEESE);
        System.out.println("Fries\t\t\t $" + FRIES);
        System.out.println("Drinks\t\t\t $" + DRINKS+"\n");
      }
      public static String collectItem()
      {
        String userInput = null;
        Scanner kbd = new Scanner(System.in);

        System.out.println("Please place your order (e.g., 3 ham). Enter Q to quit.");
        userInput = kbd.nextLine();
        System.out.println(userInput);
        return userInput;
      }
      public static String getGoodOrderLine(String userInput)
      {
        String result = "";
        boolean pass = false;
        if(userInput.equalsIgnoreCase("q"))
        {
          return userInput;//early exit, return q
        }

        //check if it has at least a digit first
        for(char c: userInput.toCharArray())
        {
          if(Character.isDigit(c))
          {pass = true;}
        }

        //if it doesn't have a digit || string doesnt begin with a digit
        if(!Character.isDigit(userInput.charAt(0)))
        {
          if(!pass)
            System.out.println("Your entry "+ userInput + " should specify a quantity");
          else
            System.out.println("Your entry "+ userInput + " does not begin with a number");
        }
        else
        {
          //do the remaining tests here
        }
        return result;
      }

}

I keep getting null pointer and index out of bounds exceptions when testing for Character.isDigit(userInput.charAt(0));


Solution

  • the problem is you are returning empty string so charAt(0) give error since char array has no elements.and if you want to collect items you need to use a collection type like list and u can't use a array since array has fixed length.and to get price of user input product you need to map prices with product names .so u can use map.but i used 2 arrays which act as a map.check this and it's output.

    import java.util.ArrayList;
    import java.util.List;
    import java.util.Date;
    import java.util.Scanner;
    
    public class myMenu {
    
        public static String names[] = {"HAM", "CHEESE", "FRIES", "DRINKS"};
        public static double prices[] = {3.75, 4.10, 2.50, 1.75};
        public static ArrayList<List<String>> allitems = new ArrayList<>();   
        static double total = 0.0;
    
        public static void main(String[] args) {
            welcomeCustomer();
            collectItem();
        }
    
        public static void welcomeCustomer() {
            System.out.println("Welcome to QuickieBurger!");
            for (int i = 0; i < names.length; i++) {
                System.out.println(names[i] + "\t\t\t" + prices[i]);
            }
        }
    
        public static void collectItem() {
            String userInput = "";
            Scanner kbd = new Scanner(System.in);
            System.out.println("Please place your order (e.g., 3 ham). Enter Q to quit.");
            userInput = kbd.nextLine();
            while (!getGoodOrderLine(userInput)) {
               userInput = kbd.nextLine();
            }
    
        }
        private static boolean getGoodOrderLine(String userInput) {
    
            if (userInput.equalsIgnoreCase("q")) {
                transaction();
            } else if (!Character.isDigit(userInput.charAt(0))) {
                System.out.println("quesntity should be specified. try again");
                return false;
            } else {
                for (int i = 0; i < names.length; i++) {
                    String items = names[i];
                    //get the first charactor from userinput
                    char c = 0;
                    for(int z=0;z<userInput.length();z++){
                        c=userInput.charAt(z);
                        if(Character.isAlphabetic(c)){
                            break;
                        }
                    }
                    if (Character.toLowerCase(items.charAt(0)) ==Character.toLowerCase(c)) {
    
                        String s="";
                        int x=0;
                        while(Character.isDigit(userInput.charAt(x))){
                            s+=userInput.charAt(x);
                            x++;
                        }
                        int quentity=Integer.parseInt(s);
                        double pri = prices[i];
                        double sub = quentity * pri;
                        total += sub;
                        ArrayList<String> subitem = new ArrayList<>();
                        subitem.add(items);
                        subitem.add(String.valueOf(quentity));
                        subitem.add(String.valueOf(sub));
                        allitems.add(subitem);
                        return false;
                    }
                }
                System.out.println("this not a valid food item.try again");
            }
    
            return false;
    
        }
    
        private static void transaction() {
            //ending program
            Date today = new Date();
            System.out.println("-------------------------------------");
            System.out.println("Date: " + today);
            for (List<String> menu : allitems) {
                System.out.println(menu.get(0)+"   "+menu.get(1)+"  = "+menu.get(2));
            }
            System.out.println("Please pay " + total + "\n");
            System.out.println("------------------------------------");
            System.out.println("End of processing");
        }
    }
    

    output>>

    Welcome to QuickieBurger!
    HAM         3.75
    CHEESE          4.1
    FRIES           2.5
    DRINKS          1.75
    Please place your order (e.g., 3 ham). Enter Q to quit.
    2 Hello
    4 CHEESE
    q
    -------------------------------------
    Date: Sun Nov 02 02:59:56 PST 2014
    HAM   2  = 7.5
    CHEESE   4  = 16.4
    Please pay 23.9
    
    ------------------------------------
    End of processing