0

I'm writing a program that allows a user to "Buy" chocolate bars, which then awards the user with coupons, seven of which can buy another chocolate bar for free. At several points in the program, the user is to be prompted to make a choice.

These choices are:

Whether to purchase chocolate bars or close the program.

Whether to use coupons to purchase a free chocolate bar.

How many chocolate bars to purchase if coupons are not used.

I don't have to worry about the price of the chocolate bars for this program. The part I'm stuck on is that the user's input has to be able to be one character, one word, or several words long, and the first letter is what is read as the user's response. So for example, the if the user inputs "Yes I do" then the input read is 'Y'.

My problem is that neither keyboard.nextLine().charAt(0) nor keyboard.next().charAt(0) seem to work. In the latter case, if the user input is several words long, the second word is used as the input. The general response to this is of course to use nextLine() instead of next(). When I use nextLine(), the first iteration of the loop executes without any problem. But the next iteration of the loop immediately produces the following error:

Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0 at java.lang.String.charAt(String.java:658) at ChocolateCoupons.main(ChocolateCoupons.java:47)

So it seems neither next() nor nextLine() work. What should I do? Here is my code:

import java.util.Scanner;

public class ChocolateCoupons 
{
    public static void main(String[] args) 
    {
        //Number of coupons that can be traded for one free chocolate
        final int COUPONS_PER_CHOCOLATE = 7;

        //So that the scanner reads only the first letter when user inputs a string
        final int START_OF_INPUT = 0;

        //Number of coupons the user has and how many chocolates to purchase.
        int couponCount = 0, purchase;

        //Choices whether to continue running the program
        //and whether to trades coupons for chocolates.
        char run = 'P', freeChocolate = 'N';

        //If true, all remaining portions of the main loop will be ignored. 
        //Resets to false at the end of every loop
        boolean end = false; 

        //Scans user input
        Scanner keyboard = new Scanner(System.in);

        while(run != 'S' && run != 's')
        {
            //Asks user whether to shut down or process a transaction
            System.out.println("Menu:");
            System.out.println("  P (process Purchase)");
            System.out.println("  S (Shut down)");
            System.out.println();
            System.out.print("  Your choice: ");

            //User's choice
            run = keyboard.nextLine().charAt(START_OF_INPUT);

            //Checks for invalid input. Ends iteration of loop if input is invalid
            if(run != 'p' && run != 'P' && run != 's' && run != 'S')
            {
              System.out.println("Invalid input!");
              end = true;
            }

            //Ends loop if user selects shutdown
            if(run == 's' || run == 'S')
                end = true;

            //Check if customer qualifies for free chocolate
            if(couponCount >= COUPONS_PER_CHOCOLATE && end != true)
            {
                //Choose whether to claim free chocolate or not
                System.out.println("Use credits to claim free chocolate bar? (Y or N)");
                freeChocolate = keyboard.next().charAt(START_OF_INPUT);

                //Subtracts coupons if user chooses yes. Ends iterations of loop if yes.
                if(freeChocolate == 'Y' || freeChocolate == 'y')
                {
                    System.out.println("Enjoy your free chocolate!");
                    end = true;
                    couponCount -= COUPONS_PER_CHOCOLATE;

                    //Displays new amount of coupons held by user
                    System.out.println("You used " + COUPONS_PER_CHOCOLATE
                      + " coupons and have " + couponCount + " left.");
                }

                //Continues program if user selects no
                else if(freeChocolate == 'N' || freeChocolate == 'n');

                //Checks for invalid input. Ends iteration of loop if Y or N are not input.
                else
                {
                    System.out.println("Invalid response!");
                    end = true;
                }
            }

            if(end != true)
            {
                //How many chocolates to buy. Gives coupons equal to number of chocolates
                System.out.println("How many chocolate bars will you purchase?");
                purchase = keyboard.nextInt();

                //Checks for invalid input
                if(purchase >= 0)
                {
                    couponCount += purchase;
                    System.out.println();
                    System.out.println(" You earned " + purchase + " coupons. You now have a total of " + couponCount + " coupons.");
                } 
                else
                    System.out.println("You can't purchase negative chocolate bars!");
            }
            end = false;
        }
        System.out.println("Thank you, and goodbye!");
        keyboard.close();
    }
}

Any other feedback concerning my program's format would also be appreciated, but my initial question is what I'm most worried about. Thanks in advance!

Kyle
  • 25
  • 5
  • 1
    That error happens when your string is of length 0. You can't get the first char of a 0-length string. Once you get your code working I would suggest you post over at the code review stack exchange for other recommendations related to style, etc. – Roddy of the Frozen Peas Nov 01 '17 at 22:10
  • 2
    Free hint unrelated to your problem: You've gone over the top defining things like `START_OF_INPUT` this actually cause more confusion than it solves. I had to jump to the top just to check it was set correctly. If you used `0`directly I'd have known. – John3136 Nov 01 '17 at 22:11
  • But why is a 0-length string being input? This error pops up without me typing anything. – Kyle Nov 01 '17 at 22:12
  • Why not split it over 2 lines: `string blah = keyboard.nextline();` Now you can check what the string is (using println) and that will probably tell you why `charAt` isn't working. – John3136 Nov 01 '17 at 22:14
  • Also `scanner` has a `hasNextLine()` which might come in useful here. – Roddy of the Frozen Peas Nov 01 '17 at 22:17
  • I'll try it out, thanks and brb. – Kyle Nov 01 '17 at 22:17
  • Okay! I checked out that duplicate, Joe, and made a change that seems to have fixed my problem. I found that putting keyboard.nextLine(); after the line purchase = keyboard.nextInt(); makes the problem go away. I also had forgotten to replace the other time I used keyboard.next() with keyboard.nextLine(). Thank you very much for your assistance. – Kyle Nov 01 '17 at 22:39

0 Answers0