-2

I'm trying to validate an input that should only accept customerType as R or C. It is not case sensitive. I get an error with my code, it says my String customerType is missing:

import java.text.NumberFormat;
import java.util.InputMismatchException;
import java.util.Scanner;

public class InvoiceApp
{
  public static void main(String[] args)
  {
    // Begin input
    Scanner sc = new Scanner(System.in);
    String choice = "y";

    while (!choice.equalsIgnoreCase("n"))
    {
      // get the input from the user
      // create catch block for customerType(r or c)
      try
      {
        System.out.print("Enter customer type (r/c): ");
        String customerType = sc.next();
      }
      catch (InputMismatchException e)
      {
        if (customerType != "r" || "c")
        {
          sc.next();
          System.out.println("Enter a valid customer type r or c");
          continue;
        }
        else
        {
          System.out.print("Enter subtotal:   ");
        }
      }
      double subtotal = sc.nextDouble();
      // get the discount percent
      double discountPercent = 0;
      if (customerType.equalsIgnoreCase("R"))
      {
        if (subtotal < 100)
          discountPercent = 0;
        else if (subtotal >= 100 && subtotal < 250)
          discountPercent = .1;
        else if (subtotal >= 250)
          discountPercent = .2;
      }
      else if (customerType.equalsIgnoreCase("C"))
      {
        if (subtotal < 250)
          discountPercent = .2;
        else
          discountPercent = .3;
      }
      else
      {
        discountPercent = .1;
      }

      // calculate the discount amount and total
      double discountAmount = subtotal * discountPercent;
      double total = subtotal - discountAmount;

      // format and display the results
      NumberFormat currency = NumberFormat.getCurrencyInstance();
      NumberFormat percent = NumberFormat.getPercentInstance();
      System.out.println("Discount percent: " + percent.format(discountPercent)
          + "\n" + "Discount amount:  " + currency.format(discountAmount) + "\n"
          + "Total:            " + currency.format(total) + "\n");

      // see if the user wants to continue
      System.out.print("Continue? (y/n): ");
      choice = sc.next();
      System.out.println();
    }
  }
}
JynXXedRabbitFoot
  • 996
  • 1
  • 7
  • 17
  • 3
    You've put the declaration `String customerType` inside your `try`, so it only has scope within that `try`. Declare `String customerType;` before your `try` and then in your `try` use `customerType = sc.next();` – Zircon Oct 10 '16 at 18:09
  • 2
    Also don't use `==` or `!=` to compare `Strings`:`customerType != "r" || "c"`. Use `.equals()` or `.equalsIgnoreCase()`... – brso05 Oct 10 '16 at 18:13
  • 3
    and you must compare on both sides of the operator. It should look like this: `( !customerType.equalsIgnoreCase("r") || !customerType.equalsIgnoreCase("c") )` – Orin Oct 10 '16 at 18:14
  • 1
    [`next()`](https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html#next--) actually **cannot** throw `InputMismatchException`, but even if it could, the exception would have meant that `customerType = sc.next()` failed to execute, which means that nothing was read from input, so trying to validate `customerType` in the catch-block is totally meaningless, even if you did get the code to compile. --- *Curious:* What made you think that you needed to write all the code in a catch clause like that? – Andreas Oct 10 '16 at 18:40

2 Answers2

1

First of all, the cause of your error is that customerType string's scope is limited to the try block in which it has been declared. Since it cannot be accessed outside try block (in your case, inside catch block), the compiler generates an error.

And you don't need to put your code in try/catch blocks as there is no code which can generate exceptions.

To solve this, there can be more than one ways:

  1. Declare the customerType string outside try block and also initialize it to either null or empty string.

  2. Second way (which I would prefer if try/catch blocks are needed) is to move all the logic inside try block. This way you won't have to declare it outside try block, and all the code that uses customerType will remain clean (without any faults), so you won't have to worry about the error. And, also include the code to execute when the mentioned exception occurs inside catch block. Your catch block should only contain that code which runs only if exception occurs.

These suggestions were related to problems with your code.

  1. As there is no requirement of try/catch block, so removing these blocks and putting your code outside them in main will alone work.

Another problem with your code is that you have typed the conditions inside if statement incorrectly. The correct way is:

if (customerType.equals("r") || customerType.equals("c")){
                ...
            }

Apart from that you need to declare discountPercent (which you didn't) and initialize to 0 as well just before using the discountPercent.

Anyways, here is the main method with corrected code (rest of the lines will be same as yours).

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    String choice = "y";

    while (!choice.equalsIgnoreCase("n")){
        System.out.print("Enter customer type (r/c): ");
        String customerType = sc.next();
        if (customerType.equalsIgnoreCase("r")||customerType.equalsIgnoreCase("c")){
            sc.next();
            System.out.println("Enter a valid customer type r or c");
            continue;
        }
        else{
            System.out.print("Enter subtotal:   ");
        }
        double subtotal = sc.nextDouble();
        double discountPercent = 0;
        if (customerType.equalsIgnoreCase("R")){
            if (subtotal < 100)
                discountPercent = 0;
            else if (subtotal >= 100 && subtotal < 250)
                discountPercent = .1;
            else if (subtotal >= 250)
                discountPercent = .2;
        }
        else if (customerType.equalsIgnoreCase("C")){
            if (subtotal < 250)
                discountPercent = .2;
            else
                discountPercent = .3;
        }
        else{
            discountPercent = .1;
        }

        // calculate the discount amount and total
        double discountAmount = subtotal * discountPercent;
        double total = subtotal - discountAmount;

        // format and display the results
        NumberFormat currency = NumberFormat.getCurrencyInstance();
        NumberFormat percent = NumberFormat.getPercentInstance();
        System.out.println(
                "Discount percent: " + percent.format(discountPercent)
       + "\n" +
                "Discount amount:  " + currency.format(discountAmount) 
       + "\n" +
                "Total:            " + currency.format(total) + "\n");

        // see if the user wants to continue
        System.out.print("Continue? (y/n): ");
        choice = sc.next();
        System.out.println();
    }
}

Let me know if you have any further doubts. I will be more than happy to help you.

Edit 1 :

As suggested by @Andreas, I have corrected my conditional statements that I typed wrong.

Dhruv Singhal
  • 145
  • 2
  • 17
  • 1
    The correct way is certainly not `customerType != "r" || customerType != "c"`. Read [comment by @brso05](http://stackoverflow.com/questions/39964145/validating-for-java-only-two-string-characters-allowed#comment67208327_39964145) or see [How do I compare strings in Java?](http://stackoverflow.com/q/513832/5221149) – Andreas Oct 10 '16 at 18:47
  • @Andreas yes, I missed it in hurry, and corrected also. – Dhruv Singhal Oct 10 '16 at 19:04
0

This works, but it makes no sense that you loop on customer continue prompt without updating a total sale value.

import java.text.NumberFormat;
import java.util.Scanner;

public class InvoiceApp
{
  public static void main(String[] args)
  {
    // Begin input
    Scanner sc = new Scanner(System.in);
    String customerType = null;
    boolean choice = true;
    while (choice)
    {
      // get the input from the user
      System.out.print("Enter customer type (r/c): ");
      customerType = sc.next();
      while (!customerType.equalsIgnoreCase("r")
          && !customerType.equalsIgnoreCase("c"))
      {
        System.out.println("Enter a valid customer type r or c");
        customerType = sc.next();
      }

      System.out.print("Enter subtotal:   ");

      double subtotal = sc.nextDouble();
      // get the discount percent
      double discountPercent = 0;
      if (customerType.equalsIgnoreCase("R"))
      {
        if (subtotal < 100)
          discountPercent = 0;
        else if (subtotal >= 100 && subtotal < 250)
          discountPercent = .1;
        else if (subtotal >= 250)
          discountPercent = .2;
      }
      else if (customerType.equalsIgnoreCase("C"))
      {
        if (subtotal < 250)
          discountPercent = .2;
        else
          discountPercent = .3;
      }
      else
      {
        discountPercent = .1;
      }

      // calculate the discount amount and total
      double discountAmount = subtotal * discountPercent;
      double total = subtotal - discountAmount;

      // format and display the results
      NumberFormat currency = NumberFormat.getCurrencyInstance();
      NumberFormat percent = NumberFormat.getPercentInstance();
      System.out.println("Discount percent: " + percent.format(discountPercent)
          + "\n" + "Discount amount:  " + currency.format(discountAmount) + "\n"
          + "Total:            " + currency.format(total) + "\n");

      // see if the user wants to continue
      System.out.print("Continue? (y/n): ");
      String userInput = sc.next();
      choice = userInput.equalsIgnoreCase("y");
      System.out.println();
    }
    sc.close();
  }
}
JynXXedRabbitFoot
  • 996
  • 1
  • 7
  • 17
  • You're welcome, I would appreciate it if you accepted my answer as correct then! To accept an answer, choose one answer that you believe is the best solution to your problem. To mark an answer as accepted, click on the check mark beside the answer to toggle it from greyed out to filled in. – JynXXedRabbitFoot Oct 11 '16 at 11:57