0

So this is currently what I have right now!

int downPayment;
System.out.printf("How much will the down payment be?: ");

Scanner keyboardIn = new Scanner(System.in);
downPayment = keyboardIn.nextInt();

System.out.println(downPayment);

However, if I were to have a user enter ' $500 ', the build would fail (as scanner 'scans' for only an integer).

Is there a way to use scanner where it would ignore the first index of an 'integer', as I think that having scanner look at the variable as a string and converting the dollar value to an int while appending the first index is super inefficient.

Thanks!

InstantNut
  • 93
  • 1
  • 9

4 Answers4

3

I think that having scanner look at the variable as a string and converting the dollar value to an int while appending the first index is super inefficient.

Drawing conclusions from thinking is for philosophers, not engineers.

Here's your proposed efficient version:

import java.util.*;

class NextInt {
  public static void main(String[] args) {
    Scanner keyboardIn = new Scanner(System.in);
    int downPayment;

    for(int i=0; i<10000000; i++) {
      downPayment = keyboardIn.nextInt();
    }
  }
}

Here's your proposed super inefficient version:

import java.util.*;

class AsString {
  public static void main(String[] args) {
    Scanner keyboardIn = new Scanner(System.in);
    int downPayment;

    for(int i=0; i<10000000; i++) {
      String input = keyboardIn.next();
      if (input.startsWith("$")) input = input.substring(1);
      downPayment = Integer.parseInt(input);
    }
  }
}

We can generate 10 million lines of test data:

yes '1500' | head -n 10000000 > nodollar
yes '$500' | head -n 10000000 > dollar

Now benchmark it (best of 3):

$ time java NextInt < nodollar
real    0m3.544s
user    0m3.759s
sys     0m0.124s

$ time java AsString < dollar

real    0m2.530s
user    0m2.735s
sys     0m0.111s

As it turns out, not only are we talking about upper bound of ~0.4 microseconds saved time per user input, but you are spending your time and effort on a slower implementation. No wonder they say that premature optimization is the root of all evil!

Anyways, that was a tangent that doesn't actually answer the question. Have you considered using skip to skip an optional $?

keyboardIn.skip("[$]?");
downPayment = keyboardIn.nextInt();
that other guy
  • 116,971
  • 11
  • 170
  • 194
  • Nice one. Even if the times were the other way around, it is rather unlikely that this program will be used 10,000,000 times, and we've all spent longer thinking about it than the 1 second that might have been gained overall. – kaya3 Jan 28 '20 at 02:06
  • damn, thank you! im super new to java and this is really helpful, thanks for sharing :) – InstantNut Jan 28 '20 at 02:09
1

Instead of making your program work for users who enter a dollar sign at the start of their number, one option is to tell the user more clearly that they are expected to enter just the number itself. If you put a $ symbol at the end of the prompt, the user will be typing immediately after that $; any sensible user will realise they are not supposed to type an extra $, because it would be visibly wrong on the screen to have two $ signs next to each other.

If anybody is silly enough to type an extra $ anyway, let them see an error message.

System.out.print("How much will the down payment be?: $");

A simple change. Note also that you don't need printf here, just print is sufficient.

kaya3
  • 47,440
  • 4
  • 68
  • 97
0

You could use one of:

downPayment = Integer.parseInt(keyboardIn.next().replace("$",""));
downPayment = Integer.parseInt(keyboardIn.next().substring(1));

But I don't know if it's the "best way".


If you really must keep your nextInt(), you can catch the exception:

try {
  downPayment = keyboardIn.nextInt();
} catch (InputMismatchException ex) {
  // handle it
  downPayment = Integer.parseInt(keyboardIn.next().replace("$",""));
}

But I don't think it's generally advised to handle any RuntimeException.

Scratte
  • 3,056
  • 6
  • 19
  • 26
0

This obviously doesn't handle every case, but you could check if the first value is a '$' character, if so remove it, then check if the remaining String can be parsed as an int:

    public static void getDownPaymentValue() {
        Scanner sc = new Scanner(System.in);
        System.out.print("How much will the down payment be?: ");
        String input = sc.next();

        String validatedInput = validateUserInput(input);
        int downPayment = 0;

        if(isInteger(validatedInput)) {
            downPayment = Integer.parseInt(validatedInput);
        } else {
            System.out.println("Value is not of type int.");
        }

        System.out.println("Validated input is: " + validatedInput);
    }

    public static String validateUserInput(String str) {
        int dollarSignIndex = str.indexOf("$");
        if(dollarSignIndex == 0) {
            str = str.substring(1);
        }
        return str;
    }

    public static boolean isInteger(String str) {
        try {
            Integer.parseInt(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }
djharten
  • 374
  • 1
  • 12