0

When I ran this code and provided 28000/3 as input, it showed:

28000/32766 = 0.

Why on earth would this happen? I'm new to c and this is really confusing.

#include <stdio.h>

int main(void) {
    int divide(int a, int b, int *result);
    int a, b;
    
    scanf("%d %d", &a, &b);
    
    int c;
    
    if (divide(a, b, &c)) {
        printf("%d/%d=%d\n", a, b, c);
    }
    
    return 0;
}

int divide(int a, int b, int *result) {
    int ret = 1;
    if (b == 0) 
        ret = 0;
    else {
        *result = a / b;
    }
    return ret;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 2
    Entering `28000/3` will confuse `scanf` because it's not expecting the `/` character – user3386109 Feb 05 '21 at 05:44
  • 4
    Always check the return value of `scanf` before using its results. – kaylum Feb 05 '21 at 05:45
  • it also doesn't provide the result I intended when the second input b is 0.PLEEEEASE HELP ME – ansley77777723 Feb 05 '21 at 05:48
  • What happens if you output the return value of `scanf()`? What happens if you output the value of `a` and `b` before and after `scanf()``? What happens if you initialise the variables to recognisable values like 2021 and 42? All those are recommended habits to avoid problems with understanding program behaviour. especially when using user input. – Yunnosch Feb 05 '21 at 05:49
  • 1
    What do you expect the result to be when `b` is `0` and what are you getting instead? When asking questions it is best to provide more detail than "doesn't work". – kaylum Feb 05 '21 at 05:49
  • I think the answer below should help you solve the problem. Also, there is no reason for `int *result` as a parameter. Instead, just return the result of the calculation. – Code-Apprentice Feb 05 '21 at 05:52
  • Does this answer your question? [What is the behavior of integer division?](https://stackoverflow.com/questions/3602827/what-is-the-behavior-of-integer-division) – the busybee Feb 05 '21 at 10:40

3 Answers3

2

The scanf() doesn't know if you would enter a division sign /. You need to change its format:

scanf("%d/%d", &a, &b);

So that you could enter 28000/3 or similar inputs.


Here's the perfect code (notice comments):

#include <stdio.h>
#include <limits.h>

// Definitions must be global
int divide(int a, int b, int *result);

int main(void) {
    int a, b;

    // It's programmer's responsibility to ensure the input
    if (scanf("%d/%d", &a, &b) != 2) {
        puts("Arguments are incorrectly passed.");
        return -1;
    }

    int c;

    if (divide(a, b, &c))
        printf("%d/%d=%d\n", a, b, c);
    else
        printf("b is zero.\n"); // also code the 'else' to print an error
                                // if b is zero

    return 0;
}

int divide(int a, int b, int *result) {
    int ret = 1;
    if (b == 0 || (a == INT_MIN && b == -1))
        ret = 0;
    else
        *result = a / b;
    
    return ret;
}
Rohan Bari
  • 7,482
  • 3
  • 14
  • 34
  • 1
    Division will also overflow for `a=INT_MIN` and `b=-1`, with undefined behavior (it crashes on intel CPUs). – chqrlie Feb 05 '21 at 07:54
  • @chqrlie thanks, I did not know about that. I have updated my answer for `divide()`. – Rohan Bari Feb 05 '21 at 08:20
  • @chqrlie sorry for that `stdint.h`. I was a bit confused with MAX and MIN ranges, will take care next of it next time, and I've fixed that conditional syntax, thanks again. – Rohan Bari Feb 05 '21 at 08:28
1

Apart from the wrong input for your scanf (see other answer and comments),
you also have to different return value concepts in your function divide().
You are using both the return value AND the return by pointer parameter, but inconsistently in the two branches of the check against 0.

To make it consistent change the function like:

#include<stdio.h>
int main(void)
{
    int divide(int a,int b,int *result);
     int a=2021,b=42;
     if(2!=scanf("%d %d",&a,&b))
     {
         printf("Scanf failed!\n");
         return 0;
     }
     int c=1970;
     if(!divide(a,b,&c))
     {
         printf("Division failed!\n");
     } else 
     {
         printf("%d/%d=%d\n",a,b,c);
     }
     
     return 0;
}
int divide(int a,int b,int *result)
{
    int ret=1;
    if(b==0)
    {
        ret=0;
        *result = 0;
    } else
    {
        *result=a/b;
        ret = 1; /* not 100% necessary because of init; for symmetry */
    }
    return ret;
}

That gets you (with input "32 4"):

32/4=8

With input "32 0":

Division failed!

With input "32/0":

Scanf failed!
Yunnosch
  • 26,130
  • 9
  • 42
  • 54
  • `ret` is useless, you can just `return 0` instead of `ret = 0;` ... `return ret;` – M.M Feb 05 '21 at 07:01
  • @M.M I do not contradict in general. I tried to stick to OPs design as much as possible. Also, in some work environments (mine for example) there are design rules against multiple returns. So it is not always unneeded. – Yunnosch Feb 05 '21 at 07:53
  • *design rules against multiple returns*: you should fight this rule. You can also remove the initialization of `ret` so there is no redundancy, but you probably have another rule that says *all local objects must be initialized* :) – chqrlie Feb 05 '21 at 07:56
  • Note also that division will overflow for `a=INT_MIN` and `b=-1`, with undefined behavior (program termination on intel CPUs). – chqrlie Feb 05 '21 at 07:58
0

There are multiple problems in your code:

  • [Major] you do not test that scanf() successfully converted 2 integers into a and b. When you type 28000/3, the conversion specification "%d %d" causes scanf() to properly convert 28000 into a but the / does not start a number so scanf() stops there and returns 1, leaving b unchanged. b is uninitialized and happens to contain the value 32766 which explains the output 28000/32766 = 0. You should change the format and test the return value.
  • [Major] you do not update *result in divide() in case of overflow, so c would be unchanged and still uninitialized if b was 0.
  • [Minor] forward declarations such as int divide(int a, int b, int *result); should appear at the global scope. The compiler accepts them in a local scope but it is considered bad style and confusing. The reason for this is the declaration only extends to the end of the main() function, so the actual definition of the divide() function could have a different prototype and this inconsistency would go undetected.
  • [Minor] integer division can overflow and cause undefined behavior (ie: program termination) if b=0, but also if a=INT_MIN (-2147483648) and b=-1. You should detect and report this overflow to the caller using the return value so the caller can distinguish division overflow from a regular 0 quotient.

Here is a modified version:

#include <limits.h>
#include <stdio.h>

/* forward declaration at global scope */
int divide(int a, int b, int *result);

int main(void) {
    int a, b, c;
 
    /* read input values and test for success */
    if (scanf("%d/%d", &a, &b) != 2) {
        printf("invalid input\n");
        return 1;
    }
    
    /* perform division and test for overflow */
    if (divide(a, b, &c)) {
        printf("division overflow: %d/%d\n", a, b);
        return 1;
    } else {
        printf("%d/%d=%d\n", a, b, c);
        return 0;
    }
}

int divide(int a, int b, int *result) {
    /* test all cases of division overflow */
    if (b == 0 || (a == INT_MIN && b == -1)) {
        *result = 0;
        return -1;
    } else {
        *result = a / b;
        return 0;
    }
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189