使用一长串" if / else if" C中的陈述?

时间:2014-09-11 18:30:12

标签: c if-statement

最初我使用了switch / case,但条件必须是变量匹配的常量值,而不是变量是否在范围内的布尔值。

相反,我有这种怪异:

    if ( data[y] > 91 ) {
       grades[9] = grades[9] + 1;
    }
    else if ( data[y] > 88 && data[y] < 92 ) {
        grades[8] = grades[8] + 1;
    }
    else if ( data[y] > 84 && data[y] < 89 ) {
        grades[7] = grades[7] + 1;
    }
    else if ( data[y] > 81 && data[y] < 85) {
        grades[6] = grades[6] + 1;
    }
    else if ( data[y] > 79 && data[y] < 82) {
        grades[5] = grades[5] + 1;
    }
    else if ( data[y] > 74 && data[y] < 79 ) {
        grades[4] = grades[4] + 1;
    }
    else if ( data[y] > 71 && data[y] < 75 ) {
        grades[3] = grades[3] + 1;
    }
    else if ( data[y] > 68 && data[y] < 72 ) {
        grades[2] = grades[2] + 1;
    }
    else if ( data[y] > 59 && data[y] < 69 ) {
        grades[1] = grades[1] + 1;
    else {
        //data[y] < 60:
        grades[0] = grades[0] + 1;
    }

有没有人知道处理这段代码的更好方法,因为我的交换机/案例想法不适用?当然必须有更好的方法来做到这一点。

8 个答案:

答案 0 :(得分:15)

缩短代码最明显的就是摆脱不必要的第二次测试:

if      (data[y] >= 92) ++grades[9];
else if (data[y] >= 89) ++grades[8];
else if (data[y] >= 85) ++grades[7];
else if (data[y] >= 82) ++grades[6];
else if (data[y] >= 80) ++grades[5];
else if (data[y] >= 75) ++grades[4];
else if (data[y] >= 72) ++grades[3];
else if (data[y] >= 69) ++grades[2];
else if (data[y] >= 60) ++grades[1];
else                    ++grades[0];

答案 1 :(得分:6)

这似乎是一种明智的数据驱动方法:

int grade_cutoff[] = { 59, 68, 71, 74, 79, 81, 84, 88, 91, INT_MAX };
int grade_bucket;

for (grade_bucket = 0; data[y] > grade_cutoff[grade_bucket]; grade_bucket++) {
  /* nothing */
}

grades[grade_bucket]++;

答案 2 :(得分:5)

使用循环。您还需要每个等级的最小数据值数组。以下是一些未经测试的代码:

for (int i = 9; i >= 0; i--)
{
    if (data[y] >= minDataValueForGrade[i])
    {
        grades[i]++;
        break;
    }
}

它简短易读,可以很容易地更改与每个年级相对应的值。

答案 3 :(得分:2)

如果你想避免if .. else长篇小说:

int arr[] = {60, 69, 72, 75, 79, 82, 85, 89, 92};
int i = 0;

while (i < sizeof arr/ sizeof *arr && data[y] < arr[i] && i++);

grades[i]++;

答案 4 :(得分:1)

您可以使用简单的查找表:

const unsigned int index[] = { 1, 1, /* ... */, 2, 2, /* ... */ };

++grades[data[y] < 60 ? 0 : index[data[y]]];

答案 5 :(得分:0)

我的C是生锈的,但是,你可以考虑从不同的角度来看问题而不是条件。

您应该(我认为)能够重构您的数据,以便您可以在没有(或者更少)条件的情况下实现决策逻辑。我想的是二维数组或查找表。这些东西......

答案 6 :(得分:0)

int const datum = data[y];
int const index = (datum > 59) + (datum > 68) + (datum > 71)
    + (datum > 74) + (datum > 79) + (datum > 81)
    + (datum > 84) + (datum > 88) + (datum > 91);
++ grades[index];

只需计算指数。

答案 7 :(得分:0)

对于主题的激进变体,假设标记只能在0..100范围内,请考虑创建一个包含分数等级编号的数组:

enum { MAX_SCORE = 100 };
static const int upper_bound[] = { 60, 69, 72, 75, 80, 82, 85, 89, 92, MAX_SCORE+1 };
enum { N_BOUNDS = sizeof(upper_bound) / sizeof(upper_bound[0]) };
int grade_for_score[MAX_SCORE + 1];

int score = 0;
for (int i = 0; i < N_BOUNDS; i++)
{
    while (score < upper_bound[i])
        grade_for_score[score++] = i;
}

设置工作的补偿是处理分数是微不足道的:

assert(data[y] >= 0 && data[y] <= MAX_SCORE);
grades[grade_for_score[data[y]]++;

这可能是一个好处,因为除了分数在[0..MAX_SCORE]范围内的基本验证之外,它不需要任何条件来处理成绩。当然,它确实使用了一些数据空间。当然,如果从文件(或数据库)读取数据,I / O交互时间会完全淹没分级时间,而优化基本上没有意义。

工作代码:

#include <assert.h>
#include <stdio.h>

int main(void)
{
    /* Setup */
    enum { MAX_SCORE = 100 };
    static const int upper_bound[] = { 60, 69, 72, 75, 80, 82, 85, 89, 92, MAX_SCORE+1 };
    enum { N_BOUNDS = sizeof(upper_bound) / sizeof(upper_bound[0]) };
    int grade_for_score[MAX_SCORE + 1];

    int score = 0;
    for (int i = 0; i < N_BOUNDS; i++)
    {
        while (score < upper_bound[i])
            grade_for_score[score++] = i;
    }

    /* Scoring - test each score from [0..MAX_SCORE] */
    int grades[N_BOUNDS] = { 0, };
    int data[1];
    int y = 0;
    for (int i = 0; i <= MAX_SCORE; i++)
    {
        data[y] = i;
        assert(data[y] >= 0 && data[y] <= MAX_SCORE);
        grades[grade_for_score[data[y]]]++;
    }

    /* Print grades */
    int sum = 0;
    for (int i = 0; i < N_BOUNDS; i++)
    {
        sum += grades[i];
        printf("Grade %d: %3d (cumulative %3d)\n", i, grades[i], sum);
    }

    return 0;
}

请注意,可以在编译时初始化grade_for_score表,而不是在运行时执行:

/* Manually generated; not formally checked for correctness */
int grade_for_score[] =
{
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    1,  1,  1,  1,  1,  1,  1,  1,  1,  2,
    2,  2,  3,  3,  3,  4,  4,  4,  4,  4,
    5,  5,  6,  6,  6,  7,  7,  7,  7,  8,
    8,  8,  9,  9,  9,  9,  9,  9,  9,  9,
    9
};

但是,表格很容易从上限表中计算出来,计算机在计算权限方面比人类更好,所以最好在运行时创建表格。

示例运行:

Grade 0:  60 (cumulative  60)
Grade 1:   9 (cumulative  69)
Grade 2:   3 (cumulative  72)
Grade 3:   3 (cumulative  75)
Grade 4:   5 (cumulative  80)
Grade 5:   2 (cumulative  82)
Grade 6:   3 (cumulative  85)
Grade 7:   4 (cumulative  89)
Grade 8:   3 (cumulative  92)
Grade 9:   9 (cumulative 101)