3种不同的函数根据C中的变量类型提供相同的输出

时间:2018-10-09 13:30:57

标签: c

我正在尝试编写模块化代码来对一组数据(数组)进行操作,这些操作是;查找:平均值,最大值,最小值,中位数。对数组进行排序,并打印统计信息。

我已经完成了这个项目的一半,编写了3个函数:平均值,最大值和最小值。

问题是,这3个函数根据数组声明变量类型输出相同的值。当它是unsigned char时,它们都返回93.000;当它是unsigned int时,它们都返回24.000。我知道我的数组函数设置有问题。我已经搜索了4天。我什么也找不到,也找不到什么问题。

这是我的代码

我有一个.h文件来记录功能原型:

    /******************************************************************************
* 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__ */

另一个.c文件,用于定义主要和功能以及代码:

    /******************************************************************************
 * 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  );


};

3 个答案:

答案 0 :(得分:4)

  1. 所有自动存储持续时间变量都需要在C中初始化。

  2. 您的除法是整数中的 all 个,它解释了整数结果。使用1.f * sum / count惯用语来强制进行浮点运算。

  3. intprintf格式说明符%d%f用于floatdouble

  4. 虽然从原理上讲可能是有效的,但从int值的数组中构造unsigned char数组会使您面临许多潜在的错误和不确定的行为。特别是,unsigned char数组的对齐方式可能不适用于您平台上的int,因此您需要仔细计算元素的数量。您似乎没有这样做。

  5. (任何符号都不要使用前导双下划线。保留它们。)

答案 1 :(得分:1)

假设您的数组的数据类型与函数所期望的匹配,那么这里有两个问题。

第一个是您的打印功能:

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  );
}

minimummaximum的类型为int,但是您使用的是%f格式说明符,期望使用double。使用错误的格式说明符会调用undefined behavior

使用%d打印= int

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

第二个问题在find_minimumfind_maximum中。这两个函数都使用while ( i < length )进入while循环,而不初始化i。这意味着其值是不确定的。使用此值索引数组可能会读取数组的末尾,从而再次调用未定义的行为。

在两个函数中将i初始化为0。

这样做,您将获得以下结果:

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

答案 2 :(得分:1)

如果这确实是您正在使用的代码,那么您会有一些未定义的行为。

标头中的声明:

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

c文件中的实现:

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

c文件中的用法:

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);

您将char数组输入到期望int数组的函数中。 这是行不通的,应该会向编译器发出一些警告。 每次访问任何数组元素都将使用错误的地址,并且该函数将访问其合法内存位置之外的数组。

您不是在比较值34, 201, 190, 154, ...或以十六进制(22,C9,BE,9A,...)来比较值0x9ABEC922, ...,而是假设32位整数。

如果将数组的类型更改为int,则没有此功能的UB,但是其他功能也有类似的问题。

除此之外:

void main() {

在不是main的有效签名的托管环境中。 它必须是其中之一:

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