• c 按范围快速指定整数


    以前用过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)
    ", #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
    ",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

    如有错误, 欢迎更正。

    本文和代码欢迎复制,但不做任何保证, 不承担任何责任,可用作商业用途,但不准拿去申请专利,对于副本也如此。

  • 相关阅读:
    新手建站必看
    88.com域名邮箱免费注册了
    屏蔽博客园的广告
    跳过烦人的hCaptcha验证
    pap.er 专为 Mac 设计的壁纸应用
    TrafficMonitor
    利用CloudFlare自动DDNS
    P.SDA1.DEV
    谷歌浏览器又隐藏的HTTPS和WWW前缀
    谷歌浏览器扩展 crx 下载
  • 原文地址:https://www.cnblogs.com/yiifburj/p/4437698.html
Copyright © 2020-2023  润新知