任意数字计数器

发布于 2024-08-15 11:00:24 字数 1155 浏览 3 评论 0原文

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

我的代码与此类似:

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

我的预期输出:

x
y
z
yx
yy
yz
zx
zy
zz
yxx
yxy
yxz
yyx
yyy
yyz
yzx
yzy
yzz
zxx
... and so on

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

出于澄清目的编辑 I:

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

char get_next() {
    static previous = digits[0];
    char *next_number;

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

    return next_number;
}

请注意,使用 get_next(void)next( previous_number)next(digits, previous_number) 生成下一个数字的函数原型对我来说并不重要。

编辑 II 以进行澄清:

我的实际场景比上面的简单示例更复杂,我需要一个适用于任意数字任意数字的通用解决方案强>。

数字输入示例:

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 */

I need a counter algortihm which use arbitrary given digits for counting purpose.

My code is similar to this:

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

My expected output:

x
y
z
yx
yy
yz
zx
zy
zz
yxx
yxy
yxz
yyx
yyy
yyz
yzx
yzy
yzz
zxx
... and so on

As you see, I need algorithm for implementing get_next() function, so using C language is not the point.

Edit I for clarification purpose:

My get_next() function may similar to this:

char get_next() {
    static previous = digits[0];
    char *next_number;

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

    return next_number;
}

Note that using get_next(void) or next(previous_number) or next(digits, previous_number) prototype for your function which generates next number is not important for me.

Edit II for clarification purpose:

My real scenario is more complex from the simple example above, I need a generic solution that works with arbitrary number of arbitrary digits.

Example digit inputs:

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 */

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

﹉夏雨初晴づ 2024-08-22 11:00:25

这很简单。您想要转换为基本的digit_count,然后不是将数字转换为数字,而是索引到数组中。

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

这是一个比我之前使用的版本更好的版本,因为它实际上创建了一个缓冲区(而不是将其打印出来),放弃了迭代递归,并且使用 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;
}

It's quite simple. You want to convert into base digit_count and then instead of converting the digits to numbers, you index into your array.

To convert to an arbitrary base, you need division and remainder.

Here's a better version than what I used before because it actually creates a buffer (rather than prints it out), drops recursion for iteration and is in C instead of my previous C/Python hodgepodge.

Because it uses a static buffer, the code is not thread safe. Also note that there is no error checking that the code doesn't underflow the buffer if the number is too large. Finally, it uses a trick of building the string from the end to the front and returning a pointer to the middle of the buffer so it doesn't have to reverse the digits at the end.

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;
}
迷鸟归林 2024-08-22 11:00:25

您的问题可以分为两部分:

  1. 将整数转换为其任意基数 n 的表示形式,并
  2. 给定 n 符号,打印上面的表示形式。

第二部分显然非常简单。如果您有给定基数中数字的表示形式,以及要在该基数中使用的符号,那么将它们打印出来只是在循环中打印内容。

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

#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;
}

完成此操作后,让我们编写一个函数来打印表示:

/* return a string representation of `num` in base `ndigits`, with `digits`
   representing the symbols */
char *next(const char *digits, size_t ndigits, int num)
{
    struct rep r;
    static char ret[MAX+1];
    size_t i;
    convert(num, ndigits, &r);
    if (r.n == MAX)
        return NULL;
    for (i=r.n; i; --i)
        ret[r.n-i] = digits[r.digits[i-1]];
    ret[r.n-i] = 0;
    return ret;
}

然后,我们可以编写驱动程序:

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;
}

我已经编写了 Convertnext ,以便它们彼此独立(除了我使用反向表示的明显简化之外)。这使得在其他程序中使用它们变得很容易。

Your question can be split into two parts:

  1. convert an integer to its representation in an arbitrary base, n, and
  2. given n symbols, print the representation above.

The second part is obviously very easy. If you have a representation of a number in a given base, and the symbols that you want to use in such a base, then printing them out is just printing things in a loop.

To get an integer's representation in a given base, we will use an array of ints, with the values representing the digits, and the indices representing the places. We also need to store the number of valid digits. Also, we are assuming that we're dealing with positive numbers only, since that's what you seem to suggest in your question.

#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;
};

Then, let's write a function to convert a number to its representation. Since it's easier to return a reversed representation, we will return that, and then print in reverse order too:

/* 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;
}

Having done this, let's write a function to print the representation:

/* return a string representation of `num` in base `ndigits`, with `digits`
   representing the symbols */
char *next(const char *digits, size_t ndigits, int num)
{
    struct rep r;
    static char ret[MAX+1];
    size_t i;
    convert(num, ndigits, &r);
    if (r.n == MAX)
        return NULL;
    for (i=r.n; i; --i)
        ret[r.n-i] = digits[r.digits[i-1]];
    ret[r.n-i] = 0;
    return ret;
}

Then, we can write our driver program:

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;
}

I have written convert and next above so that they're independent of each other (apart from the obvious simplification that I'm using reversed representations). This makes it easy to use them in other programs.

你爱我像她 2024-08-22 11:00:25
char *get_next()
{
  static char str[10];
  static int i=0;
  int radix = 3; // size of array
  itoa(i,str,radix); // create base-3 representation
  char *p = &str[0];
  while( *p )
  {
    *p = digits[*p-'0']; // convert to the xyz scheme, breaks if radix>10
    p++;
  }
  i++;
  return str;
}
char *get_next()
{
  static char str[10];
  static int i=0;
  int radix = 3; // size of array
  itoa(i,str,radix); // create base-3 representation
  char *p = &str[0];
  while( *p )
  {
    *p = digits[*p-'0']; // convert to the xyz scheme, breaks if radix>10
    p++;
  }
  i++;
  return str;
}
∞觅青森が 2024-08-22 11:00:25

看起来您需要重载 operator++ 而不是 get_next 。这就引出了下一个推论,即这个东西应该是一个单独的对象。

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

Looks like instead of get_next you need to overload the operator++. This leads to the next derivation which is that this thing should be a separate object.

I would convert the "digits" into decimal, then operate on them, then convert them back.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文