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