'3 different functions giving the same output depending on variable type in C

I'm trying to write a modular code to do operations on a set of data (Array), the operations are; find: mean, maximum, minimum, median. sort the array, and print statistics.

I'm halfway through this project, wrote 3 functions: mean, maximum, and minimum.

the problem is, the 3 functions output the same value depending on the array declaration variable type. when it is unsigned char, all of them return 93.000, when it is unsigned int all of them return 24.000. I know there is something wrong with my array function setup. I have been searching for it for 4 days. I can't find anything and can't find what is wrong.

here's my code

I have a .h file for documentation of function prototypes:

    /******************************************************************************
* Copyright (C) 2017 by Alex Fosdick - University of Colorado
*
* Redistribution, modification or use of this software in source or binary
* forms is permitted as long as the files maintain this copyright. Users are
* permitted to modify this and use it to learn about the field of embedded
* software. Alex Fosdick and the University of Colorado are not liable for any
* misuse of this material.
*
*****************************************************************************/
/**
* @file  Module of the code
* @brief function declarations to include in header
*
* it defines 7 functions which are used in statistical analysis
*
* @author Mahmoud Saad
* @date   October 10, 2018
*
*/
#ifndef __STATS_H__
#define __STATS_H__

/* Add Your Declarations and Function Comments here */
void print_array (int array[], int length);
/**
* @brief prints array
*
* prints each element with spaces in between
*
* @param array[]         the array itself
* @param length          length of array
* @param
* @param
*
* @return
*/

/* Add Your Declarations and Function Comments here */
float find_median (int array[], int length);
/**
* @brief finds median
*
* sorts elements and if odd number picks the middle if even, divide the 2 middle elements to get median
*
* @param array[]         the array itself
* @param length          length of array
* @param
* @param
*
* @return returns median
*/

/* Add Your Declarations and Function Comments here */
float find_mean (unsigned char array[], int count);
/**
* @brief finds mean
*
* adds all elements and dividies by their number
*
* @param array[]         the array itself
* @param length          length of array
* @param
* @param
*
* @return mean
*/

/* Add Your Declarations and Function Comments here */
int find_maximum (int numbers[], int length);
/**
* @brief finds maximum
*
* stores first value in varable then replace it with any higher value
*
* @param array[]         the array itself
* @param length          length of array
* @param
* @param
*
* @return maximum
*/

/* Add Your Declarations and Function Comments here */
int find_minimum (int numbers[], int length);
/**
* @brief finds minimum
*
* stores first value in vaiable then replaces it with any lower value
*
* @param array[]         the array itself
* @param length          length of array
* @param
* @param
*
* @return minimum
*/

/* Add Your Declarations and Function Comments here */
int sort_array ( int array[], int length);
/**
* @brief sorts array
*
* <Add Extended Description Here>
*
* @param array[]         the array itself
* @param length          length of array
* @param <Add InputName> <add description here>
* @param <Add InputName> <add description here>
*
* @return <Add Return Informaiton here>
*/

/* Add Your Declarations and Function Comments here */
void print_statistics(float mean, int maximum, int minimum);
/**
* @brief sorts array
*
* <Add Extended Description Here>
*
* @param array[]         the array itself
* @param length          length of array
* @param <Add InputName> <add description here>
* @param <Add InputName> <add description here>
*
* @return <Add Return Informaiton here>
*/


#endif /* __STATS_H__ */

another .c file for main and function definitions and code:

    /******************************************************************************
 * Copyright (C) 2017 by Alex Fosdick - University of Colorado
 *
 * Redistribution, modification or use of this software in source or binary
 * forms is permitted as long as the files maintain this copyright. Users are
 * permitted to modify this and use it to learn about the field of embedded
 * software. Alex Fosdick and the University of Colorado are not liable for any
 * misuse of this material.
 *
 *****************************************************************************/
/**
 * @file Statistical analysis
 * @brief Does some analysis on databases
 *
 * <Add Extended Description Here>
 *
 * @author Mahmoud Saad
 * @date   October 4th, 2018
 *
 */



#include <stdio.h>
#include "stats.h"

/* Size of the Data Set */
#define SIZE (40)
#define NULL (0)

int   maximum, minimum;
float mean, median;

void main() {

  unsigned char test[SIZE] = { 34, 201, 190, 154,   8, 194,   2,   6,
                              114, 88,   45,  76, 123,  87,  25,  23,
                              200, 122, 150, 90,   92,  87, 177, 244,
                              201,   6,  12,  60,   8,   2,   5,  67,
                                7,  87, 250, 230,  99,   3, 100,  90};

  /* Other Variable Declarations Go Here */
  int   maximum, minimum;
  float mean, median;

  /* Statistics and Printing Functions Go Here */

  print_array(test, SIZE);
  print_array(test, SIZE);
  mean    = find_mean    (test, SIZE);
  median  = find_median  (test, SIZE);
  maximum = find_maximum (test, SIZE);
  minimum = find_minimum (test, SIZE);
  print_statistics(mean, maximum, minimum);

}

/* Add other Implementation File Code Here */

print_array (int array[], int length){};

float find_median (int array[], int length){};

float find_mean (unsigned char array[], int count){
  int i;
  unsigned int sum =0 ;

  for(i = 0; i < count; ++i){

    sum += array[i];

  }
   float avg = sum/count;
  return (avg);
};

int find_maximum (int numbers[], int length){
     int max, i;
     while ( i < length ){
      if ( i == 0 ) {
       max = numbers[0];    // Must initialize to values in set, not zero
     }


     if ( numbers[i] >= max){
       max = numbers[i];
     }
     i++;
     }

     return(max);
     };

int find_minimum (int numbers[], int length){
    int min, i;
    while ( i < length ){
    if ( i == 0 ) {
      min = numbers[0];    // Move to second item and start comparisons
    }

    if ( numbers[i] <= min){
      min = numbers[i];
    }
    i++;
    }


    return (min);
    };

int sort_array ( int array[], int length){};

void print_statistics(float mean, int maximum, int minimum){
  printf( "The average is: %f\n", mean );
  printf( "The maximum is: %f\n", maximum  );
  printf( "The minimum is: %f\n", minimum  );


};
c


Solution 1:[1]

Assuming you have the datatype of the array matched with what the functions expect, you have two issues here.

The first is in your printing function:

void print_statistics(float mean, int maximum, int minimum){
  printf( "The average is: %f\n", mean );
  printf( "The maximum is: %f\n", maximum  );
  printf( "The minimum is: %f\n", minimum  );
}

minimum and maximum have type int, but you're using the %f format specifier, which expects a double. Using the wrong format specifier invokes undefined behavior.

Use %d to print = an int:

  printf( "The maximum is: %d\n", maximum  );
  printf( "The minimum is: %d\n", minimum  );

The second problem is in find_minimum and find_maximum. Both functions enter a while loop with while ( i < length ) without initializing i. This means its value is indeterminate. Using this value to index an array will likely read past the end of the array, again invoking undefined behavior.

Initialize i to 0 in both functions.

Once you do that, you'll get the following results:

The average is: 93.000000
The maximum is: 250
The minimum is: 2

Solution 2:[2]

  1. All automatic storage duration variables need to be initialised in C.

  2. Your divisions are all in integer arithmetic, which explains the whole-number results. Use the 1.f * sum / count idiom to force evaluation in floating point.

  3. The format specifier for an int in printf is %d. %f is for a float or double.

  4. Whilst being potentially valid in principle, fashioning an int array from a array of unsigned char values opens you up to a lot of potential bugs and undefined behaviour. In particular, the alignment of the unsigned char array might not be appropriate for an int on your platform, and you need to calculate the number of elements carefully. You don't appear to do that.

  5. (Don't use leading double underscores for any symbol. They are reserved.)

Solution 3:[3]

If that is really the code you are using, you have quite some undefined behaviour.

Declaration in your header:

int find_maximum (int array[], int length);

Implementation in your c file:

int find_maximum (int numbers[], int length){
...

Usage in your c file:

unsigned char test[SIZE] = { 34, 201, 190, 154,   8, 194,   2,   6,
                            114, 88,   45,  76, 123,  87,  25,  23,
                            200, 122, 150, 90,   92,  87, 177, 244,
                            201,   6,  12,  60,   8,   2,   5,  67,
                              7,  87, 250, 230,  99,   3, 100,  90};
...
maximum = find_maximum (test, SIZE);

You feed an array of char into a function expecting an array of int. This does not work and should give you some warnings from the compiler. Every access to any array element will use wrong address and the function will access the array beyond its legal memory location.

Instead of comparing values 34, 201, 190, 154, ... or in hex (22, C9, BE, 9A, ...) you are dealing with values 0x9ABEC922, ... assuming 32bit integers.

If you change the type of your array to int you do not have this UB with this function but your other functions have similar problems.

Besides that:

void main() {

In a hosted environment that is not a valid signature for main. It has to be one of these:

int main(void)
int main(int argc, char *argv[])

Solution 4:[4]

define float 0. scale the minimum value as a common mean for other values. it is an infimum for other values.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 dbush
Solution 2
Solution 3
Solution 4 charles