任意数字计数器
我需要一个计数器algortihm ,它使用任意给定的数字进行计数。
我的代码与此类似:
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语言不是重点。
编辑我以澄清目的:
我的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 */
这很简单。 您希望转换为base 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; }
您的问题可以分为两部分:
- 将一个整数转换为其在任意基数
n
和中的表示forms - 给出
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; }
完成后,让我们编写一个函数来打印表示:
/* 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 (rn == MAX) return NULL; for (i=rn; i; --i) ret[rn-i] = digits[r.digits[i-1]]; ret[rn-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; }
我已经编写了convert
和上面的内容,以便它们彼此独立(除了我使用反向表示的明显简化)。 这使得在其他程序中使用它们变得很容易。
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; }
看起来你需要重载operator++
而不是get_next
。 这导致了下一个推导,即这个东西应该是一个单独的对象。
我会将“数字”转换为十进制,然后对它们进行操作,然后将它们转换回来。