Home > Back-end >  Why this C program can calculate the min but can't calculate the max?
Why this C program can calculate the min but can't calculate the max?

Time:08-25

I'm learning C, and I wrote a program that reads a list of numbers and provides the sum, max, min and mean of the list. The list ends when a negative number is typed.

#include <stdio.h>
#include <stdlib.h>

int main ()
{
    int i, number, sum, divider, min, max;
    double mean;
    int addend[1000];
    char s[80];

    for (i=0; i>=0; i  ) {
        fgets (s, sizeof(s), stdin);
        number = atoi(s);
        addend[i]=number;
        if (addend[i]>=0) {
            continue;
        }
        else break;
    }
    divider=i;
    i=i-1;
    sum=addend[i];
    while (i>=1) {
        sum=sum addend[i-1];
        i=i-1;
    }
    printf("[SUM]\n%i\n", sum);
    if (addend[0]<0) {
        printf("[MIN]\n0\n\n[MAX]\n0\n\n[MEAN]\n0\n");
    }
    else {
        mean=sum/divider;
        i=divider-1;
        min=addend[i];
        while (i>=0) {
            if (addend[i-1]<min) {
                min=addend[i-1];
            }
            i=i-1;
        }
        max=addend[i];
        while (i>=0) {
            if (addend[i-1]>max) {
                max=addend[i-1];
            }
            i=i-1;
        }
        printf("[MIN]\n%i\n\n[MAX]\n%i\n\n[MEAN]\n%f\n", min, max, mean);
    }
    return 0;
}

Everything works fine, except the max (if i type "3, 6, 8, 9, -1" the max is 1075314688). I already found a solution (if I write max=addend[divider-1] on line 42 it works fine), but I'm trying to understand why the code I originally wrote doesn't work. I tried searching for the answer online but I didn't find anything.

CodePudding user response:

You don't reset i when you're recalculating the max. You need to insert i=divider-1; before max=addend[i]; like you did for the minimum:

i=divider-1;
min=addend[i];
while (i>=0) {
    if (addend[i-1]<min) {
        min=addend[i-1];
    }
    i=i-1;
}
i=divider-1; //Unless you do this i==-1 at this point!
max=addend[i];
while (i>=0) {
    if (addend[i-1]>max) {
        max=addend[i-1];
    }
    i=i-1;
}

PS: You should learn about for(;;) loops. This code is asking to be converted in to standard loops. I'm also not sure why you have (i>=0) and then addend[i-1] when i==0 doesn't that access addend[-1]?

CodePudding user response:

In general this code snippet

i=i-1;
sum=addend[i];

can invoke undefined behavior if the first entered number will be negative. In this case i will be equal to 0 and the expression i - 1 will be equal to -1. That means that the expression addend[i] accesses memory beyond the array.

This while loop invokes undefined behavior

    i=divider-1;
    min=addend[i];
    while (i>=0) {
        if (addend[i-1]<min) {
            min=addend[i-1];
        }
        i=i-1;
    }

because when i is equal to 0 the expression addend[i-1] accesses memory beyond the array addend.

And moreover after above loop is equal to -1 so this statement

max=addend[i];

again invokes undefined behavior and the following loop

    while (i>=0) {
        if (addend[i-1]>max) {
            max=addend[i-1];
        }
        i=i-1;
    }

will not be executed.

Also pay attention to that in this statement in the right-side of the assignment

mean=sum/divider;

there is used the integer arithmetic.

The program can look the following way.

#include <stdio.h>
#include <stdlib.h>

int main( void ) 
{
    enum { N = 1000 };
    int addend[N];
    char s[80];

    size_t n = 0;

    while ( n < N && fgets (s, sizeof( s ), stdin ) != NULL )
    {
        int number = atoi( s );
        if ( !( number < 0 ) )
        {
            addend[n  ] = number;
        }
        else
        {
            break;
        }
    }

    if ( n == 0 )
    {
        printf("[MIN]\n0\n\n[MAX]\n0\n\n[MEAN]\n0\n");
    }
    else
    {
        long long int sum = 0;
        for ( size_t i = 0; i < n; i   )
        {
            sum  = addend[i];
        }

        printf( "[SUM]\n%lld\n", sum );

        int min = addend[0];
        int max = addend[0];

        for ( size_t i = 1; i < n; i   )
        {
            if ( max < addend[i] )
            {
                max = addend[i];
            }
            else if ( addend[i] < min )
            {
                min = addend[i];
            }
        }

        double mean = ( double )sum / n;

        printf( "[MIN]\n%i\n\n[MAX]\n%i\n\n[MEAN]\n%f\n", min, max, mean);
    }

}
  •  Tags:  
  • c
  • Related