在C++中定义'for'循环宏
Define a 'for' loop macro in C++
也许这不是好的编程实践,但是是否可以定义一个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)
其中程序员将符号名称插入" symbol_name
"。
用法示例:
loop(x, 10)
{
cout << x << endl;
}
#define loop(x,n) for(int x = 0; x < n; ++x)
在今天的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
会对生成的字符串执行一些有用的操作,但语法允许这样做。
[编辑]通过数学家;您可以使用以下方法支持不可复制的函子
template<typename FUNCTION>
inline void loop(int n, FUNCTION&& f) {
for (int i = 0; i < n; ++i) {
std::forward<FUNCTION>(f)(i);
}
}
[编辑]2020 变体,在传递不适当的函数时应该提供更好的错误消息。
inline void loop(int n, std::invocable<int> auto&& f) {
for (int i = 0; i < n; ++i) {
std::invoke(f,i);
}
}
#define loop(x, n) for(int x = 0; x < n; ++ x)
像这样的东西?
#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;
}
可以将变量名称定义为宏的第一个参数:
#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 )
但最好不要使用它。
#define loop(VARIABLE, n) for(int VARIABLE = 0; VARIABLE < n; ++ VARIABLE)
你可以试试这个。
使用:
#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: %dn", i);
printf("we can even access i_end: %dn", i_end);
}
FOR(auto, i, 0, 10) {
printf("FOR auto i: %dn", 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] = %dn", 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
参数只计算一次,并要求begin
和end
具有相同的类型,这几乎总是如此。
由于不应使用 ==
或 !=
运算符测试双精度值,因此宏的默认FOR
使用 <
运算符进行比较,这限制了迭代器对宏的使用,因为它们现在也需要定义<
运算符。我无法想出一种适用于双迭代器和任意迭代器的解决方案;您可以选择一个更适合您需求的宏。
但是,您不应该在代码中引入所有宏,因为只有一个适合大多数需求的宏定义,代码将更具可读性。
在竞赛编程中,有必要尽可能快地编码。加快编码速度的一种方法是使用宏。竞赛程序员使用下面的宏来缩写"for loops":
#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("%dt", 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("%dt", i);
}
}
如果运行代码,您将看到程序永远不会停止工作,尽管您可能期望输出应为 1 到 10。
用于双向 for 循环,它在一个宏中替换了for(auto i = 0; i < n; ++i)
和for(auto i = n - 1; i >= 0; --i)
。
你可以使用它,
#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
请注意,xor 运算符(i < n)^(st > n)
适当地补充了函数。
或者,您也可以使用三元运算符(st > n)?(i >= n):(i < n)
而不是异或运算符。喜欢这个
#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
。
尝试这样做- #define 循环(i,n( for((i( = 0;(一( <(国际((n(;(一(++(
- 如何在C++中从两个单独的for循环中添加两个数组
- 为什么我的for循环不能正确获取argv
- 在基于范围的for循环中使用结构化绑定声明
- 通过for循环使用用户输入填充列表
- 使用for循环检查数组中的重复项
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 为什么 const std::p air<K,V>& 在 std::map 上基于范围的 for 循环不起作用?
- 正在使用for循环创建QScatterSerie
- Python中的for循环与C++有何不同
- 在更改for循环的第三部分后,未使用for循环结果
- 在 for 循环中查找问题时遇到困难
- 嵌套for循环C++的问题(初学者)
- 如何用for循环在c++中生成单词三角形
- 如何在for循环中包含两个索引值的测试条件
- 带有多个独立参数的C++For循环
- C++ Python 循环"for i, num in enumerate(list):"版本
- C 多循环 for () 基础知识
- 没有条件值的 FOR 循环"for (int i = 1; ; i++)"无法正常工作
- 为用户提供循环for循环的选项
- 打破循环for循环