3

I am confused about writing a program that takes '/' character from user and warning to user not to use 0 in numerator. I have build the program but I want an alternative method to using the goto statement.

# include <stdio.h>
int main()
{
    char o;
    int num1,num2;
    printf("Enter one operator like '+' '-' '/' '%%' '*' : ");
    scanf("%c",&o);
    printf("Enter 1st number: ");
    scanf("%d",&num1);
my: printf("Enter 2nd number: ");
    scanf("%d",&num2);

Below I want to remove these 2 lines but it should achieve the same result as it works.

    if(o=='/' && num2==0 ){
        printf("You can't divide by zero \n");
        goto my;
    }    
    switch(o) {
        case '+':
            printf("%d + %d = %d",num1, num2, num1+num2);
            break;
        case '-':
            printf("%d - %d = %d",num1, num2, num1-num2);
            break;
        case '*':
            printf("%d * %d = %d",num1, num2, num1*num2);
            break;
        case '/':
            printf("%d / %d = %d",num1, num2, num1/num2);
            break;
        case '%':
            printf("%d %% %d = %d",num1, num2, num1%num2);
            break;
        default:
            printf("Operator is not correct");
            break;
    }
    printf("\n\n");
    system ("pause");
}
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • 1
    You shouldn't remove the code and make the answers look meaningless – Gopi Feb 23 '15 at 05:35
  • See [Goto still considered harmful](http://stackoverflow.com/questions/46586/goto-still-considered-harmful/) for a discussion of the pros and cons of `goto` statements in general. – Jonathan Leffler Feb 23 '15 at 05:56
  • You should test the return valueof `scanf` to avoid undefined behavior and endless loop on EOF. – chqrlie Feb 23 '15 at 07:21
  • Be aware that 0 is not the only value that will cause a division overflow: `INT_MIN / -1` will produce an exception and crash your program. Try typing `-2147483648` and `-1` as inputs. – chqrlie Feb 23 '15 at 07:22
  • You only test for zero division, but the modulo operator `%` has the same problem. – chqrlie Feb 23 '15 at 07:24

3 Answers3

8

There is nothing wrong with goto in and of itself!

This is what most people fail to understand, instead simply parroting a poorly chosen snippet from a paper given decades ago, one that Dijkstra himself later came to regret, stating something along the lines of having "a bad feeling that people are making a religion out of it".

If people would simply try to understand the reasons behind guidelines like use of goto, break and continue, or limiting exit points from functions, and so on, they'd be far better practitioners of the art.

What Dijkstra actually railed against, and what I agree with whole-heartedly, was the "unbridled use of the go to statement", in a computing environment where there was mostly little else in terms of iteration. The fact that many environments only had goto could lead to a lot of spaghetti code, very hard to follow.

I actually consider blind dogmatism in the industry far more of a problem than goto statements ever were :-) The problem with goto is its misuse, since, as mentioned, it can make code much harder to follow and what I tend to do when I hear these pronouncements is ask:

Is this code hard to follow or maintain because it breaks the "rules"?

If you were to restructure your code as follows:

// ===================================================
// Get the second number, disallowing zero if dividing.
getSecondNum:
    printf ("Enter 2nd number: ");
    scanf ("%d", &num2);
    if ((o == '/') && (num2 == 0)) {
        printf ("You can't divide by zero \n");
        goto getSecondNum;
    }
// ===================================================

you would be hard-pressed trying to come up with a do or while based solution that was more readable or understandable. You may match the readability but you'll often find that a poorly selected choice between the zero-or-more do and one-or-more while can render the code less readable.

For what it's worth, this is about as close as I can get to the same code in a non-goto-using way:

// ===================================================
// Get the second number, disallowing zero if dividing.
do {
    printf ("Enter 2nd number: ");
    scanf ("%d", &num2);
    if ((o == '/') && (num2 == 0)) {
        printf ("You can't divide by zero \n");
} while ((o == '/') && (num2 == 0));
// ===================================================

but that has other issues such as code duplication. That too can be fixed but it generally involves the use of more variables, or the use of break which has exactly the same issue as goto here(b).


So, bottom line, don't take as gospel something you don't understand, it doesn't matter whether it comes from Dijkstra, Knuth, dkr, or even whatever other gods you may believe in :-)

Think about why it may be considered gospel in the first place, then that's how you decide whether it applies in a given situation(a).

I frequently use goto in state machines, error handling and so on, places where it actually simplifies the code that would otherwise be harder to understand.


(a) This includes advice from random people on the net, even from those called "paxdiablo" :-)


(b) One thing you might want to consider is to let the user enter zero even for a division, and then just sort it out in the calculation with something like:

case '/':
    if (num2 == 0)
        printf ("%d / 0 is undefined, cannot divide by zero", num1);
    else
        printf ("%d / %d = %d", num1, num2, num1 / num2);
    break;

I'd probably prefer the catch-early option myself but this may be a viable solution for you.

paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • i also write the same code in floating point numbers, where floating point number is not reasonable with '==' sing. what i should do there? @paxdiablo – Zainab Nabeel Feb 23 '15 at 05:43
  • @Zainab, comparing floating point numbers is a totally different question, one that's been asked many times here on SO. Basically, you check for "close enough" rather than equal, such as if the difference is less than 0.00001% of the average, depending on all sorts of things. I'd suggest searching SO for the questions already asked on that topic. – paxdiablo Feb 23 '15 at 05:46
  • i have searched about floating point number, and approximately got the point. Now, using do while loop in integer variables, if i enter 0.50 in num2, loop doesn't break. What should i do there? Why it does not pick the real number before the decimal point? – Zainab Nabeel Feb 23 '15 at 07:09
  • @Zainab, again this has nothing to do with _this_ question, you should ask another so that you get more people than just me looking at it. In this case, if you enter 0.50, you'll scan the int 0 and be left with the pointer looking at `.`. The next time you go to scan an int, it will be invalid because of the `.`. This will go on forever. – paxdiablo Feb 23 '15 at 07:32
0

There are multiple alternatives check out mine.

while(1)
{
   printf("Enter a number\n");
   if(scanf("%d",&num2) == 1)
   {
     if(o == '/' && num2 == 0)
     {
       printf("You can't divide by zero\n");
     }
     else
     break;
   }
}
Gopi
  • 19,784
  • 4
  • 24
  • 36
0

Convert it into a loop like below:

do {
    printf("Enter 2nd number: ");
    scanf("%d",&num2);
    if(o=='/' && num2==0 ){
        printf("You can't divide by zero \n");
        continue;
    } else {
        break;
    }
} while (1);
SMA
  • 36,381
  • 8
  • 49
  • 73