定义' for' C ++中的循环宏

时间:2014-06-24 16:40:57

标签: c++ loops for-loop c-preprocessor

也许这不是很好的编程习惯,但可以定义一个for循环宏吗?

例如,

#define loop(n) for(int ii = 0; ii < n; ++ ii)

效果很好,但不能让您更改变量名ii

可以使用:

loop(5)
{
    cout << "hi" << " " << "the value of ii is:" << " " << ii << endl;
}

但是没有名称/符号ii的选择。

是否可以做这样的事情?

loop(symbol_name, n)

程序员将符号名称插入&#34; symbol_name&#34;。

使用示例:

loop(x, 10)
{
    cout << x << endl;
}

9 个答案:

答案 0 :(得分:28)

#define loop(x,n) for(int x = 0; x < n; ++x)

答案 1 :(得分:13)

在今天的C ++中,我们不会为此使用宏,但我们会使用模板和仿函数(包括lambda):

template<typename FUNCTION>
inline void loop(int n, FUNCTION f) {
  for (int i = 0; i < n; ++i) {
    f(i);
  }
}
// ...
loop(5, [](int jj) { std::cout << "This is iteration #" << jj << std::endl; } );

loop函数在内部使用变量i,但lambda没有看到。它是loop的内部。相反,lambda定义了一个参数jj并使用该名称。

除了lambda之外,您还可以传递任何函数,只要它接受单个整数参数即可。您甚至可以传递std::to_string<int> - 而不是loop会对结果字符串做一些有用的事情,但语法允许它。

答案 2 :(得分:6)

#define loop(x, n) for(int x = 0; x < n; ++ x)

Something like this

#include <iostream>
using namespace std;

#define loop(x, n) for(int x = 0; x < n; ++ x)

int main() {

    loop(i, 10)
    {
        cout << i << endl;
    }

    return 0;
}

答案 3 :(得分:2)

您可以将变量名称定义为宏的第一个参数:

#define loop(variable, n) for(int variable = 0; variable < n; ++variable )

请注意,大多数有经验的程序员都遵循一条规则 - 为宏使用大写标识符。在你的情况下,假设你有一个函数和宏:

#define loop(variable, n) for(int variable = 0; variable < n; ++variable )

void loop();

现在尝试在代码中调用该函数,并观察您获得的丑陋错误消息。其中一些根本不容易理解。更糟糕的是在类中的命名空间或方法中使用该循环函数并且根本没有帮助。

所以至少要这样:

#define LOOP(variable, n) for(int variable = 0; variable < n; ++variable )

但最好不要使用它。

答案 4 :(得分:2)

使用:

#include <vector>
#include <cstdio>

using std::printf;

#define FOR(TYPE, IDENT, BEGIN, END) for(TYPE IDENT = BEGIN, IDENT##_end = static_cast<decltype(IDENT)>(END); IDENT < IDENT##_end; ++IDENT)
#define FOR_STEP(TYPE, IDENT, BEGIN, END, STEP) for(TYPE IDENT = (TYPE)(BEGIN), IDENT##_end = static_cast<decltype(IDENT)>(END); IDENT < IDENT##_end; IDENT += STEP )
#define FOR_ITER(IDENT, BEGIN, END) for(auto IDENT = BEGIN, IDENT_end = END; IDENT != IDENT_end; ++IDENT)

int main() {
  FOR(int, i, 0, 10) {
    printf("FOR i: %d\n", i);
    printf("we can even access i_end: %d\n", i_end);
  }

  FOR(auto, i, 0, 10) {
    printf("FOR auto i: %d\n", i);
  }

  std::vector<int> vec = {4, 5, 7, 2, 3, 1, 4, 9, 8, 6};

  printf("FOR with iterator: {");
  FOR(auto, it, vec.begin(), vec.end()) {
    printf("%d, ", *it);
  }
  printf("}\n");

  printf("FOR with non constant end:\n");
  FOR(long, i, 0, vec.size()) {
    printf("vec[%ld] = %d\n", i, vec[i]);
  }
  printf("\n");


  // You can set a step size
  printf("FOR_STEP(double, d, 0, 20, 2.1): ");
  FOR_STEP(double, d, 0, 20, 2.1) {
    printf(" %f ", d);
  }
  printf("\n");

  // It works with iterators that don't have "<" but only "!="
  // defined, but you probably want to use a range-based 'for' anyway.
  printf("FOR_ITER(auto, it, vec.begin(), vec.end()): ");
  FOR(auto, it, vec.begin(), vec.end()) {
    printf("%d, ", *it);
  }
  printf("\n");
}

这是我能为C ++ 11目标提出的最佳选择。它确保END参数仅评估一次,并要求beginend具有相同的类型,这几乎总是如此。

由于您不应在与==!=运算符相等的情况下测试双精度数,因此默认FOR宏使用<运算符进行比较,这限制了迭代器的宏,因为它们现在也需要定义<运算符。我无法想出一个适用于双重和任意迭代器的解决方案;您可以选择一个更适合您需求的宏。

但是你不应该为你的代码引入所有的宏,因为只有一个宏定义适合大多数需求,代码将更具可读性。

答案 5 :(得分:1)

#define loop(VARIABLE, n) for(int VARIABLE = 0; VARIABLE < n; ++ VARIABLE)

你可以试试这个。

答案 6 :(得分:0)

在竞赛编程中,必须尽可能快地编码。加速编码的一种方法是使用宏。竞赛程序员使用下面的宏来缩写&#34; for循环&#34; :

#define For(i,j,n) for(int i=(j);i<((int)n);++i)

例如,下面的代码将打印1到10。

#include <stdio.h>
#define For(i,j,n) for(int i=(j);i<((int)n);++i)

int main(void)
{
   For(i, 1, 11)
   {
       printf("%d\t", i);
   }
}

但宏是危险的,挑剔的,而且不那么安全。我真的建议你不要在你的项目中使用它们。要显示此问题,请考虑以下代码。

#include <stdio.h>
#define For(i,j,n) for(int i=(j);i<((int)n);++i)

int main(void)
{
   int end = 10;
   For(i, 1, end++)
   {
       printf("%d\t", i);
   }
}

如果您运行代码,您将看到程序永远不会停止工作,尽管您可能期望输出应该相同1到10.

答案 7 :(得分:0)

像这样尝试-#为((i)= 0;(i)<(int)(n);(i)++)定义循环(i,n)

答案 8 :(得分:0)

对于在一个宏中同时替换for(auto i = 0; i < n; ++i)for(auto i = n - 1; i >= 0; --i)的双向for循环。

您可以使用此

#define F(i, st, n) for (auto i = st-(st > n); (i < n)^(st > n); i += 1-2*(st > n))

说明: 如果开始<= n,则i = st; i < n; i += 1 否则i = st - 1; i >= n; i += -1

请注意,异或运算符(i < n)^(st > n)对函数进行了适当的补充。

或者,您也可以使用三元运算符(st > n)?(i >= n):(i < n)代替xor运算符。像这样

#define F(i, st, n) for (auto i = st-(st > n); (st > n)?(i >= n):(i < n); i += 1-2*(st > n))

由于时间开销很小,因此应该同样有效。

请记住, F(i, 0, m)F(i, m, 0)都包含0而排除了m