以前用过octave, 和matlab类似的软件, 指定范围非常方便 i = 1:10:100; 就可以得到
10 20 30 ... 100
这一系列的数据, 但是在c里面, 必须手动写循环, 太不符合懒人的习惯了, 今天写了一个宏, 终于实现了, 貌似编译器没有优化, 还是在运行时获取整数的数值,不是在编译阶段, 但是无所谓了,一般这种偷懒都是在测试的时候使用, 正式代码不会用的。
代码如下:
#include <stdio.h> #include <stdlib.h> #define FOR(i, ...) do{ long i, __s__##i, __e__##i,__delta__##i; char *__pt__##i = #__VA_ARGS__; while(*__pt__##i) { if((*__pt__##i < ‘0‘ || *__pt__##i > ‘9‘) && *__pt__##i != ‘ ‘ && *__pt__##i != ‘,‘ && *__pt__##i != ‘:‘) { if(*__pt__##i != ‘-‘ || *(__pt__##i+1) < ‘0‘ || *(__pt__##i+1) > ‘9‘) { fprintf(stderr, "error of F(%s,%s)\n", #i, #__VA_ARGS__); exit(1); } } __pt__##i ++; } __pt__##i = #__VA_ARGS__; char *__end_ptr__##i; do{ __s__##i = strtol(__pt__##i, &__end_ptr__##i, 10); while(*__end_ptr__##i == ‘ ‘) __end_ptr__##i++; if(*__end_ptr__##i == ‘:‘) { __delta__##i = strtol(__end_ptr__##i+1, &__end_ptr__##i, 10); while(*__end_ptr__##i == ‘ ‘) __end_ptr__##i++; if(*__end_ptr__##i == ‘:‘) __e__##i = strtol(__end_ptr__##i+1, &__end_ptr__##i, 10); else { __e__##i = __delta__##i; __delta__##i = 1; } } else { __e__##i = __s__##i; __delta__##i = 1; } for(i = __s__##i; __s__##i <= __e__##i ? i <= __e__##i: i >= __e__##i; i += __delta__##i) {(void)0; #define DO(...) __VA_ARGS__; #define DONE(i) } __pt__##i = __end_ptr__##i; while(*__pt__##i == ‘ ‘ || *__pt__##i == ‘,‘) __pt__##i++; }while(*__pt__##i);}while(0); int main(void) { FOR(i, 1 2 -3 , -1:10 99:100 999 11:11, 111:3:119,1:-1:-1); DO( FOR(j, 88:2:91); DO( printf("i = %ld, j = %ld\n",i, j) ); DONE(j); ); DONE(i); return 0; }
定义变量使用##是为了防止嵌套使用时候的变量冲突。
逗号和空格可做分隔符, 冒号作为范围指定标记, a:b代表 从a到b, b必须大于a, 增量为1,包含两端, a:b:c 可以包含两端, b为增量, a < c b为正数, a>c b为负数。
范围错误获取不到数值不会报错, 但输入非法会报错, -后面不紧跟数字会报错, 有abc等非数字字符,包括+也会报错,具体情况看代码。
使用的变量都是{}内的局部变量,对外面不会有影响。理论上和外面的变量名字冲突了也不会有影响。
测试代码
i分别取 1 2 -3 -1 0 1 2 3 4 5 6 7 8 9 10 99 100 999 11 111 114 117 1 0 -1
每一个i j分别取 88 90
FOR() DO() DONE()后面的; 可有可无,因为多余的; 编译器会兼容, gcc clang 测试都不会有警告, 如果没有; 可能vim等编辑器在对齐的时候会遇到麻烦。
编译, 执行,打印结果为预期结果。
i = 1, j = 88
i = 1, j = 90
i = 2, j = 88
i = 2, j = 90
i = -3, j = 88
i = -3, j = 90
i = -1, j = 88
i = -1, j = 90
i = 0, j = 88
i = 0, j = 90
i = 1, j = 88
i = 1, j = 90
i = 2, j = 88
i = 2, j = 90
i = 3, j = 88
i = 3, j = 90
i = 4, j = 88
i = 4, j = 90
i = 5, j = 88
i = 5, j = 90
i = 6, j = 88
i = 6, j = 90
i = 7, j = 88
i = 7, j = 90
i = 8, j = 88
i = 8, j = 90
i = 9, j = 88
i = 9, j = 90
i = 10, j = 88
i = 10, j = 90
i = 99, j = 88
i = 99, j = 90
i = 100, j = 88
i = 100, j = 90
i = 999, j = 88
i = 999, j = 90
i = 11, j = 88
i = 11, j = 90
i = 111, j = 88
i = 111, j = 90
i = 114, j = 88
i = 114, j = 90
i = 117, j = 88
i = 117, j = 90
i = 1, j = 88
i = 1, j = 90
i = 0, j = 88
i = 0, j = 90
i = -1, j = 88
i = -1, j = 90
如有错误, 欢迎更正。
本文和代码欢迎复制,但不做任何保证, 不承担任何责任,可用作商业用途,但不准拿去申请专利,对于副本也如此。