3

This isn't a serious problem or anything someone has asked me to do, just a seemingly simple thing that I came up with as a mental exercise but has stumped me and which I feel that I should know the answer to already. There may be a duplicate but I didn't manage to find one.

Suppose that someone asked you to write a piece of code that asks the user to enter a number and, every time the number they entered is not zero, says "Error" and asks again. When they enter zero it stops.

In other words, the code keeps asking for a number and repeats until zero is entered. In each iteration except the first one it also prints "Error".

The simplest way I can think of to do that would be something like the folloing pseudocode:

int number = 0;
do
{
    if(number != 0)
    {
        print("Error");
    }
    print("Enter number");
    number = getInput();
}while(number != 0);

While that does what it's supposed to, I personally don't like that there's repeating code (you test number != 0 twice) -something that should generally be avoided. One way to avoid this would be something like this:

int number = 0;
while(true)
{
    print("Enter number");
    number = getInput();
    if(number == 0)
    {
        break;
    }
    else
    {
        print("Error");
    }
}

But what I don't like in this one is "while(true)", another thing to avoid.

The only other way I can think of includes one more thing to avoid: labels and gotos:

    int number = 0;
    goto question;
error:
    print("Error");
question:
    print("Enter number");
    number = getInput();
    if(number != 0)
    {
        goto error;
    }

Another solution would be to have an extra variable to test whether you should say "Error" or not but this is wasted memory.

Is there a way to do this without doing something that's generally thought of as a bad practice (repeating code, a theoretically endless loop or the use of goto)?

I understand that something like this would never be complex enough that the first way would be a problem (you'd generally call a function to validate input) but I'm curious to know if there's a way I haven't thought of.

  • Why is "while(true)" a thing to avoid? – A. I. Breveleri Jun 12 '14 at 10:20
  • In this example it's not that important (because it's short) but in general, the best arguments against while(true) I've read are a)it makes it harder for a (human) reader to know what ends the loop and b)it makes it easier for future changes to remove the clause by mistake. – George T Jun 12 '14 at 15:21
5

The following solution avoids repetition and separates the concerns of getting the input and validating it:

do
{
  print "Enter number"
  number = getInput()
} while(!numberValid(number))

bool numberValid(number) {
  if (number == 0) { 
    return true
  } else {
    print "Error!"
    return false
  }
}
  • One of the only uses I know of for putting the while at the end. – Robert Harvey Jun 10 '14 at 16:09
0

In Ruby I would consider this to be a guard clause and I would write it as either:

do_something if condition

or

do_something unless condition

I use these sparingly though. If there is a lot of code (more than 2 statements or lines say) I prefer the traditional if then else construct.

The main time I use is is for short conditions so that I can write the single line:

procA if x=1

instead of the 3 lines:

if x=1 then
  procA
end
0

I'd separate the two behaviours The first is getting a number for the user, the second is validating it and eventually re-asking it So I'd go like this int number = 0; print "Enter number"; number = getInput(); while(number != 0) { print "Error!"; number = getInput(); } Maybe you could not like the double input line, but I think it's a nice trade off

  • I'd say this has the same "problem" (for my personal tastes) as the original example. More so if you repeat the second "Enter number" line. :) – George T Jun 10 '14 at 7:34
0

You could do something like:

int number;
while((number = solicitNumber()) != 0) {
    print("Error!");
}

...

int solicitNumber() {
    print("Enter number");
    return getInput();
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.