zoukankan      html  css  js  c++  java
  • 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

    如有错误, 欢迎更正。

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

  • 相关阅读:
    开源项目
    [Accessibility] Missing contentDescription attribute on image [可取行]失踪contentDescription属性图像
    Android 布局 中实现适应屏幕大小及组件滚动
    EF 错误记录
    EasyUI 加载时需要显示和隐藏 panel(面板)内容破版问题
    IE 报表缩放后页面破版
    VS 2017 引入nuget 问题
    SSRS 报表显示页面 asp net session丢失或者找不到 asp net session has expired or could not be found()
    log4net 配置
    网站
  • 原文地址:https://www.cnblogs.com/yiifburj/p/4437698.html
Copyright © 2011-2022 走看看