C 任意数字计数器

C 任意数字计数器,c,algorithm,counter,state-machine,C,Algorithm,Counter,State Machine,我需要一个计数器算法,它使用任意给定数字进行计数 我的代码与此类似: static char digits[] = {'x','y','z'}; /* Arbitrary number of arbitrary digits. */ int i; for(i=0; i<100; i++) { printf("%s\n", get_next()); } char get_next() { static previous = digits[0]; char *next

我需要一个计数器算法,它使用任意给定数字进行计数

我的代码与此类似:

static char digits[] = {'x','y','z'}; /* Arbitrary number of arbitrary digits. */
int i;
for(i=0; i<100; i++) {
    printf("%s\n", get_next());
}
char get_next() {
    static previous = digits[0];
    char *next_number;

    /* do something here using previous and digits[] */

    return next_number;
}
如您所见,我需要实现
get_next()
函数的算法,因此使用C语言不是重点

为了澄清,编辑I:

我的get_next()函数可能与以下类似:

static char digits[] = {'x','y','z'}; /* Arbitrary number of arbitrary digits. */
int i;
for(i=0; i<100; i++) {
    printf("%s\n", get_next());
}
char get_next() {
    static previous = digits[0];
    char *next_number;

    /* do something here using previous and digits[] */

    return next_number;
}
请注意,为生成下一个数字的函数使用
get\u next(void)
next(previous\u number)
原型对我来说并不重要

为澄清起见,编辑二:

从上面的简单示例来看,我的真实场景更复杂,我需要一个通用的解决方案,它可以处理任意数字的任意数

数字输入示例:

static char digits[] = {'a', 'b', 'c', ... 'z', '0', '1', ...}; /* Lots of digits */
static char digits[] = {'s','t','a','c','k','o','v','e','r'};   /* Arbitrary sequence */

这很简单。您希望将数字转换为基本数字计数,然后将数字转换为数字,而不是索引到数组中

要转换为任意基数,需要除法和余数

这是一个比我以前使用的更好的版本,因为它实际上创建了一个缓冲区(而不是打印出来),放弃了迭代的递归,并且使用C语言,而不是以前的C/Python大杂烩

因为它使用静态缓冲区,所以代码不是线程安全的。还请注意,如果数字太大,则检查代码是否未在缓冲区下溢不会出错。最后,它使用了一种技巧,从字符串的末尾到前面构建字符串,并返回一个指向缓冲区中间的指针,这样就不必反转末尾的数字

char *getnum(int x)
{
    static char buffer[1024];
    int idx = 1024;

    buffer[--idx] = '\0';

    if (x == 0)
        buffer[--idx] = digits[0];
    else
    {
        while (x != 0)
        {
            buffer[--idx] = digits[x % digit_count];
            x /= digit_count;
        }
    }    

    return buffer + idx;
}

您的问题可分为两部分:

  • 将整数转换为其在任意基中的表示形式,
    n
    ,然后
  • 给定
    n
    符号,打印上面的表示
  • 第二部分显然很简单。如果你在一个给定的基数中有一个数字的表示,并且你想在这个基数中使用符号,那么把它们打印出来就是在循环中打印东西

    为了得到给定基中整数的表示,我们将使用
    int
    s数组,值表示数字,索引表示位置。我们还需要存储有效位数。另外,我们假设我们只处理正数,因为这是你在问题中的建议

    #define MAX 128 /* maximum number of digits in the final representation */
    
    /* abstract representation of a number in a given base.
       `n` is the number of valid digits in the representation, and
       `digits` stores the digits in reverse order */
    struct rep {
        int digits[MAX]; /* change as needed, or dynamically allocate */
        size_t n;
    };
    
    然后,让我们编写一个函数,将数字转换为其表示形式。由于返回反向表示更容易,因此我们将返回该表示,然后也按反向顺序打印:

    /* convert a number `n` to its (reversed) representation in base `base`,
       and return the result in `ret`. */
    void convert(int n, size_t base, struct rep *ret)
    {
        size_t i = 0;
        do {
            ret->digits[i++] = n % base;
            n /= base;
        } while (n > 0 && i < MAX);
        ret->n = i;
    }
    
    然后,我们可以编写驱动程序:

    int main(void)
    {
        const char digits[] = {'x','y','z'};
        size_t ndigits = sizeof digits / sizeof digits[0];
        int i;
        for (i=0; i < 100; i++) {
            char *data = next(digits, ndigits, i);
            if (data)
                printf("%s\n", data);
            else
                fprintf(stderr, "%d, error converting\n", i);
        }
        return 0;
    }
    
    int main(无效)
    {
    常量字符位数[]={'x','y','z'};
    size_t ndigits=sizeof digits/sizeof digits[0];
    int i;
    对于(i=0;i<100;i++){
    字符*数据=下一个(数字,ndigit,i);
    如果(数据)
    printf(“%s\n”,数据);
    其他的
    fprintf(stderr,“%d,错误转换\n”,i);
    }
    返回0;
    }
    

    我在上面写了
    convert
    next
    ,使它们彼此独立(除了使用反向表示的明显简化)。这使得在其他程序中使用它们变得很容易。

    看起来需要重载
    操作符+
    ,而不是
    get\u next
    。这导致了下一个推导,即这个东西应该是一个单独的对象


    我会将“数字”转换成十进制,然后对它们进行运算,然后再将它们转换回来。

    你确定你想要一个get_next(),而不是一个get(I),在那里我会被转换成你自己的编号函数吗?你不希望有x,y,z,xx,xy,xz,yx,yy,yz,zx,zy?帕斯迪亚布洛:我认为他不会,在这个计数系统中,
    x
    0
    的等价物。就像你没有小数形式的介于
    9
    10
    之间的
    00
    。@paxdiablo:我认为给出的示例是正确的。例如,假设x、y、z分别为0、1、2。如何让_next()知道
    数字
    ,或者上一次返回的组合是什么(假设您不希望其中有一个静态值),您假设这些数字在ASCII中是连续的。关于
    digits={'a','h','t','z'}
    ?您的解决方案是针对特定数量的数字,我需要针对“任意数量的任意数字”的解决方案,我可以使用255作为基数(itoa的第三个参数)?@eyazici:对于值>36,您必须滚动您自己的itoa,但本质上,状态机只是变量“i”。@abyx:itoa中的数字是连续的,然后用作数字的索引,不做任何假设,它只是一个查找表。这就是我要找的,我想它是递归的,但我找不到如此优雅的解决方案,谢谢。顺便问一下,如果你是Python或Pascal程序员,在花括号之前使用半列(这对C来说是非法的),这绝对是最简单和最好的方法。假设它已经使用了一个静态缓冲区,那么它也可以启动“static int next_x=0;int x=next_x++”,而不是传入x,并被称为get_next(),如果这是真正需要的话。
    int main(void)
    {
        const char digits[] = {'x','y','z'};
        size_t ndigits = sizeof digits / sizeof digits[0];
        int i;
        for (i=0; i < 100; i++) {
            char *data = next(digits, ndigits, i);
            if (data)
                printf("%s\n", data);
            else
                fprintf(stderr, "%d, error converting\n", i);
        }
        return 0;
    }