所以基本上我的开关案例有效但我的教授说有太多的回报而且#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;}
};
我没有看到它有什么问题,我相信它可以写得更好。是否有人能够以更友好的方式向我展示一种格式化方法?我的教授也希望我在开关中使用中断,不知道为什么要使用中断返回。
答案 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 here有illustrated 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;
}
一开始的额外回报并没有显着增加复杂性,因为它处于可预测的位置。在大型函数中间出现问题只是意外回归。
另一方面,这是微不足道的风格论点,可以分散实际问题。你的代码有两个更大的问题,我希望你的教授给你打电话。
你的函数没有参数。相反,month
和year
是全局变量。这是非常糟糕的风格。它使您的程序难以理解,因为任何事物都可能产生任何影响。相反,传递它们。
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 ;
}