编程轻松炫技:不费吹灰之力打印100个数字,面试考点应有尽有

2024-01-10 16:19:05 浏览数 (1)

给大家设定一个条件:不使用循环,请打印出1-100个数字

如果使用循环很简单了,那么你能想到多少种方法呢?

今天来给大家用一些C 的骚操作来写出这种代码,欢迎留言与转发~

这道题目其实非常简单,但却涵盖了很多面试考点,其中包括:

  • 模版特化、便特化,如何编写递归模版
  • CRTP
  • std::copy、std::iota、std::transform如何使用,各自算法实现
  • 类静态变量
  • 等等

1.递归

1-100可以拆为554,用三个函数去打印它,函数a cout一次,然后变量加1,函数b层层嵌套a重复5次,函数c层层嵌套b重复5次,最后在main函数中对c层层嵌套4次。

代码语言:javascript复制
#include <iostream>

int a(int n) {
  std::cout << n   << std::endl;
  return n;
}

int b(int n) { return a(a(a(a(a(n))))); }

int c(int n) { return b(b(b(b(b(n))))); }

int main() {
  c(c(c(c(1))));
  return 0;
}

2.模版重载

使用模版与特化来处理,当迭代100时只输出100,否则输出I,并且 1递归处理。

代码语言:javascript复制
#include <iostream>
template <int I>
struct JustPrint : public JustPrint<I   1> {
  JustPrint() : JustPrint<I   1>() { std::cout << I << " "; }
};

template <>
struct JustPrint<100> {
  JustPrint<100>() { std::cout << 1 << " "; }
};

int main() { JustPrint<1> j; }

3.CRTP

方式3基于方式2,将其改造为crtp编程风格,是不是有点看不懂了,嘿嘿。

下面struct可以被替换为class,这里我用类来描述。其实就是两个类,第一个类Print为父类,打印每次的I,并调用子类,子类PrintDerived即成Print,并将自己传递给父类,子类是一个重载类,控制递归终止。

代码语言:javascript复制
#include <iostream>

template <typename Derived, int I>
struct Print {
  Print() {
    std::cout << I << " ";
    Derived::next();
  }
};

template <int I>
struct PrintDerived : public Print<PrintDerived<I>, I> {
  static void next() { PrintDerived<I   1>(); }
};
template <>
struct PrintDerived<100> : public Print<PrintDerived<100>, 100> {
  static void next() {}
};

int main() {
  PrintDerived<1> j;
  return 0;
}

4.类静态变量

创建一个Test数组,元素为100个,静态变量每次累加。

代码语言:javascript复制
#include <iostream>
using namespace std;

class Test {
  static int i;

 public:
  Test() { cout <<   i << endl; }
};
int Test::i;
int main() {
  Test a[100];
  return 0;
}

5.使用算法库

使用std::for_each简单粗暴。

代码语言:javascript复制
int main() {
  std::vector<int> l(100);
  std::iota(l.begin(), l.end(), 1);
  std::for_each(l.begin(), l.end(), [](int& n) { std::cout << n << std::endl; });
  return 0;
}

6.C 20 ranges

使用C 20的std::views,在std::copy时打印。

代码语言:javascript复制
#include <iostream>
#include <iterator>
#include <ranges>
int main() {
  auto numbers = std::views::iota(1, 100   1);
  std::copy(numbers.begin(), numbers.end(), std::ostream_iterator<int>(std::cout, "n"));
}

这个方式继续改造,还有一种实现,使用std::transform。

代码语言:javascript复制
auto range = std::views::transform(std::ranges::iota_view{1, 101}, [](const auto& x) {
  std::cout << x << std::endl;
  return x;
});
std::vector<int> a(range.begin(), range.end());

0 人点赞