输出从1到1000的数

输出从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微信公众账号和微信小程序

(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)

——=== 访问 酷壳404页面 寻找遗失儿童。 ===——
好烂啊有点差凑合看看还不错很精彩 (19 人打了分,平均分: 3.89 )
Loading...

输出从1到1000的数》的相关评论

  1. 我觉得这样的文章可以让我们更好地去理解C语言中的一些东西,别出心裁,特有创意,在别的地方是看不到的!谢谢分享!

  2. 上文第一段代码有问题,我用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);程序竟然也不会崩溃,这就让我很是想不通了…

    1. 建议面试时看到这道题给下面这样的答案:

      printf(“从1到1000的数\n”);

      当然,除了娱乐以外,我们可以从答案中了解一下各种各样的C/C++的特性。C++的确是可以被滥用得很BT的。

  3. @陈皓
    第二段代码还有个小问题—如果n/(1000-n)不赋值给一个变量,好想程序是不会结束的….比如这样写int temp=n/(1000-n);才行,不知道这个是不编译器的问题….

  4. 不用问号表达式的话,可以通过&&短路实现:

    #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);
    }

  5. 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);
    }
    }

  6. 解题的基本思路:不能用循环就用递归,不能用条件判断就用哈希函数

  7. @yea
    最后一个其实跟第二个的解法的原理是一样的,无论是函数还是变量,都是存放在内存的一块空间上,有 一个内存地址。函数名本身就可以当做是一个指针,指向函数在内存上的地址,所以函数名相加减,就是内存地址相加减(我猜,没有深究)。当n=1000时,程序就执行存放地址为(main+exit-main)的函数,也就是exit.

  8. // 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;
    }

  9. @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;
    }

  10. 最后一个报错:
    error C2296: ‘-‘ : illegal, left operand has type ‘void (__cdecl *)(int)’

  11. 赞的。不过严格点说,segmentation fault之类的出错信息也是输出,所以有些异常退出的解不符合题目本身要求。

  12. @tuoxie
    最后一个很牛,利用了函数指针

    j<1000的时候
    main – (exit – main)*0 还是调用 main 函数,打印
    j=1000的时候
    main – (exit – main)*1 就调用 exit 函数退出了

  13. 宏在C语言中的强大作用总是那么令人叹止,又那么让人着迷。可惜面向对象的高级语言中就好像缺少这一强大的辅助特性

  14. 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;
    }

  15. 最后一个改成这样更好:
    void main(int j) {
    printf(“%d\n”, j);
    (main + (exit – main)*(j/1000))((j+1)%1001);
    }

    哈哈,而且这样谢有个限制:调用时不能传入任何参数,否则。就不是从1到1000了。

  16. 也可以这样:
    #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;
    }

回复 thankgod 取消回复

您的电子邮箱地址不会被公开。