我想出了两种略有不同的方法:一种使用递归,另一种则不使用。
typedef unsigned long long ull;
void No_Recursion(ull num, char *str, int base, char *alpha){
while (num){
*(str++)=alpha[(num-1)%base];
num=(num-1)/base;
}
}
void Recursion(ull num, char *str, int base, char*alpha) {
if (!num) return;
*str=alpha[(num-1)%base];
Recursion((num-1)/base,str+1,base,alpha);
}
这两个函数的调用方式类似:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define t 1000 // number of numbers to convert
int main (void) {
char *s=calloc(20,sizeof(char));
char al[]="abc";
ull e;
int base=strlen(al);
for (e=1;e<=t;++e) {
Recursion(e,s,base,al); // or the same with No_Recursion
printf("%s\n",s);
}
free(s);
return 0;
}
这给出了相反顺序的输出:
a
b
c
aa
ba
ca
ab
bb
cb
ac
... etc
我在网上搜索了一下,发现可以使用递归算法来解决这个问题。他们建议在递归调用后打印数字。但是,这对我不起作用。而且,No_Recursion
似乎更快一点。当然,我可以使用 strrev
来反转结果字符串,但这需要很多时间。
注意:是的,我正在使用 (num-1)%base
并且它对于我的任务来说是正确的,请不要说我需要使用 num%base
。
注意:字母可能是绝对随机的,而不是按字母顺序排列
最重要的事情:我不知道结果字符串的大小
我们如何将十进制数转换为以 3 为基数(如此处)或以 62 为基数 [a-zA-z0-9] 等,以便在没有 strrev
和类似的情况下,结果数字不会反转功能?
最佳答案
您可以传入一个参数,告诉函数需要使用多少空间,向后填充字符串,然后返回指向所创建字符串开头的指针。
char* No_Recursion(ull num, char *str, int base, char *alpha, size_t count){
char *ptr = *str + count;
*(ptr--) = `\0`;
do{
*(ptr--)=alpha[(num-1)%base];
num=(num-1)/base;
} while (num);
return ptr;
}
或者,如果您确实希望将字符串存储在 str
中,则可以在计算后返回到开头。
void No_Recursion(ull num, char *str, int base, char *alpha, size_t count){
char *ptr = *str + count;
*(ptr--) = `\0`;
do{
*(ptr--)=alpha[(num-1)%base];
num=(num-1)/base;
} while (num);
while(*ptr)
*(str++) = *(ptr++);
*ptr = '\0';
}
请注意,这两种解决方案以及问题中的两个函数都是不安全。所有这些都容易发生缓冲区溢出。这可以通过以下两种方法之一解决:跟踪您在缓冲区中的位置,或者巧妙地分配缓冲区以确保它不会溢出。
明智地分配空间需要在分配空间之前执行计算。
int buffer_size = (int) ceil( log( t ) / log( sizeof(al)/sizeof(al[0]) )) );
char *s = calloc(buffer_size,sizeof(*s));
关于转换为碱基会得到相反的输出。如何在没有strrev的情况下使其正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30220999/