【问题标题】:Why is the result of this c code "days: 33" and not "days: 30"?为什么这个 c 代码的结果是“days: 33”而不是“days: 30”?
【发布时间】:2021-07-14 02:06:24
【问题描述】:

我正在为考试而学习,在一次旧考试中,有人询问以下代码的输出是什么。我对这段代码如何输出“天:33”感到困惑。有什么方法可以轻松解释吗?

编辑:感谢您的解释,是的,我知道这段代码的逻辑没有意义(就计算给定年份给定月份的实际天数而言),它只是一个古老的考试问题。

#include <stdio.h>

int calcDays(int, int);

int main(){

    int days;
    
    days = calcDays(11, 2020);
    
    printf("days: %d\n", days);

    return 0;
}

int calcDays(int month, int yr){

    int days = 28;
    
    switch(month)
    {
        case 2:    days += 1 - yr % 4;
        case 4:
        case 6:
        case 9:
        case 11:   days += 2;
        default:   days += 3;
    }
    
    return(days);
}

【问题讨论】:

  • 请注意,yr % 4 是一个介于 0 到 3 之间的数字。
  • 您的switch/case 没有breaks。
  • 提示:case 失败。总是break!
  • 看来你需要了解一下break 声明
  • 您还需要阅读公历闰年的完整规则。

标签: c switch-statement label break


【解决方案1】:

switch 语句是“计算跳转”。它所做的只是跳转到附加语句中的一个标签(通常是包含多个带有标签的语句的复合语句),或者,如果没有任何标签匹配,则跳转到附加语句之外。

所以switch (month) 跳转到标记为case 2 的语句或标记为case 4 的语句,或标记为case 6 的语句,或标记为case 9 的语句,或标记为case 11 的语句或一个标记为default。然后程序继续正常执行:它执行跳转到的语句,以及之后的语句,以及之后的语句,等等。

标签不会将语句划分为单独的集合。案例 2 不会在 case 4 标签所在的位置结束。 case 2语句执行后,控制继续到case 4语句;它不会跳出switch 语句。

所以,一旦程序跳转到语句case 11: days += 2;,它就会执行days += 2;。然后它继续下一条语句,即default: days += 3;,并执行该语句。

注意default: days += 3; 是一个语句,case 11: days += 2; 也是。在任何语句前面加上一个标签会产生一个新语句:

days += 2; 是一个声明。 case 11: days += 2; 是一个语句(包含另一个语句 days += 2;)。 case 9: case 11: days += 2; 是一个语句(包含另外两个语句)。 case 6: case 9: case 11: days += 2; 是一个语句,以此类推。

【讨论】:

    【解决方案2】:

    在函数内的switch语句中,这两个标签之间没有break语句

    case 11:   days += 2;
    default:   days += 3;
    

    所以这些陈述

    days += 2;
    days += 3;
    

    按顺序进行评估。

    如果有像这样的break语句,你可以得到预期的结果

    case 11:   days += 2; break;
    
    default:   days += 3;
    

    例如如果参数month设置为2那么所有这些语句

    days += 1 - yr % 4;
    days += 2;
    days += 3
    

    在这段代码中sn-p

    case 2:    days += 1 - yr % 4;
    case 4:
    case 6:
    case 9:
    case 11:   days += 2;
    default:   days += 3
    

    将被评估。

    注意这句话

    days += 1 - yr % 4;
    

    没有意义,因为除以 4 的余数可以是 0、1、2 或 3。

    【讨论】:

      【解决方案3】:

      您需要防止您的case 掉线:

      int calcDays(int month, int yr){
      
          int days = 28;
          
          switch(month)
          {
              case 2:
                days += leapOffset(yr);
                break;
              case 4:
              case 6:
              case 9:
              case 11:  
                days += 2;
                break;
              default:
                days += 3;
          }
          
          return(days);
      }
      

      更简单、更难搞砸的方法:

      int calcDays(int month, int yr) {
          switch(month)
          {
              case 2:
                return 28 + leapOffset(yr);
                break;
              case 4:
              case 6:
              case 9:
              case 11:  
                return 30;
                break;
              default:
                return 31;
          }
          
          return(days);
      }
      

      这两个都需要有效的leapOffset() 计算:

      int leapOffset(int yr) {
        return ((yr % 4 == 0) && (yr % 100 != 0) || (yr % 400) == 0)) ? 1 : 0;
      }
      

      【讨论】:

        【解决方案4】:

        你得到 33 而不是 30,因为在 case:11 中没有中断。你可能想把它写成:

        case 11:   {
            days += 2;
            break;
        }
        
        

        【讨论】:

          【解决方案5】:

          您的开关最后没有中断,因此所有内容都将添加到天数。试试这个:

          switch(month)
          {
              case 2:    days += 1 - yr % 4; break;
              case 4:
              case 6:
              case 9:
              case 11:   days += 2; break;
              default:   days += 3; break;
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2019-01-11
            • 1970-01-01
            • 2021-12-15
            • 1970-01-01
            • 2019-08-17
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多