需要帮助使我的开关盒看起来更好

时间:2016-10-02 03:40:12

标签: c++ c++11

所以基本上我的开关案例有效但我的教授说有太多的回报而且#34;使用变量结果,然后在结束时返回它!"

所以这是我的代码

int getMonthValue(){
    switch(month){
        case(1): //January
            if(isLeapYear(year) == true)
                return 6;
            else
                return 0;
        case(2): // February
            if(isLeapYear(year) == true)
                return 2;
            else
                return 3;
        case(3): //March
            return 3;
        case(4): //April
            return 6;
        case(5): //May
            return 1;
        case(6): //June
            return 4;
        case(7): //July
            return 6;
        case(8): //August
            return 2;
        case(9): //September
            return 5;
        case(10): //October
            return 0;
        case(11): //November
            return 3;
        case(12): //December
            return 5;}                                                                 

};

我没有看到它有什么问题,我相信它可以写得更好。是否有人能够以更友好的方式向我展示一种格式化方法?我的教授也希望我在开关中使用中断,不知道为什么要使用中断返回。

7 个答案:

答案 0 :(得分:4)

在您的案例中使用逻辑运算符不是一个好主意。使用数组!这段代码非常好理解,速度非常快。并且很容易更改返回值:

unsigned getMonthValue(unsigned month, unsigned year) {
   const static unsigned ans[2][12] = {
//      Jan F  M  A  M  J  J  A  S  O  N  Dec
        {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 }       //normal year 
      , {6, 2, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5 }       //leap year
  };
  assert(month <= 12);
  assert(month >= 1);
  const size_t month_index = month - 1;
  const size_t leap = isLeapYear(year) ? 1 : 0;
  return ans[leap][month_index];
}

<强>更新

有关此技术的非常有用的链接 - Lookup_table。感谢Schwern

答案 1 :(得分:3)

试试这个

int getMonthValue(int month, int year){
map<int,int> staticAnswers;
staticAnswers[3] = 3;
staticAnswers[4] = 6;
staticAnswers[5] = 1;
staticAnswers[6] = 4;
staticAnswers[7] = 6;
staticAnswers[8] = 2;
staticAnswers[9] = 5;
staticAnswers[10] = 0;
staticAnswers[11] = 3;
staticAnswers[12] = 5;
switch(month){
    case(1): //January
        if(isLeapYear(year) == true)
            return 6;
        else
            return 0;
    case(2): // February
        if(isLeapYear(year) == true)
            return 2;
        else
            return 3;
    default:
        return staticAnswers[month];
};

答案 2 :(得分:3)

以下是我的写作方式:

int
getMonthValue (int month, int year)
{
    switch(month)
    {
    case 1: // January
         if (isLeapYear(year))
             return 6;  // explanation here of why 6 is the right value
         return 0;

    case 2: // February
         if (isLeapYear(year))
             return 2;  // explain why 2 is the right value
         return 3;

    case 3:   return 3;  // March
    case 4:   return 6;  // April
    case 5:   return 1;  // May
    case 6:   return 4;  // June
    case 7:   return 6;  // July
    case 8:   return 2;  // August
    case 9:   return 5;  // September
    case 10:  return 0;  // October
    case 11:  return 3;  // November
    case 12:  return 5;  // December
    }
}

我知道许多缺乏经验的程序员会反对不一致的陈述。但是以这种方式编写 - 语句结构完全遵循逻辑。也就是说,词汇结构揭示了逻辑。

答案 3 :(得分:0)

关于switch语句的一个好处是你被允许 fall-through case语句,所以这在C ++中是允许的:

switch (month) {
  case 4:
  case 7:
    return 6;
  case 9:
  case 12:
    return 5;

哪个应该减少return语句的数量,但会改变可读顺序。

另一个选项,因为您要检查范围[1-12]中的所有值,将使用数组,例如:

static const int values[] = { 3, 6, 1 ... };
if (month < 3) {
  /* leap year check */
}
else
  return values[month - 3]; // we subtract 3 to start from March

但这最终应该主要是个人偏好,所以教授给出的建议听起来只是唠叨你。

答案 4 :(得分:0)

您的教授严格执行"Single Entry, Single Exit"(SESE)Structured Programming规则。所有输入都作为参数出现。所有输出都是在最后通过一个return语句。例行程序中间没有惊喜。没有全局变量。副作用极小。没有。当您不必仔细扫描代码返回或在函数中间调用gotos时,它使代码更易于阅读。

这是一个很好的经验法则。在20世纪70年代构思时,这是一个激进的想法。现在就是你做事的方式。

与许多样式规则一样,问题在于您严格执行规则而不考虑为什么规则存在;你可以结束相反的效果。 Some of the answers hereillustrated that nicely。样式规则必然是现实的简化版本,并且列举所有边缘情况和异常是困难的。要允许一些摆动的空间。

对于像你这样的小例程,做一个非常清楚的事情,适合一个页面,并且是一个易于阅读的开关语句...就像你正在做的那样做多个回报。为最终存储返回值会使其更长,更复杂,从而违背规则的要点。而且你避免忘记break,这是一个非常常见的C陷阱。

违反SESE的另一个好理由是early exit。结构化编程说要做到这一点:

int some_function(int arg) {
    int ret;

    if( arg < 0 ) {
        ret = arg;
    }
    else {
        this is the real
        meat and potatoes
        of the function
        and because of
        that one simple
        condition at the
        top it all
        is indented an
        extra level
        adding complexity
        to the whole
        function

        ret = whatever;
    }

    return ret;
}

每个级别的嵌套都会增加复杂性。提前退出可以避免这种不必要的嵌套,方法是将简单的案例放在最顶层。

int some_function(int arg) {
    if( arg < 0 ) {
        return arg;
    }

    this is the real
    meat and potatoes
    of the function
    which doesn't
    have to be indented
    an extra level
    since we dealt with
    all the simple cases
    at the top

    return whatever;
}

一开始的额外回报并没有显着增加复杂性,因为它处于可预测的位置。在大型函数中间出现问题只是意外回归。

另一方面,这是微不足道的风格论点,可以分散实际问题。你的代码有两个更大的问题,我希望你的教授给你打电话。

将值传递给函数,不要使用全局变量。

你的函数没有参数。相反,monthyear是全局变量。这是非常糟糕的风格。它使您的程序难以理解,因为任何事物都可能产生任何影响。相反,传递它们。

int getMonthValue( int month, int year ) {
    ...
}

检查你的界限。

第二个问题是你的函数没有边界检查。如果month为0,该怎么办? 13? -50? 20398?它将通过switch语句落到函数的底部。编译器应该已经警告过你了。

test.c:48:1: warning: control may reach end of non-void function [-Wreturn-type]
}
^

要解决这个问题,除非你能想出一个不好的理由,否则总是在default上加上switch条款。

switch(month) {
    ...all your regular cases...

    default:
        fprintf(stderr, "Month %d is out of range.\n", month);
        exit(1);
}

答案 5 :(得分:-1)

你的教授是对的,不要在学习过程中担心这一切

尝试这样的事情:

 a b 1, 
 b c 1,
 a c 1,
 d e 2

在你的情况下也不要使用支架,它根本看起来不干净。

我有时也会选择在我的案例中使用括号&#34; {&#34;和&#34;}&#34;虽然在这个例子中它可能更适合不要。天气与否使用括号是我不知道的最佳做法。

我正在按照这些方式对这些括号进行辩护&#34; {&#34;和&#34;}&#34;

无论如何这是一个更清洁的案例陈述,希望它有所帮助。

答案 6 :(得分:-1)

使用三元运算符的可能解决方案!:

int getMonthValue()
{
    return 
        month == 3  ? 3 : 
        month == 4  ? 6 :
        month == 5  ? 1 :
        month == 6  ? 4 :
        month == 7  ? 6 :
        month == 8  ? 2 :
        month == 9  ? 5 :
        month == 10 ? 0 :
        month == 11 ? 3 :
        month == 12 ? 5 :
        month == 1  ?     isLeapYear(year) ? 6 : 0 :
        month == 2  && isLeapYear(year) ? 2 : 3 ;
}