关于短路求值本身,这里就不赘述了,可以去看wiki上面的解释,http://zh.wikipedia.org/wiki/%E7%9F%AD%E8%B7%AF%E6%B1%82%E5%80%BC
今天在实验课的网站上发现了一道新出的选做题,题目是:给定数据组数T以及T个不大于40的正整数,要求输出对应的斐波那契数列中的对应项,要求不能使用乘除法、for、while、if 、else、switch、case 等关键字以及条件判断语句(A?B:C)。一开始看错了题目没看到T组,想用宏又想不出来(宏太笨了只查找替换文本……),只想到了打表一个方法,后来发现竟然有T组数据,直接就跪了。然后灵机一动,想到了短路求值,于是成功切掉了。
其中的核心其实就是用短路求值代替判断,用判断+函数实现递归来代替循环。
抽象一点的表示就是把
if (表达式) {
语句体
}
替换成了
(表达式) && (语句体);
还有把
for (初始化; 循环条件; 增量) {
语句体
}
替换成了
int f(形参) {
(循环条件) && (语句体, 增量, f(新的形参));
return 1; // 这句其实也可以不写
}
其中语句体用“,”连接,凡是在增量语句中改变的局部变量都要通过参数传递……而且凡是在语句体里面含有不是表达式的语句(如定义局部变量、无返回值函数等[其实只想到这两个……])的循环都不能这样写,如果需要调用无返回值的函数的话需要另外写一个有返回值的函数来调用它(或者直接改成有返回值的……)。
贴一下我所写的完整代码
#include<stdio.h>
int fibon[41];
/*计算斐波那契数列(实际上是递推而不是递归)*/
int calc(int pos) {
fibon[pos] = fibon[pos - 1] + fibon[pos - 2];
pos <= 40 && calc(pos + 1); // 短路求值
return 1;
}
/*输入一个数n并输出斐波那契数列的第n项,参数为剩余需要读入的数的个数*/
int scanf_and_print(int t) {
int n;
t > 0 && (scanf("%d", &n), printf("%d\n", fibon[n]), scanf_and_print(t - 1));
return 1;
}
int main() {
int t;
fibon[1] = 1;
fibon[2] = 1;
calc(3);
scanf("%d", &t);
scanf_and_print(t);
return 0;
}
后来发现原题原来是只输入一个数n然后输出斐波那契数列的第n项,题目的标准程序如下
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
class Num {
public:
Num() {
int tmp = b_;
b_ = a_ + b_;
a_ = tmp;
}
static int getAns() {return a_;}
private:
static int a_;
static int b_;
};
int Num::a_ = 0;
int Num::b_ = 1;
int main() {
int n;
cin >> n;
Num *p = new Num[n];
delete []p;
cout << Num::getAns() << endl;
return 0;
}
是用类的构造函数以及静态成员变量来实现的,想了一下,还真是一个实现循环的好方法,用对象数量来控制循环次数,修改一下也可以处理T组数据,如下。
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int now = 3;
class Num {
public:
Num() {
fibon[Num::now] = fibon[Num::now - 1] + fibon[Num::now - 2];
Num::now++;
}
static int now;
static int fibon[41];
};
class print{
public:
print() {
int n;
cin >> n;
cout << Num::fibon[n] << endl;
}
};
int Num::fibon[41];
int Num::now = 3;
int main() {
int t;
Num::fibon[1] = 1;
Num::fibon[2] = 1;
Num *p = new Num[38];
delete []p;
cin >> t;
print *p2 = new print[t];
delete []p2;
return 0;
}
其实以上只是小把戏,没看出来什么意义……
最后有一点感想,果然程序设计语言还是像老师所说的那样离不开判断和循环(据说函数是非必须的,不过这里用它来代替了循环)。

本著作係採用 創用 CC 姓名標示-非商業性 3.0 美國 授權條款授權.