我有这个疯狂的家庭作业,我必须创建一个表达式来验证关于朱利安和格里高利历以及许多其他事情的日期......
问题是它必须全部在一个表达式中,所以我不能使用任何;
是否有任何在表达式中定义变量的选项?像
这样的东西d < 31 && (bool leapyear = y % 4 == 0) || (leapyear ? d % 2 : 3) ....
我可以在哪里定义和初始化一个或多个变量,并在不使用任何;
的情况下在一个表达式中使用它们?
编辑:明确地说,它必须是一行表达式。没有功能..
我现在正在做的就是编写宏并扩展它们,所以我最终会得到像这样的东西
#define isJulian(d, m, y) (y < 1751 || (y == 1752 && (m < 9) || (m == 9 && d <= 2)))
#define isJulianLoopYear(y) (y % 4 == 0)
#define isGregorian(d, m, y) (y > 1573 || (y == 1752 && (m > 9) || (m == 9 && d > 13)))
#define isGregorianLoopYear(y) ((y % 4 == 0) || (y % 400 = 0))
// etc etc ....
看起来这是解决问题的唯一合适方式
编辑:这是原始问题
假设我们有包含日,月和年的变量d
m
和y
。任务是写一个单独的表达式,决定日期是否有效。如果date有效,则值应为true(非零值);如果date无效,则值为false(零)。
这是表达式的一个例子(正确的表达式看起来像这样):
d + 4 == y ^ 85 ? ~m : d * (y-2)
这些是错误答案(不是表达式)的例子:
if ( log ( d ) == 1752 ) m = 1;
或:
for ( i = 0; i < 32; i ++ ) m = m / 2;
仅提交仅包含一个不带;
的单个表达式的文件。不要提交命令或整个程序。
答案 0 :(得分:6)
((m >0)&&(m<13)&&(d>0)&&(d<32)&&(y!=0)&&(((d==31)&&
((m==1)||(m==3)||(m==5)||(m==7)||(m==8)||(m==10)||(m==12)))
||((d<31)&&((m!=2)||(d<29)))||((d==29)&&(m==2)&&((y<=1752)?((y%4)==0):
((((y%4)==0)&&((y%100)!=0))
||((y%400)==0)))))&&(((y==1752)&&(m==9))?((d<3)||(d>13)):true))
答案 1 :(得分:5)
<evil>
如果可以重用现有的,为什么要定义新的? errno
是一个完美的临时变量。
</evil>
答案 2 :(得分:4)
我认为作业的目的是要求你在不使用变量的情况下这样做,而你想要做的事情可能会破坏它的目的。
答案 3 :(得分:2)
在标准C ++中,这是不可能的。 G ++有一个名为statement expressions的扩展,可以做到这一点。
答案 4 :(得分:2)
我不相信你可以,但即使你可以,它只会在(在你的例子中)中定义括号内,并且不能在它们之外使用。
答案 5 :(得分:1)
第一:不要。它可能很可爱,但即使有一个允许它的扩展,代码高尔夫是一个危险的游戏,几乎总是会导致比它解决的悲伤。
好的,回到家庭作业定义的“真实”问题。你能做出额外的功能吗?如果是这样,而不是捕获它是否是变量中的闰年,而是创建一个返回正确值的函数isLeapYear(int year)。
是的,这意味着你不止一次计算它。如果这最终成为一个性能问题,我会非常惊讶......首先担心这一点是不成熟的优化。
如果不允许你写这些功能,我会感到非常惊讶。这似乎是这样一个练习的一半。
...
好的,所以这里是您需要做的快速概述。
首先,基本验证 - 月,日,年是可能的值 - 月0-11(假设从0开始),第0-30天,年非负(假设是约束)。
一旦你过去了,我可能会检查1752个特殊情况。
如果这不相关,可以非常简单地处理“常规”月份。
这给我们留下了闰年的情况,可以分为两个表达式 - 是否是闰年(将根据格里高利/朱利安进一步细分),以及日期是否有效
所以,在最高级别,你的表达式看起来像这样:
areWithinRange(d,m,y)&amp;&amp; pass1752SpecialCases(d,m,y)&amp;&amp; pass30DayMonths(d,m,y)&amp;&amp; pass31DayMonths(d,m,y)&amp;&amp; passesFebruaryChecks(d,M,Y)
如果我们假设只有主动检测到规则中断,我们才会从子表达式返回false(30月份31天,30DayMonth规则返回false,但2月30天无关紧要,所以传递真实),那么我们可以说这个级别的逻辑是正确的。
此时,我会为各个部分编写单独的函数(作为纯表达式,单个返回...语句)。一旦你有了这些,你可以用扩展版本替换顶级表达式中的方法调用。只要确保你把所有内容括号括号(是一个单词吗?)。
我还会创建一个使用该表达式的测试工具程序,并且有许多有效和无效的输入,并验证您做的是正确的。您可以在函数中编写它,以便通过执行以下操作来轻松剪切和粘贴最终的内容:
bool isValidDate(int d, int m, int y)
{
return
// your expression here
}
由于表达式本身就是一行,因此很容易剪切和粘贴。
您可以找到其他方法来简化您的逻辑 - 除了1752特殊情况,例如,1到28之间的日期总是有效。
答案 6 :(得分:1)
您的解决方案,我不会完全为您提供,可能会遵循这些方针:
isJulian ? isJulianLeapyear : isGregorianLeapyear
为了使其更具体,它可能是这样的:
isJulian ? (year % 4) == 0 : ((year % 4) == 0 || (year % 400) == 0)
您必须确保您的算法正确无误。我不是日历专家,所以我不知道。
答案 7 :(得分:0)
你显然必须以某种方式通过日期。除此之外,您真正要做的就是链接&&
和||
(假设我们将日期作为tm
结构):
#include <ctime>
bool validate(tm date)
{
return (
// sanity check that all values are positive
date.tm_mday >= 1 && date.tm_mon >= 0 && date.tm_year >= 0
// check for valid days
&& ((date.tm_mon == 0 && date.tm_mday <= 31)
|| (date.tm_mon == 1 && date.tm_mday <= (date.tm_year % 4 ? 28 : 29))
|| (date.tm_mon == 2 && date.tm_mday <= 31)
// yadda yadda for the other months
|| (date.tm_mon == 11 && date.tm_mday <= 31))
);
}
实际上不需要date.tm_year % 4 ? 28 : 29
左右的括号,但为了便于阅读,我将它们包括在内。
<强>更新强>
查看评论时,您还需要类似的规则来验证公历中不存在的日期。
更新II
由于您在处理过去的日期,因此您需要实施更正确的闰年测试。但是,我一般会处理未来的日期,这个不正确的闰年测试将在2012年,2016年,2020年,2024年,2028年,2032年,2036年,2040年,2044年,2048年,2052年,2056年,2060年,2064年, 2068年,2072年,2076年,2080年,2084年,2088年,2092年和2096年。我将预测,在此测试失败之前,2100年基于硅的计算机将被遗忘的遗物。我严重怀疑我们会在当时使用的量子计算机上使用C ++。此外,我不会被分配来修复错误的程序员。
答案 8 :(得分:0)
考虑到这是家庭作业,我认为最好的建议是获得自己的解决方案。
如果我正在处理这项任务,我会先违反规则。
我会写一个给定变量d,m和y的c ++函数,返回一个关于日期有效性的布尔结果。我会根据需要使用尽可能多的非递归辅助函数,并且可以随意使用if,else if和else,但是没有大声循环。
然后我会内联所有帮助函数
我会减少所有if,else if和else语句到? :记谱法
如果我成功地限制了我对变量的使用,我或许可以将所有这些减少到没有变量的单个函数 - 其中的主体将包含我寻找的单个表达式。
祝你好运。