C:逻辑运算符

C: Logical operators

在此代码中,用户必须输入 his/her 科目成绩 (1-10) 和 his/her 缺勤 (0-14)。如果 he/she 成绩 >=5 且缺席 <=2,则学生通过。

我对成绩和缺勤数都超出计划限制的可能性有疑问。 "right" 逻辑运算符是什么:

#include <stdio.h>
#include <stdlib.h>
int main()
{   
    int gr, ap;

    printf("GIVE YOUR SUBJECT GRADE:\n");
    scanf("%d", &gr);
    printf("GIVE YOUR SUBJECT ABSENCES\n");
    scanf("%d", &ap);

    if (ap >= 0 && ap <= 14 && gr >= 0 && gr <= 10)
    {
       if (gr >= 5 && ap <= 2)
          printf("YOU PASSED!\n");
       else if (gr < 5 && ap <=2)
          printf("FAILED DUE TO YOUR GRADE\n");
       else if (gr >= 5 && ap > 2)
          printf("FAILED DUE TO YOUR ABSENCES\n");
       else if (gr < 5 && ap > 2)
          printf("FAILED DUE TO YOUR GRADE AND ABSENCES\n");   
    }
    else 
     {                    
        if (ap >= 0 && ap <= 14 && gr < 0 || gr > 10)  
             printf("FALSE GRADE NUMBER\n");       
        else if (gr >= 0 && gr <= 10 && ap < 0 || ap > 14)
             printf("FALSE ABSENCES NUMBER\n");
//here is the problem
        else if (gr < 0 || gr > 10 && ap < 0 || ap > 14) 
             printf("FALSE ABSENCES AND GRADE NUMBERS\n");
      }     
    system("pause");
    return 0;
}

由于 && 优先于 ||,所以这里需要括号:

ap >= 0 && ap <= 14 && (gr < 0 || gr > 10)
//                     ^                 ^

否则条件解释为

(ap >= 0 && ap <= 14 && gr < 0) || (gr > 10)

这会导致问题。

其他两个条件也一样——它们应该如下:

(gr >= 0 && gr <= 10) && (ap < 0 || ap > 14)
(gr < 0 || gr > 10) && (ap < 0 || ap > 14)

请注意,当您一遍又一遍地评估相同的条件时,最好创建一个变量来存储一次结果,然后再使用该变量:

int validGrade = gr > 0 && gr <= 10;
int validAbsences = ap >= 0 && ap < 14;

现在你可以这样写代码了:

if (validGrade && validAbsences) {
    ...
} else {
    if (validAbsences && !validGrade) {
        ...
    } else if (!validAbsences && validGrade) {
        ...
    } else {
        ...
    }
}

你首先检查 gr 是否超出范围而不是 ap,然后你检查 ap 是否超出范围但不 gr,如果两者都不是其中一个为真则两者都必须超出范围,为此你只需要最后一个 else 语句。

但是上面两个条件都不对,把||改成&&。事实上,您并没有真正检查 apgr,因为如果一个在范围内,您就知道另一个在范围外。所以你可以这样简化它:

// If ap is in range, that means gr must be out of range
if (ap >= 0 && ap <= 14)
    printf("FALSE GRADE NUMBER\n");
// else if gr is in range then ap must be out of range
else if (gr >= 0 && gr <= 10)
    printf("FALSE ABSENCES NUMBER\n");
// else both ap and gr are out of range
else
    printf("FALSE ABSENCES AND GRADE NUMBERS\n");

我还有另外几个建议,比如改用 unsigned int,这样值就永远不会低于零。您还可以使用宏来简化代码的可维护性和可读性。

也许是这样的:

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

#define AP_IN_RANGE(ap)  ((ap) <= 14)
#define GR_IN_RANGE(gr)  ((gr) <= 10)

int main(void)
{   
    unsigned int gr, ap;

    printf("GIVE YOUR SUBJECT GRADE:\n");
    scanf("%u", &gr);
    printf("GIVE YOUR SUBJECT ABSENCES\n");
    scanf("%u", &ap);

    if (AP_IN_RANGE(ap) && GR_IN_RANGE(gr))
    {
       if (gr >= 5 && ap <= 2)
          printf("YOU PASSED!\n");
       else if (gr < 5 && ap <=2)
          printf("FAILED DUE TO YOUR GRADE\n");
       else if (gr >= 5 && ap > 2)
          printf("FAILED DUE TO YOUR ABSENCES\n");
       else
          printf("FAILED DUE TO YOUR GRADE AND ABSENCES\n");   
    }
    else
    {                    
        if (AP_IN_RANGE(ap))
            printf("FALSE GRADE NUMBER\n");       
        else if (GR_IN_RANGE(gr))
            printf("FALSE ABSENCES NUMBER\n");
        else
            printf("FALSE ABSENCES AND GRADE NUMBERS\n");
    }     
}

当然,你真的应该确保用户输入是否有效,所以你需要检查什么scanf returns。这将防止用户输入一些字母而不是有效的无符号数字。