任务:打印从1到1000的数字,不使用任何循环或条件语句。不要只写printf()或cout语句1000次。

用C或c++怎么做呢?


当前回答

有趣的函数指针(不需要新流行的TMP):

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>


#define MSB(typ) ((sizeof(typ) * CHAR_BIT) - 1)

void done(int x, int y);
void display(int x, int y);

void (*funcs[])(int,int)  = {
    done,
    display
};

void done(int x, int y)
{
    exit(0);
}

void display(int x, int limit)
{
    printf( "%d\n", x);
    funcs[(((unsigned int)(x-limit)) >> MSB(int)) & 1](x+1, limit);
}


int main()
{
    display(1, 1000);
    return 0;
}

附注:我将禁止条件符扩展到逻辑运算符和关系运算符。如果允许逻辑否定,递归调用可以简化为:

funcs[!!(limit-1)](x+1, limit-1);

其他回答

使用递归,可以使用函数指针算术替换条件:

#include <stdio.h>
#include <stdlib.h> // for: void exit(int CODE)

// function pointer
typedef void (*fptr)(int);

void next(int n)
{
        printf("%d\n", n);

        // pointer to next function to call
        fptr fp = (fptr)(((n != 0) * (unsigned int) next) +
                         ((n == 0) * (unsigned int) exit));

        // decrement and call either ``next'' or ``exit''
        fp(n-1);
}

int main()
{
        next(1000);
}

注意,这里没有条件句;n !=0和n==0是无分支操作。(不过,我们在尾部调用中执行了一个分支)。

下面是使用信号的POSIX变体:

#include <stdio.h>
#include <signal.h>

void counter(int done)
{
        static int i;

        done = ++i / 1000;

        printf("%d\n", i);

        signal(SIGINT, (void (*)(int))(done * (int)SIG_DFL + (1-done) * (int)&counter));
        raise(SIGINT);
}

int main()
{
        signal(SIGINT, &counter);
        raise(SIGINT);

        return 0;
}

有趣的部分是counter()对signal()的调用。在这里,将安装一个新的信号处理程序:如果"done"为真,则SIG_DFL,否则计数器。

为了使这个解决方案更加可笑,我使用了信号处理程序所需的int形参来保存临时计算的结果。作为一个副作用,恼人的“未使用变量”警告在使用gcc -W -Wall编译时消失。

经过一些修改,我想出了这个:

template<int n>
class Printer
{
public:
    Printer()
    {        
        std::cout << (n + 1) << std::endl;
        mNextPrinter.reset(new NextPrinter);
    }

private:
    typedef Printer<n + 1> NextPrinter;
    std::auto_ptr<NextPrinter> mNextPrinter;
};

template<>
class Printer<1000>
{
};

int main()
{
    Printer<0> p;
    return 0;
}

后来@ybungalobill的作品启发我想出了这个更简单的版本:

struct NumberPrinter
{
    NumberPrinter()
    {
        static int fNumber = 1;
        std::cout << fNumber++ << std::endl;
    }
};


int main()
{
    NumberPrinter n[1000];
    return 0;
}

我错过了所有的乐趣,所有好的c++答案都已经贴出来了!

这是我能想到的最奇怪的事情,我不认为它是合法的C99:p

#include <stdio.h>

int i = 1;
int main(int argc, char *argv[printf("%d\n", i++)])
{
  return (i <= 1000) && main(argc, argv);
}

另一个,有点欺骗:

#include <stdio.h>
#include <boost/preprocessor.hpp>

#define ECHO_COUNT(z, n, unused) n+1
#define FORMAT_STRING(z, n, unused) "%d\n"

int main()
{
    printf(BOOST_PP_REPEAT(1000, FORMAT_STRING, ~), BOOST_PP_ENUM(LOOP_CNT, ECHO_COUNT, ~));
}

最后一个想法,同样的欺骗:

#include <boost/preprocessor.hpp>
#include <iostream>

int main()
{
#define ECHO_COUNT(z, n, unused) BOOST_PP_STRINGIZE(BOOST_PP_INC(n))"\n"
    std::cout << BOOST_PP_REPEAT(1000, ECHO_COUNT, ~) << std::endl;
}

不懂足够的C(++)来写代码,但你可以使用递归而不是循环。为了避免这种情况,可以使用在第1000次访问后抛出异常的数据结构。例如,某种带有范围检查的列表,在每次递归时增加/减少索引。

从评论中判断,c++中似乎没有任何范围检查列表?

相反,你可以用1/n作为递归函数的参数,每次调用都减少1。从1000开始。DivisionByZero异常将停止递归