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)\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

如有错误, 欢迎更正。

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

时间: 2024-11-05 09:33:49

c 按范围快速指定整数的相关文章

[算法学习]给定一个整型数组,找出两个整数为指定整数的和(3)

问题描述: 设计一个类,包含如下两个成员函数: Save(int input) 插入一个整数到一个整数集合里. Test(int target) 检查是否存在两个数和为输入值.如果存在着两个数,则返回true,否则返回false 允许整数集合中存在相同值的元素 分析: 与[算法学习]给定一个整型数组,找出两个整数为指定整数的和(2)不同,这里需要算出的是存不存在这两个数,可以在上一篇的基础上修改一下数据结构,HashMap其中key是数值,value是数值个数,然后需要作两步判断,map中存在数

求指定整数范围内的素数之和

//求指定整数范围内的素数之和int getSumResult(int start,int end){ int i,j; int flag=0; int result=0; if(start<0||end <0) { lr_output_message("开始值.结束值需要为正整数"); exit(-1); } else if(start>=end) { lr_output_message("开始值需要<结束值"); exit(-1); }

算法初级面试题08——递归和动态规划的精髓、阶乘、汉诺塔、子序列和全排列、母牛问题、逆序栈、最小的路径和、数组累加成指定整数、背包问题

第八课主要介绍递归和动态规划 介绍递归和动态规划 暴力递归: 1,把问题转化为规模缩小了的同类问题的子问题 2,有明确的不需要继续进行递归的条件(base case) 3,有当得到了子问题的结果之后的决策过程 4,不记录每一个子问题的解 动态规划 1,从暴力递归中来 2,将每一个子问题的解记录下来,避免重复计算 3,把暴力递归的过程,抽象成了状态表达 4,并且存在化简状态表达,使其更加简洁的可能 图灵引入的是:我不知道怎么算,但是我知道怎么试.知道怎么暴力破解出来. 要学会,练习懂得怎么尝试.

混合使用 ForkJoin, Akka, Future 实现一千万个不重复整数的排序

  本来只是想写一个 ForkJoin 的示例,但写着写着就加入了 akka, future 的元素, 是在解决问题的过程中逐渐引入的.我觉得这种学习的方式很好,就是在解决一个问题的过程中,可以综合地探索和学习到很多不同的东西.传统的学习讲究"循序渐进"的方式,但是"跳跃式+快速试错"也许是学习新技术的更好的方法. :) 原本是想实现十亿个不重复整数的排序, 由于文件外排序没有解决,因此,暂时实现的是一千万个不重复数,可以一次性加载到 2G 的内存里.  一. 任务

redis快速入门-数据类型

前言 最近因项目需要用到redis,所以借助<Redis入门指南>(李子骅 编著)这本书快速入门了一下,此处记录下一些知识点(主要是命令),方便以后查阅. 简介 Redis是一个开源的key-value存储,并用于构建高性能,可扩展的Web应用程序的完美解决方案. Redis的三个主要特点: Redis数据库完全在内存中,使用磁盘仅用于持久性. 相比许多键值数据存储,Redis拥有一套较为丰富的数据类型. Redis可以将数据复制到任意数量的从服务器. Redis的优势 异常快速:Redis的

Swift编程语言学习——注释、分号、整数、浮点数

注释 请将你的代码中的非执行文本注释成提示或者笔记以方便你将来阅读.Swift 的编译器将会在编译代码时自动忽略掉注释部分. Swift 中的注释与C 语言的注释非常相似.单行注释以双正斜杠作(//)为起始标记: // 这是一个注释 你也可以进行多行注释,其起始标记为单个正斜杠后跟随一个星号(/*),终止标记为一个星号后跟随单个正斜杠(*/): /* 这是一个, 多行注释 */ 与C 语言多行注释不同,Swift 的多行注释可以嵌套在其它的多行注释之中.你可以先生成一个多行注释块,然后在这个注释

JavaScript基础使用parseInt()转换整数(005)

parseInt()可以把一个字符串格式的整数解析一个整数数值,如"32 days"将被解析为32.这个函数还接受第二个参数,指定整数的进制(当然,一般来说应该是十进制).一个好的习惯是,总是使用这第二个参数,以防一些意外的Bug的出现. var month = "06", year = "09", DECIMAL = 10: month = parseInt(month, DECIMAL); year = parseInt(year, DECI

[小技巧] 快速给目录打包

$ tar zcvf directory{.tar.gz,} # 只要目录名和tar包的一致,就可以用大括号快速指定参数. 示例: $ tar zcvf net{.tar.gz,} $ ls -ld net*drwxrwxr-x. 2 aaa aaa 4096 8月   8 03:48 net-rw-rw-r--. 1 aaa aaa 220507 8月  20 21:03 net.tar.gz 译至:https://twitter.com/climagic/status/50183003845

整数和浮点数

整数 整数就是没有小数部分的数字,比如42和-23.整数可以是有符号(正.负.零)或者无符号(正.零). Swift 提供了8,16,32和64位的有符号和无符号整数类型.这些整数类型和 C 语言的命名方式很像,比如8位无符号整数类型是UInt8,32位有符号整数类型是Int32.就像 Swift 的其他类型一样,整数类型采用大写命名法. 整数范围 你可以访问不同整数类型的min和max属性来获取对应类型的最小值和最大值: let minValue = UInt8.min // minValue