输出从1到1000的数
有这样一个面试题——请把从1到1000的数打印出来,但你不能使用任何的循环语句或是条件语句。更不能写1000个printf或是cout。用C/C++语言。
我相信,大多数人一开始你可能想到的是递归算法:
void f(int n){ printf("%d\n",n); (1000-n) ? f(n+1) : exit(0) ; } int main(){ f(1); }
当然,题目中说了不能使用条件语句,所以,上面那种解法的不符合题意的,因为还是变向地使用了条件表达式。不过,我们可以用别的方法来让这个递归终止,比如:
除以零,当程序crash,呵呵。
void f(int n){ printf("%d\n",n); n/(1000-n); f(n+1); }
还有这样退出递归的:
void yesprint(int i); void noprint(int i); typedef void(*fnPtr)(int); fnPtr dispatch[] = { yesprint, noprint }; void yesprint(int i) { printf("%d\n", i); dispatch[i / 1000](i + 1); } void noprint(int i) { /* do nothing. */ } int main() { yesprint(1); }
还有下面这些各种各样的解法:
#include<stdio.h> /* prints number i */ void print1(int i) { printf("%d\n",i); } /* prints 10 numbers starting from i */ void print10(int i) { print1(i); print1(i+1); print1(i+2); print1(i+3); print1(i+4); print1(i+5); print1(i+6); print1(i+7); print1(i+8); print1(i+9); } /* prints 100 numbers starting from i */ void print100(int i) { print10(i); print10(i+10); print10(i+20); print10(i+30); print10(i+40); print10(i+50); print10(i+60); print10(i+70); print10(i+80); print10(i+90); } /* prints 1000 numbers starting from i */ void print1000(int i) { print100(i); print100(i+100); print100(i+200); print100(i+300); print100(i+400); print100(i+500); print100(i+600); print100(i+700); print100(i+800); print100(i+900); } int main() { print1000(1); return 0; }
不过,print用得多了一些。我们可以用宏嘛。
#include<stdio.h> #define Out(i) printf("%d\n", i++); #define REP(N) N N N N N N N N N N #define Out1000(i) REP(REP(REP(Out(i)))); void main() { int i = 1; Out1000(i); }
不过,我们应该使用C++的一些特性,比如:
使用构造函数
class Printer { public: Printer() { static unsigned i=1; cout << i++ << endl;; } }; int main() { Printer p[1000]; }
或是更为NB的Template:
template<int N> struct NumberGeneration{ static void out(std::ostream& os) { NumberGeneration<N-1>::out(os); os << N << std::endl; } }; template<> struct NumberGeneration<1>{ static void out(std::ostream& os) { os << 1 << std::endl; } }; int main(){ NumberGeneration<1000>::out(std::cout); }
最后来个BT一点的:
void main(int j) { printf("%d\n", j); (main + (exit - main)*(j/1000))(j+1); }
本文来自: http://stackoverflow.com/q/4568645/89806
(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)
《输出从1到1000的数》的相关评论
感觉这种题就是吃饱了撑的,奏是不好好走道。
完全同意。
不能同意你更多。
吃饱撑的!
属于装{B}一族
不过能够增加生活的乐趣。
《编程珠玑II》上似乎有这样的一个问题…
我觉得这样的文章可以让我们更好地去理解C语言中的一些东西,别出心裁,特有创意,在别的地方是看不到的!谢谢分享!
上文第一段代码有问题,我用gcc 4.4编译,报错“error: expected expression before ‘return’”,意思应该是说1000-n ? f(n+1):return;一行中不能使用函数调用f(n+1),对于c我不太熟悉,请问这是为什么?
另外第二段代码,n/1000-n;应该为n/(1000-n);吧?否则怎么会出现除以0的情况呢?但即使是写成n/(1000-n);程序竟然也不会崩溃,这就让我很是想不通了…
这样看来,作者在写文字之前,代码虽然简单,但还是需要编译运行一下呢…
@youngsterxyf
谢谢你的查错。我将改正。
去面试的看到这题,建议直接 走!!!!!
建议面试时看到这道题给下面这样的答案:
printf(“从1到1000的数\n”);
当然,除了娱乐以外,我们可以从答案中了解一下各种各样的C/C++的特性。C++的确是可以被滥用得很BT的。
最后一个太变态
在 wangcong 的 presentation 里看到过这个题目。第一反应是 system(“seq 1 1000”);
等高人给个用 printf 折腾栈的解法
我X 太牛了
或者这么写:
#include
main(_){printf(“%d\n”,_),1000>_&&main(_+1);}
@陈皓
第二段代码还有个小问题—如果n/(1000-n)不赋值给一个变量,好想程序是不会结束的….比如这样写int temp=n/(1000-n);才行,不知道这个是不编译器的问题….
不用问号表达式的话,可以通过&&短路实现:
#include
int printnum(int i, int n)
{
printf(“%d\n”, i);
return (i – n) && printnum(i + 1, n);
}
int main()
{
int n;
printf(“Input n: “);
scanf(” %d”, &n);
printnum(1, n);
}
int fat(int n)
{
printf(“%d\n”,n);
return n%1000 && fat(n+1);
}
public class Test1000 {
static final int test(int i) {
System.out.println(i);
int over = i / (i ^ 1000);
return test(i + 1);
}
public static void main(String[] args) {
test(1);
}
}
int i=1001;
int main()
{
i–>1&&printf(“%d\n”,i)&&main();
return 0;
}
第4行少个“-”
高手帮忙解释一下最后那段代码吧!
@yea
我觉得最后一行是个循环,直到n=1000时,运行exit…退出程序…但这个程序是不能直接运行的吧?
解题的基本思路:不能用循环就用递归,不能用条件判断就用哈希函数
@yea
最后一个其实跟第二个的解法的原理是一样的,无论是函数还是变量,都是存放在内存的一块空间上,有 一个内存地址。函数名本身就可以当做是一个指针,指向函数在内存上的地址,所以函数名相加减,就是内存地址相加减(我猜,没有深究)。当n=1000时,程序就执行存放地址为(main+exit-main)的函数,也就是exit.
// STL实现也蛮容易的
#include
#include
#include
#include
#include
using namespace std;
int main() {
vector v(1000, 1);
partial_sum(v.begin(), v.end(), v.begin());
copy(v.begin(), v.end(), ostream_iterator(cout, “\n”));
return 0;
}
@Qiao
#include <iostream>
#include <algorithm>
#include <vector>
#include <iterator>
#include <numeric>
using namespace std;
int main() {
vector<int> v(1000, 1);
partial_sum(v.begin(), v.end(), v.begin());
copy(v.begin(), v.end(), ostream_iterator<int>(cout, “\n”));
return 0;
}
条条大道通罗马啊
太惊悚太可怕了
@greatghoul
换个心态还是能接受哈,站在编程的角度看而不是做软件的角度。
没有人想过用 goto吗?
只有这样搞才能把C++吃透了
最后一个报错:
error C2296: ‘-‘ : illegal, left operand has type ‘void (__cdecl *)(int)’
木有看懂。。。
赞的。不过严格点说,segmentation fault之类的出错信息也是输出,所以有些异常退出的解不符合题目本身要求。
多来点
@xanduy
用了&&操作符来短路,似乎属于条件判断的范畴,违反了规则。
@tuoxie
最后一个很牛,利用了函数指针
j<1000的时候
main – (exit – main)*0 还是调用 main 函数,打印
j=1000的时候
main – (exit – main)*1 就调用 exit 函数退出了
@Qiao
用迭代器,相当于让库函数去做循环了,够聪明够狠的。
宏在C语言中的强大作用总是那么令人叹止,又那么让人着迷。可惜面向对象的高级语言中就好像缺少这一强大的辅助特性
int print_num(int num)
{
int j = 0;
printf(“%d\n”, num);
j = (num – 1000) && (print_num(num + 1));
return (num + 1);
}
int main()
{
print_num(0);
return 0;
}
最后一个改成这样更好:
void main(int j) {
printf(“%d\n”, j);
(main + (exit – main)*(j/1000))((j+1)%1001);
}
哈哈,而且这样谢有个限制:调用时不能传入任何参数,否则。就不是从1到1000了。
淘宝2011校招的笔试题就有这道,很类似
也可以这样:
#include
typedef void (*FN)(int i);
void doPrint(int i);
void doStop(int i);
FN ActionTable[] = {doPrint,doStop};
void doPrint(int i){
printf(“%d\n”,i);
}
void doStop(int i){
doPrint(i);
exit(0);
}
void safePrint(const int value,const int range){
int index;
index = value/range;
(*ActionTable[index])(value);
safePrint(value+1,range);
}
int main(int argc,char* argv[]){
safePrint(1,1000);
return 0;
}
一个小错误:倒数第三个程序,Pointer()构造函数定义中多了个分号。
挺有意思的。