伪代码也能跑——for
EricWan · · Tech. & Eng.
本人很闲,这个想法是我自己想出的,如有雷同,那我就很唐。
怎么错别字那么多(
不保证包对,但是对于遍历整数应该是包对的。如果发现错误,欢迎留言,若没有更正,可以私信作者。
使用方法
for (<type> <name> : <begin> to <end>)
,定义一个 <type> <name>
变量并遍历 [<begin>, <end>]
。
for (<type> <name> : <begin> until <end>)
,定义一个 <type> <name>
变量并遍历 [<begin>, <end>)
。
down_to
和 down_until
同理,只不过是 ++
换为了 --
。
支持 to, up_to, down_to
其中 up_to
和 to
相同。支持 until, up_until, down_until
其中 up_until
和 until
相同。
若没有明确规定不使用 safe
版的 to
和 down_to
实现,默认使用 safe
版,safe 版会多占用若干空间并多一倍的比较常数。
同时支持在上面的那六个宏标识后接 _safe
或 _fast
明确指定使用那一版,例如 to_fast
明确规定使用 fast
版实现
注意事项
如果 <end>
是一个带 operator,
的表达式,需要用小括号括一下 <end>
。
为了符合有关 for:
有关 operator!=(itreator)
的要求,fast
版实现中 to
中的 <end>
需要对 operator++()
有定义,同理 down_to
中的 <end>
需要对 operator--()
有定义。
until
系列仅有 fast
版实现,因为 <end>
不涉及 ++--
操作。
实现方法
将 to
和 until
等替换为 ,标识符,
,标识符和左参先结合然后和右参结合,生成一个可遍历的 range
,使用 c++14
的 range-for
对其遍历。
代码
想用的话可以吧这个东西粘入某一个文件中,如 pseudo_code_extend.h
,使用 #include "pseudo_code_extend.h"
,或者直接粘在代码开始的位置。
可以使用 #define __UNUSE__PSEUDO_CODE_EXTENDS__
明确禁止使用这些可能和变量冲突的宏表示。
可以使用 #define __UNUSE__SAFE_FOR_LOOP__
或 #define __USING__SAFE_FOR_LOOP__ 0
明确规定 to, up_to, down_to
使用 fast
版实现。
#include <type_traits>
#ifdef __UNUSE__SAFE_FOR_LOOP__
#define __USING__SAFE_FOR_LOOP__ 0
#endif
#ifndef __USING__SAFE_FOR_LOOP__
#define __USING__SAFE_FOR_LOOP__ 1
#endif
#ifndef __UNUSE__PSEUDO_CODE_EXTENDS__
#define __USING__PSEUDO_CODE_EXTEND__OF__FOR_LOOP__
#endif
namespace __pseudo_code_extend {
namespace __for_loop {
namespace safe { // safe for only to mod
struct fft_translator {};
struct ffdt_translator {};
template<typename T>
struct fft_range {
struct iterator {
T x;
bool e;
const fft_range *base;
const T &operator*() const { return x; }
bool operator!=(const iterator &b) const { return x != b.x || e != b.e; }
iterator &operator++() {
if (x == base->e) e = true;
else ++x;
return *this;
}
};
T b, e;
iterator begin() const { return {b, false, this}; }
iterator end() const { return {e, true, this}; }
};
template<typename T2, typename T>
fft_range<T2> operator,(fft_range<T2> ans, T &&e) {
ans.e = e;
return ans;
}
template<typename T>
fft_range<std::decay_t<T> > operator,(T &&b, fft_translator) {
fft_range<std::decay_t<T> > ans;
ans.b = b;
return ans;
}
template<typename T>
struct ffdt_range {
struct iterator {
T x;
bool e;
const ffdt_range *base;
const T &operator*() const { return x; }
bool operator!=(const iterator &b) const { return x != b.x || e != b.e; }
iterator &operator++() {
if (x == base->e) e = true;
else --x;
return *this;
}
};
T b, e;
iterator begin() const { return {b, false, this}; }
iterator end() const { return {e, true, this}; }
};
template<typename T2, typename T>
ffdt_range<std::decay_t<T2> > operator,(ffdt_range<T2> ans, T &&e) {
ans.e = e;
return ans;
}
template<typename T>
ffdt_range<std::decay_t<T> > operator,(T &&b, ffdt_translator) {
ffdt_range<std::decay_t<T> > ans;
ans.b = b;
return ans;
}
}
namespace fast {
struct fft_translator {};
struct ffu_translator {};
struct ffdt_translator {};
struct ffdu_translator {};
template<typename T>
struct fft_range {
struct iterator {
T x;
const T &operator*() const { return x; }
bool operator!=(const iterator &b) const { return x != b.x; }
iterator &operator++() { ++x; return *this; }
};
T b, e;
iterator begin() const { return {b}; }
iterator end() const { return {e}; }
};
template<typename T>
struct ffu_range_begin { T b; };
template<typename T2, typename T>
fft_range<T2> operator,(fft_range<T2> ans, T &&e) {
++(ans.e = e);
return ans;
}
template<typename T>
fft_range<std::decay_t<T> > operator,(T &&b, fft_translator) {
fft_range<std::decay_t<T> > ans;
ans.b = b;
return ans;
}
template<typename T2, typename T>
fft_range<T2> operator,(ffu_range_begin<T2> ans_u, T &&e) {
fft_range<T2> ans;
ans.b = ans_u.b;
ans.e = e;
return ans;
}
template<typename T>
ffu_range_begin<std::decay_t<T> > operator,(T &&b, ffu_translator) {
return {b};
}
template<typename T>
struct ffdt_range {
struct iterator {
T x;
const T &operator*() const { return x; }
bool operator!=(const iterator &b) const { return x != b.x; }
iterator &operator++() { --x; return *this; }
};
T b, e;
iterator begin() const { return {b}; }
iterator end() const { return {e}; }
};
template<typename T>
struct ffdu_range_begin { T b; };
template<typename T2, typename T>
ffdt_range<T2> operator,(ffdt_range<T2> ans, T &&e) {
--(ans.e = e);
return ans;
}
template<typename T>
ffdt_range<std::decay_t<T> > operator,(T &&b, ffdt_translator) {
ffdt_range<std::decay_t<T> > ans;
ans.b = b;
return ans;
}
template<typename T2, typename T>
ffdt_range<T2> operator,(ffdu_range_begin<T2> ans_u, T e) {
ffdt_range<T2> ans;
ans.b = ans_u.b;
ans.e = e;
return ans;
}
template<typename T>
ffdu_range_begin<std::decay_t<T> > operator,(T &&b, ffdu_translator) {
return {b};
}
}
}
}
#ifdef __USING__PSEUDO_CODE_EXTEND__OF__FOR_LOOP__
#if __USING__SAFE_FOR_LOOP__
#define to , __pseudo_code_extend::__for_loop::safe::fft_translator() ,
#define up_to to
#define down_to , __pseudo_code_extend::__for_loop::safe::ffdt_translator() ,
#else
#define to , __pseudo_code_extend::__for_loop::fast::fft_translator() ,
#define up_to to
#define down_to , __pseudo_code_extend::__for_loop::fast::ffdt_translator() ,
#endif
#define until , __pseudo_code_extend::__for_loop::fast::ffu_translator() ,
#define up_until until
#define down_until , __pseudo_code_extend::__for_loop::fast::ffdu_translator() ,
#define to_safe , __pseudo_code_extend::__for_loop::safe::fft_translator() ,
#define until_safe , __pseudo_code_extend::__for_loop::fast::ffu_translator() ,
#define up_to_safe to_safe
#define up_until_safe until_safe
#define down_to_safe , __pseudo_code_extend::__for_loop::safe::ffdt_translator() ,
#define down_until_safe , __pseudo_code_extend::__for_loop::fast::ffdu_translator() ,
#define to_fast , __pseudo_code_extend::__for_loop::fast::fft_translator() ,
#define until_fast , __pseudo_code_extend::__for_loop::fast::ffu_translator() ,
#define up_to_fast to_fast
#define up_until_fast until_fast
#define down_to_fast , __pseudo_code_extend::__for_loop::fast::ffdt_translator() ,
#define down_until_fast , __pseudo_code_extend::__for_loop::fast::ffdu_translator() ,
#endif
使用示例
#include "pseudo_code_extend.h"
#include <bits/stdc++.h>
using namespace std;
signed main() {
set<int> st{1, 2, 3, 4, 5, 6, 7, 8, 9};
for (auto i : st.begin() to_fast st.end()) {
// 错误,++std::set::end() 未定义
// 所以 ++std::set::end() 可能为一个别的位置的迭代器
// 我的电脑上测试 --(++st.end()) == st.find(7)
cout << distance(st.begin(), i) << " " << *i << endl;
}
for (auto i : st.begin() to_safe st.end()) { // 正确,to 也可
cout << distance(st.begin(), i) << " " << *i << endl;
}
for (auto i : --st.end() down_to st.begin()) {
cout << *i << " ";
}
cout << endl;
for (int i : 2 to 5) {
cout << i << " ";
}
cout << endl;
for (int i : 2 until 5) {
cout << i << " ";
}
cout << endl;
for (int i : 5 down_to 2) {
cout << i << " ";
}
cout << endl;
for (int i : 5 down_until 2) {
cout << i << " ";
}
cout << endl;
for (int i : 5 down_until_safe 2) {
cout << i << " ";
}
cout << endl;
for (int i : 5 down_until_fast 2) {
cout << i << " ";
}
cout << endl;
vector<int> vec{1, 10, -10, 42};
for (vector<int>::iterator i : vec.begin() + 1 to vec.end() - 1) {
cout << *i << " ";
}
cout << endl;
for (auto i : vec.begin() to vec.end() - 1) {
cout << *i << " ";
}
cout << endl;
for (vector<int>::iterator i : vec.end() - 1 down_to_fast vec.begin()) {
// 虽然 STL 的 --begin() 也是 UB,但是在 vector 里没有出错,很幸运
cout << *i << " ";
}
cout << endl;
for (vector<int>::iterator i : vec.end() - 1 down_to vec.begin()) {
cout << *i << " ";
}
cout << endl;
return 0;
}
期望输出(关于前几行,可能不同,因为第一个使用实例是用于论证 fast
版的 to
可能出错):
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 9
9 8 7 6 5 4 3 2 1
2 3 4 5
2 3 4
5 4 3 2
5 4 3
5 4 3
5 4 3
10 -10 42
1 10 -10 42
42 -10 10 1
42 -10 10 1
补充说明
如果 #define from :
可能更优雅。
fft
为 For-From-To
的缩写,其他同理。
更加广义的定义(例如 typeid(<begin>)
不一定等于 typeid(<end>)
)我懒得写了。。。