通过查看开发人员职位的访谈协议,我发现了以下问题:“提供了一种代码,该代码将按从n到0的降序打印数字,而不使用(隐藏或显式)比较运算符(打印功能的实现不计算在内)”。 尽管该任务与我无关,但它占据了我的全部空间,我决定考虑解决问题的方法(尽管我仍然不知道谁和何时解决哪个任务需要这种代码优化方法)。
首先想到的是尝试使用模式。 像这样
template<int n> void print() { printf("%d\n", n); print<n - 1>(); } template<> void print<0>() { printf("0\n"); } int main(int argc, char* argv[]) { print<N>(); return 0; }
问题在于编程是一门工程学科,而不是一门神秘的学科,如果系统中发生“某事”,则应描述“它”并为其分配资源,在这种情况下,因为模板的开发发生了在编译阶段,对此类构造的嵌套有限制(它是正确的,并且要感谢上帝。),编译器正确地发出了“致命错误C1202:递归类型或函数依赖上下文太复杂”,其大小N更大2000。
接下来想到的是将经典方法与函数指针一起使用。
typedef void(*PrintFunc)(int); void printZero(int); void printNumber(int n); PrintFunc g_functors[] = {printZero, printNumber}; void printZero(int) { printf("0\n"); } void printNumber(int n) { printf("%d\n", n--); g_functors[!!n](n); } int main(int argc, char* argv[]) { printNumber(N); return 0; }
但是即使那样,自然法则对我们的限制仍然让人感到自己,并且由于函数调用的嵌套受到堆栈大小的限制,因此获得了合法的“堆栈溢出”,其值为N> 4630。
在这个地方,失望和愤怒完全笼罩了我,我意识到,要完全解决这个问题,您就不应该回避任何事情,包括最肮脏的把戏。 问题是对于某些N值,我们需要将控制权转移到代码的必要部分。 当我们有条件语句可供使用时,这没问题,但是当条件语句不存在时,我们必须求助于巫术。 在远古时代,可以使用goto方法解决此问题,但是从那时起,女巫猎人和其他恶龙战士已经严重限制了其功能(这也是不错的选择),我们想写这样的东西
g_functors[0] = [](int){print("0\n"); goto end; } g_functors[1] = [](int n){print("%d\n", n); goto begin; } begin: g_functors[!!n](n--); end:
但是我们不能。
因此,尽管我被禁止从事黑魔法,但在这种情况下,我决定通过在前面的示例中添加一点魔法来作为例外。
void printZero(int); void printNumber(int n); PrintFunc g_functors[] = {printZero, printNumber}; void printZero(int) { printf("0\n"); throw 0; } void printNumber(int n) { printf("%d\n", n); } int main(int argc, char* argv[]) { int n = N; try{ begin: g_functors[!!n](n--); goto begin; } catch (...){} return 0; }
这就完全解决了问题(对于任何N)。
PS:我将很高兴听到其他解决此问题的方法