我尝试编译该程序,但编译器收到一条消息,提示"分段错误(内核已转储)"。 谁能告诉我出什么事了吗?
#include
#include
#include
#define power(x,y) (int)pow((double)x,(double)y)
/*-------------------setBits-------------------*/
/* A function to set the i (and following) bit(s) to be 'number'. The function takes 'number' and adds the matching powers of 2 to 'destination'. */
void setBits(int number, int i, int *destination) {
for( ; number!=0 ; number/=2 , i++)
(*destination) += (number % 2) * (power(2, i));
}
/*-------------------getDigit-------------------*/
/* A function that returns a string of 'number' converted to base 32. */
char getDigit(int number) {
char *digits ="0123456789ABCDEFGHIJKLMNOPQRSTUV";
return digits[number];
}
/*-------------------get32-------------------*/
/* A function that returns a string of 'number' converted to base 32. */
char *get32(int number) {
char *result ="";
if (number/32 == 0)
result[0] = getDigit(number);
else strcat(result,get32(number/32));
return result;
}
/*-------------------main-------------------*/
int main(){
int test = 0;
setBits(23, 5, &test);
printf("%s", get32(test));
return 0;
}
另外,如果有人有更好的代码提示,我也很乐意获得建议(:
谢谢。
请确认编译和链接阶段都可以,但是当您尝试运行它时,导致的二进制崩溃。
char *result =""这将创建一个指向只读存储器的指针。 您不能使用strcat对其进行追加,因为修改此字符串将导致不确定的行为,在您的情况下为分段错误。
重新安装操作系统和编译器。
用C处理字符串很棘手。您无法像使用脚本语言一样轻松地拆分和连接它们。字符串是字符数组,其存储必须由用户处理。这也是造成分段违规的原因:您尝试修改只读内存。
其他答案建议使用malloc。这是一种获取内存以容纳strig的可行方法,但它有一个缺点:必须释放内存。这意味着您不能直接在printf中使用get32的返回值,因为您必须将分配的字符串的句柄保留在某个地方。
这也意味着您的递归解决方案不适合C,因为您必须free所有中间字符串。
在您的情况下,您需要的字符串很短。您希望以32为基数打印一个32位数字。该数字最多可以包含7位数字,因此需要八个字节。 (第八个字节用于存储终止空字符。)
另一种不使用分配的有用方法是传入一定长度的缓冲区并让函数填充它。该函数必须接收数组及其长度作为参数:
char *get32(char buf[], int len, int number)
{
const char *digits ="0123456789ABCDEFGHIJKLMNOPQRSTUV";
int n = len;
buf[--n] = '\\0';
memset(buf, '0', n);
while (number) {
buf[--n] = digits[number % 32];
number /= 32;
}
return &buf[n];
}
此函数写入一个具有len - 1位的数字,最初全为零,然后返回一个指向第一个非零数字的指针,以便可以打印它。 char缓冲区由调用函数提供:
int main()
{
int test = 0;
char buf[8];
setBits(23, 5, &test);
puts(get32(buf, sizeof(buf), test));
return 0;
}
当然,如果要在同一printf中打印两个数字,则必须使用不同的缓冲区,否则缓冲区将被覆盖。
非常感谢,这对我有很大帮助!
您需要为结果分配内存。加
#include
并将结果声明更改为
char *result = calloc( BUFSIZE, sizeof(char));
其中BUFSIZE是最大长度结果,可以将结尾的'\ 0'加一。 calloc()用零填充已分配的内存,因此您的结果字符串将正确终止。
为了避免内存泄漏,您还应该在每次调用get32()之后释放缓冲区:
char *result = get32(...)
printf("%s", result);
free(result);
在main()中,同样在get32()本身调用之后。
您的错误在这里:
char *result ="";
strcat(result,get32(number/32));
man strcat将确认您第一个期望的参数是写入结果字符串的目标位置。由于您将result作为目标,因此strcat()将尝试写入result。不幸的是,该指针指向二进制程序的特殊目标,在该目标中注册了其文字字符串(此处为"")。本部分是只读的。
strcat()尝试写入只读节=> BOOM => SIGSEGV。
您应该为result分配(malloc())内存并使用strncat():
char* const result = malloc(SOME_SIZE*sizeof(char));
result[0] = '\\0';
strncat(result, get32(number/32), SOME_SIZE);
最后,不要忘记free(result);)。
...并且我是否强制malloc返回?
@LPs man strcat:"与strcat()一样,dest中生成的字符串始终以空值结尾。" 但是+1演员。
..但是src不在您的情况下。 另请注意,sizeof(result)在您的strncat中是错误的:它将返回char *的大小,主要是4或8。
我不想打扰您,但这不是正确的解决方案。 您可以更正get32以返回NULL终止的字符串,或使用calloc