为什么这个c代码的结果是"days: 33"而不是"days: 30"?
Why is the result of this c code "days: 33" and not "days: 30"?
我正在为考试而学习,在一次旧考试中被问及以下代码的输出是什么。我对这段代码如何输出“天数: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);
}
你的switch最后没有break,所以一切都会加到days上。试试这个:
switch(month)
{
case 2: days += 1 - yr % 4; break;
case 4:
case 6:
case 9:
case 11: days += 2; break;
default: days += 3; break;
}
您需要防止您的 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;
}
在函数内的switch语句中,这两个标签之间没有break语句
case 11: days += 2;
default: days += 3;
所以这些陈述
days += 2;
days += 3;
依次评估。
如果有像
这样的中断语句,你可以得到预期的结果
case 11: days += 2; break;
default: days += 3;
例如,如果参数月份设置为 2,则所有这些语句
days += 1 - yr % 4;
days += 2;
days += 3
在此代码段中
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。
你得到 33 而不是 30,因为在 case:11 中没有中断。你可能想把它写成:
case 11: {
days += 2;
break;
}
一个switch
语句是一个“计算跳跃”。它所做的只是跳转到附加语句中的一个标签(通常是包含多个带有标签的语句的复合语句),或者,如果 none 个标签匹配,则跳转到附加语句之外。
因此 switch (month)
跳转到标记为 case 2
的语句或标记为 case 4
的语句,或标记为 case 6
的语句,或标记为 [=15] 的语句=],或者标有 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;
是语句,依此类推。
我正在为考试而学习,在一次旧考试中被问及以下代码的输出是什么。我对这段代码如何输出“天数: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);
}
你的switch最后没有break,所以一切都会加到days上。试试这个:
switch(month)
{
case 2: days += 1 - yr % 4; break;
case 4:
case 6:
case 9:
case 11: days += 2; break;
default: days += 3; break;
}
您需要防止您的 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;
}
在函数内的switch语句中,这两个标签之间没有break语句
case 11: days += 2;
default: days += 3;
所以这些陈述
days += 2;
days += 3;
依次评估。
如果有像
这样的中断语句,你可以得到预期的结果case 11: days += 2; break;
default: days += 3;
例如,如果参数月份设置为 2,则所有这些语句
days += 1 - yr % 4;
days += 2;
days += 3
在此代码段中
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。
你得到 33 而不是 30,因为在 case:11 中没有中断。你可能想把它写成:
case 11: {
days += 2;
break;
}
一个switch
语句是一个“计算跳跃”。它所做的只是跳转到附加语句中的一个标签(通常是包含多个带有标签的语句的复合语句),或者,如果 none 个标签匹配,则跳转到附加语句之外。
因此 switch (month)
跳转到标记为 case 2
的语句或标记为 case 4
的语句,或标记为 case 6
的语句,或标记为 [=15] 的语句=],或者标有 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;
是语句,依此类推。