Application throws InputMismatchException when string is assigned to double

75 views Asked by At

I am writing a program where I need to check if a string (name) contains any whitespaces or not.

Here's part of my program :

    public static void main()
    {
        Scanner sc = new Scanner(System.in) ;
        String name = "" ;
        boolean error = false ;
        do {
            if(error) System.out.println("Sorry, error. Try again") ;
            error = false ;
            
            System.out.print("Enter your name : ") ;
            name = sc.next() ;
            if(name=="") error = true ;
        } while(error) ;
        
        double amount = 0.00 ;
        do {
            if(error) System.out.println("Sorry, error. Try again") ;
            error = false ;
            
            System.out.print("Enter amount of purchase : ") ;
            amount = sc.nextDouble() ;
            if(amount<=1) error = true ;
        } while(error) ;
    }
}

For checking errors in the name string input, I need to check if the string contains any whitespaces or not because otherwise java.lang.InputMismatchException is thrown when it accepts amount (and when the entered name contains whitespace with another string).

Is there any predefined function that does this?

3

There are 3 answers

3
Reilas On BEST ANSWER

You can use the following method to determine if a String contains a white-space character.

boolean containsSpace(String string) {
    for (char character : string.toCharArray()) {
        switch (character) {
            case ' ', '\t', '\n', '\r', '\f' -> {
                return true;
            }
        }
    }
    return false;
}

Also, you're going to want to test the name value using the String.equals method, as opposed to the == equality operator.

if (name.equals("")) error = true;

Furthermore, the main method requires a single String array, or String varargs parameter, to be valid.

public static void main(String[] args)

Here is a quick demonstration of how I would implement the task.

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    
    String name;
    while (true) {
        System.out.print("Name: ");
        name = scanner.nextLine();
        if (!containsSpace(name))
            break;
        System.out.println("Name contains white-space.  Re-enter.");
    }
    
    double amount;
    while (true) {
        System.out.print("Amount: ");
        try {
            amount = Double.parseDouble(scanner.nextLine());
            break;
        } catch (NumberFormatException exception) {
            System.out.println("Invalid amount.  Re-enter.");
        }
    }
    
    System.out.printf("Name is '%s'%n", name);
    System.out.printf("Amount is %,f%n", amount);
}
1
aled On

If you want to read a floating point number you have to explicitly ask for it using Scanner.nextDouble(). next() returns a String. You can not assign a string to a number in Java.

0
Pavol Varga On

I am writing a program where I need to check if a string (name) contains any whitespaces or not. so there isn't any predefined functions?

Of course, there is - isWhitespace,
plus the trim() method might be considered,
to remove leading and trailing spaces from the user input: name = scanner.next().trim();

boolean containsSpace(String string) {
  for (char character : string.toCharArray()) {
    if (Character.isWhitespace(character)) {
      return true;
    }
  }
  return false;
}

And the second part of your problem - to get the "amount" as a double, I would split into two simplistic functions to follow single responsibility principle and improve maintainability and testability. And I will put method getDouble(String string) into a dedicated class, and package, let say: myproject.common.Numbers

So the whole program will consist methods like this:

public static void main(String[] args) {
  final var instance = new StackOverflow();
  instance.parseNameAndAmount();
}

void parseNameAndAmount() {
  Scanner scanner = new Scanner(System.in);
  final var name = getName(scanner);
  final var amount = getAmount(scanner);
  scanner.close();

  print("Name is %s".formatted(name));
  print("Amount is %s".formatted(amount));

}

String getName(Scanner scanner) {
  String name;
  do {
    print("Enter a name with no spaces: ");
    name = getName(scanner.nextLine().trim());
  } while (name == null);
  return name;
}

String getName(String string) {
  if (string == null || string.isEmpty()) {
    return null;
  }

  if (containsSpace(string)) {
    return null;
  }
  return string;
}

boolean containsSpace(String string) {
  for (char character : string.toCharArray()) {
    if (Character.isWhitespace(character)) {
      return true;
    }
  }
  return false;
}


double getAmount(Scanner scanner) {
  Double amount;
  do {
    print("Enter amount of purchase (valid number): ");
    amount = getDouble(scanner.nextLine().trim());
  } while (amount == null);
  return amount;
}

Double getDouble(String string) {
  if (string == null) {
    return null;
  }

  try {
    return Double.valueOf(string);
  } catch (NumberFormatException e) {
    return null;
  }
}

void print(String string) {
  System.out.println(string);
}

As I mentioned testability and maintainability, one of the tests might look like this, of course to be thorough, more tests needs to be done.

@Test
void getDouble_When_NegativeWithExponent() {
  // Given
  final var given = "-12.45E9";

  // when
  final var actual = stackOverflow.getDouble(given);

  // Then
  assertThat(actual)
      .isNotNull()
      .isNegative();
}