从数组中获取最大最小元素,删除它们并对数组的其余部分求和

时间:2016-09-28 17:34:11

标签: c arrays

我正在尝试从评委中获得5个不同的成绩,并将它们放入阵列中。 然后我尝试从数组中找到max和min元素。 例子{2,3,4,5,6} max = 6,min = 2。 之后,我必须删除6和2,然后添加3 + 4 + 5,这给我一个12的总和。 如何删除然后添加总和?因为看起来我在从数组中删除时遇到错误。这是代码

#include <stdio.h>

int main()
{
    int judge1, judge2,judge3,judge4, judge5,i,max,min;
    int size = 4;


    printf("Judge one grade");
    scanf("%d", &judge1);
    printf("Judge one grade");
    scanf("%d", &judge2);
    printf("Judge one grade");
    scanf("%d", &judge3);
    printf("Judge one grade");
    scanf("%d", &judge4);
    printf("Judge one grade");
    scanf("%d", &judge5);
    int a[] = {judge1, judge2, judge3, judge4, judge5};
    max=a[0];
    for(i=1;i<size;i++){
        if(max<a[i])
            max=a[i];
    }

    min=a[0];
    for(i=1;i<size;i++){
        if(min>a[i])
            min=a[i];
    }

    for (i=0;i < size ;i++) {
        if(a[i] == min || a[i] == max){
            a[i] = a[i+1];
        }
    }

    for (i=0;i < size ;i++) {
        int sum = 0;
        sum+= a[i];
        printf("%d\n", sum);
    }

    return 0;
}

4 个答案:

答案 0 :(得分:2)

这是您的删除代码。基本的想法是,如果它是最小值或最大值,用它后面的那个替换它。

for (i=0;i < size ;i++) {
    if(a[i] == min || a[i] == max){
        a[i] = a[i+1];
    }
}

好的,我们来试试吧。 {4, 3, 6, 5}。 3分是最小,6分是最大

i == 0
a[0] == 4
a[1] == 3
No change: {4, 3, 6, 5}

i == 1
a[1] == 3 (the min)
a[2] == 6 (the max)
a[1] = a[2]: {4, 6, 6, 5}  /* whoops, you replaced the min with the max */

i = 2
a[2] == 6 (the max)
a[3] == 5
a[2] = a[3]: {4, 6, 5, 5}

i == 3
a[3] == 5
a[4] == garbage /* whoops, you walked off the array */
No change

所以有两个问题。当您进行更换时,您必须重新检查新值。如果min和max或彼此相邻,或者有两个最大值,这将是一个问题。

其次是你走出阵列。 i + 1是一面红旗。如果最小值或最大值是最后一个值,则用垃圾替换它。诸如Valgrind之类的内存检查器会发现这些非常非常常见的问题。我强烈建议您始终运行内存检查程序并修复它抱怨的所有内容。

而不是改变数组,这变得棘手,在两次传递中更容易做到这一点。它也是非破坏性的,您无需更改或复制数据。

  1. 找到最小值和最大值
  2. 忽略最小值和最大值
  3. 取平均值

    您可以在一个循环中找到最小值和最大值。

    int min = a[0];
    int max = a[0];
    for( i = 1; i < size; i++ ) {
        if( a[i] < min ) {
            min = a[i];
        }
        if( a[i] > max ) {
            max = a[i];
        }
    }
    

    然后取平均值并忽略最小值和最大值

    int sum = 0;
    int count = 0;
    
    for( i = 0; i < size; i++ ) {
        if( a[i] != min && a[i] != max ) {
            sum += a[i];
            count++;
        }
    }
    
    int avg = sum / count;
    

    这揭示了另一个问题。如果有多个分钟和最大值怎么办?如果分数为{3, 3, 3, 5, 5, 5}怎么办?你想把它们扔掉,得到平均0吗?可能不是。你可能只想丢掉最高和最低的单一分数。

    您可以使seen_minseen_max布尔变量仅跳过minmax一次,但这会变得复杂。 @MikeNakis solution更好,存储最小值和最大值的索引并使用它来跳过。

    int min_idx = 0;
    int max_idx = 0;
    for( i = 1; i < size; i++ ) {
        if( a[i] < a[min_idx] ) {
            min_idx = i;
        }
        if( a[i] > a[max_idx] ) {
            max_idx = i;
        }
    }
    
    int sum = 0;
    int count = 0;
    
    for( i = 0; i < size; i++ ) {
        /* Skip the min and max score */
        if( i == min_idx || i == max_idx ) {
            continue;
        }
    
        sum += a[i];
    
        /* You could replace count with size - 2, but this way
           there's one less assumption */
        count++;
    }
    
    double avg = (double)sum / count;
    

答案 1 :(得分:2)

你在两个for循环中使用的逻辑是错误的。 第一个循环 -

for (i=0;i < size ;i++) {
    if(a[i] == min || a[i] == max){
        a[i] = a[i+1];
    }
}

在这里,您要将下一个元素复制到上一个元素。因此,对于数组[2,3,4,5,6],你将复制3到2,因此数组将变为[3,3,4,5,6],这将在求和时给出错误的结果。< / p>

第二次循环 -

for (i=0;i < size ;i++) {
    int sum = 0;
    sum+= a[i];
    printf("%d\n", sum);
}

这里你在每次迭代中将sum初始化为0,因此a [i]总是会被加到0.因此输出将是最后一个元素值。 你应该在for循环开始之前初始化sum。

回答 -

#include <stdio.h>

int main()
{
    int judge1=2, judge2=3,judge3=4,judge4=5, judge5=6,i,max,min;
    int size = 5;


    int a[] = {judge1, judge2, judge3, judge4, judge5};
    max=0;
    for(i=1;i<size;i++){
        if(a[max]<a[i])
            max=i;
    }
    for (i=max;i<size;i++) {
        a[i] = a[i+1];
    }
    size--;

    min=0;
    for(i=1;i<size;i++){
        if(a[min]>a[i])
            min=i;
    }
    for (i=min;i < size ;i++) {
        a[i] = a[i+1];
    }
    size--;

    int sum = 0;
    for (i=0;i < size ;i++) {
        sum+= a[i];
        printf("%d\n", sum);
    }

    return 0;
}

或者,如果你只需要这里的总和那么简单的解决方案

#include <stdio.h>

int main()
{
    int judge1=2, judge2 = 3,judge3 = 4,judge4 = 5, judge5 = 6, i;
    int size = 5, sum = 0, max, min;
    int a[] = {judge1, judge2, judge3, judge4, judge5};
    max = a[0]; 
    min = a[0];
    for (i=0;i < size ;i++) {
        if(max<a[i])
            max=a[i];
        if(min>a[i])
            min=a[i];
        sum+= a[i];
    }
    sum = sum - (max + min);
    printf("%d\n", sum);
    return 0;
}

答案 2 :(得分:1)

不要再次遍历数组,而是使用索引。请注意,在您的代码中,您在循环内部重置sum,因此它只显示最后一个值,并且在循环结束时不在范围内(因此它将消失)。您也可以在循环内打印,而不是在计算完全总和之后打印。

int imin = 0, imax = 0;
max=a[0];
for(i=1; i<size; i++){
    if(max<a[i]) {
        imax = i;
        max=a[i];
    }
}

min=a[0];
for(i=1; i<size; i++){
    if(min>a[i]) {
        min=a[i];
        imin = i;
    }
}

a[imin] = 0; // Does not contribute to the sum
a[imax] = 0; // Does not contribute to the sum

int sum = 0;
for (i=0; i<size; i++) {
    sum += a[i];
}
printf("sum = %d\n", sum);   

答案 3 :(得分:1)

甚至不需要阵列。计算最小值,最大值和总和:

unsigned min = -1u;  // min is set to the greatest unsigned value
unsigned max = 0;    // max is set to the least unsigned value
unsigned sum = 0;

for (int i=0; i<5; i++) {
  unsigned judge;
  printf("Judge one grade ");
  if (scanf("%u", &judge) != 1) break; // validate input
  if (judge > max) max = judge;
  if (judge < min) min = judge;
  sum += judge;
}

if (min > max) {
  printf("No valid input\n");
  return -1;
}

// print sum less the min and max, which is OP's goal
unsigned sum_less_min_max = sum - min - max;
printf("sum = %u\n", sum_less_min_max);