Home > Enterprise >  Creating an exception without conditions?
Creating an exception without conditions?

Time:09-19

I have to create a program in which I input 2 values simultaneously but, these values must range from 50 to 127. If the value is less than 50 or above 127 it should show an exception saying "value entered" is too low or too high. As a requirement for the program, I cannot use flow-control statements. I have not tried anything as I am lost

import java.util.Scanner;

public class A1_Q1 {

    public static void main(String[] args) {
        // declaration of variables
        double x, y, z;
        int p, q;
        Scanner kBoard = new Scanner(System.in);

        System.out.println("Welcome to the Simple 3D-Space Program:");
        System.out.println("                                       ");
        System.out.print("Enter values for 'p' and 'q' simultaneously. Must be between 50 and 127:");

        String input = kBoard.nextLine();

//separating first number and second number from the inputed line
        String firstNum = input.substring(0, input.indexOf(" "));
        String secondNum = input.substring(input.indexOf(" "), input.length());

//isolating numbers from the strings and filtering out
        String numOnlyP = firstNum.replaceAll("[^0-9]", "");
        String numOnlyQ = secondNum.replaceAll("[^0-9]", "");

//transforming string into integer values
        p = Integer.parseInt(numOnlyP);
        q = Integer.parseInt(numOnlyQ);

//to check and see if previous code was functioning correctly
        System.out.println(p   " "   q);
    }

}

CodePudding user response:

The constraint against using flow control statements is highly artificial, but it does force you into a certain direction. For the program to behave differently for some inputs than it does for others requires flow control. If you cannot use flow control in your program then that means the needed flow control must be somewhere else. And the only "somewhere else" you are allowed to use is java.util.Scanner.

As a blooming programmer, some of the things you need to learn and have ready at all times at the tip of your brain are the powers of two, and certain ones of them especially. Among those is 27 = 128, which has special significance as one more than 127, the maximum value of an 8-bit two's complement integer, such as a Java byte (these properties are closely related). And lo and behold, the maximum value your program is supposed to accept is 127.

Read the API docs of Scanner, especially those for scanning inputs of various specific Java types. You will find some that can serve the purpose of (as a side effect) throwing an exception for inputs larger than 127. If you want to throw a custom exception instead, then you can catch the one thrown by the Scanner and throw one of your choice in its place -- provided that try / catch is not considered flow control.

Scanner could be pressed into service for an exception for violation of the lower bound, too, but that would require a very unnatural hack.

Details are left as the exercise they are intended to be.

CodePudding user response:

This question is a tad disingenuous. A requirement that 50-127 is accepted, the rest is not, is not normally possible without flow control. So we need flow control, but, we're not allowed to use flow control.

Quite the dilemma.

It's a bit like an escape room. You must screw together this intricate thing, but, you don't have a screwdriver (all your pockets were emptied before entering it), so now what? Well, you look around the room. What tools do you have? Even if they are epically not suited to the job, can they be used to deliver?

So, let's look. What do we have? We have scanner.

We need to look at what you can do with those, and see if that helps, because other than Scanner you're not given much room to work.

And lo! Scanner delivers. It's a method that is almost never used with scanner, but it's there, and it'll give us a way through: The next(Pattern) method can do the job.

Quoting from the javadoc:

Returns the next token if it matches the specified pattern.

Great!

Now, I'm flabbergasted, but the docs are broken. Java is used by millions of people and the docs are taken fairly seriously, so that is mostly an indictment on how little this method is used. Nobody, apparently, noticed. The thing missing from the docs is subtle, but important: What happens if the next token in the stream does not match the specified pattern? The docs don't say. But the scanner acts the exact same way as when you call e.g. nextInt() and the next token is not an int: It throws InputMismatchException.

This means next(Pattern) is the complete package: Will pass if input 'matches the pattern' and throws if it does not, so now all we need is a pattern that matches if the input is 50-127 and fails otherwise. We can trivially do that, though we'll need to dive into Regular Expressions to do the job - as that is the 'language' for the pattern we can provide to this next method. (There is a String variant too, but it just parses your string as... a regular expression, so we can't get out of reading up on those).

Scanner s = new Scanner(System.in);
int value = s.next("[5-9][0-9]|1[0-1][0-9]|12[0-7]");

It's a rather unwieldy pattern, but it'll get the job done. This pattern says:

  • The input has to be one of these 3 different options (a|b|c is regexp for: either a, or b, or c)
  • Option 1: A 5/6/7/8/9, followed by any digit.
  • Option 2: A 1, followed by a 0 or a 1, followed by any digit.
  • Option 3: A 1, a 2, and then a 0/1/2/3/4/5/6/7.

That'll covers 50-127. If you want e.g. 00050 to be okay too, stick a 0* on the front, which regexp for 'any amount of zeroes'.

I think this exercise is quite a reach. As the answers provided so far clearly attest, no java programmer would get in their right mind to solve such a task by using the regexp pattern powers of scanner, they'd just read an int and use an if like normal. As the unwieldiness of that regexp shows, using a regex pattern to limit numeric input is not really what it is meant for. A key insight into writing readable, flexible code is to avoid doing that: Using a thing in a way that the author of the thing clearly was not at all thinking about when they wrote it is a fine way to create confusing code that runs into bugs quickly and may no longer work nearly as well in future updates of said thing. I guess it's testing if you can think creatively and read documentation, perhaps?

If you can contact the author of this question, you might want to have them read this answer too :)

I'll be filing a bug over at OpenJDK about the subtle mistake in the docs, at any rate.

  • Related