我一直在研究学校的一些练习题,其中之一是必须将输入的整数写到动态分配的字符串中。该代码可以正常工作,直到释放分配的内存(发生堆损坏)为止。
有人可以解释为什么发生这种情况以及我在做什么错吗?
int main() {
char *string = NULL;
char **string2 = &string;
Conversion(string2);
printf("Entered number converted to string: %s", string);
free(string);
return 0;
}
int Conversion(char **string) {
int num = 0, temp = 0, dcount = 0;
printf("Enter number: ");
scanf(" %d", &num);
temp = num;
while (temp != 0) {
temp /= 10;
dcount++;
}
*string = (char*)malloc(dcount*sizeof(char));
if (*string == NULL) {
printf("Error during memory allocation!");
return -1;
}
sprintf(*string, "%d", num);
return 0;
}
答案 0 :(得分:5)
您需要分配一个额外的字符来说明\0
终止符。
*string = (char*)malloc((dcount + 1) * sizeof(char));
如果dcount
为0或负数,则num
也不正确。
其他评论:
您可以use snprintf()
to calculate the needed buffer size。这样可以节省计算num
中数字的所有繁重工作,并且可以正确处理所有边缘情况。
int dcount = snprintf(NULL, 0, "%d", num);
您应该avoid casting malloc's return value。
*string = malloc((dcount + 1) * sizeof(char));
sizeof(char)
被定义为1。我将省略乘法
*string = malloc(dcount + 1);
但是,如果您保留它,avoid hard coding the item type。
*string = malloc((dcount + 1) * sizeof(**string));
如果您将字符串从char*
更改为char16_t*
/ char32_t*
/ wchar_t*
,则该字符串会自动调整,而sizeof(char)
会在没有错误的情况下进行编译不匹配。
答案 1 :(得分:2)
该功能有几个缺点。
对于初学者,您无需考虑分配的字符串的终止零'\0'
。
第二,用户可以输入0
作为数字。在这种情况下,dcount
的值将不正确,因为循环
while (temp != 0) {
temp /= 10;
dcount++;
}
将被跳过。
第三,该功能将无法正确处理负数,并且允许用户输入负数。
此声明
char **string2 = &string;
是多余的。您可以通过以下方式调用该函数
Conversion( &string );
该功能不应该要求用户输入数字。该函数应该仅执行一项任务:将整数转换为字符串。
还有一个功能设计缺陷。
从函数声明中
int Conversion(char **string);
(应该在函数main
之前),尚不清楚用户是为字符串提供内存还是由函数为字符串分配内存。
如下面的演示程序所示,该函数的更好的界面可以采用以下方式显示。
#include <stdio.h>
#include <stdlib.h>
char * Conversion( int x )
{
const int Base = 10;
size_t digits = x < 0 ? 1 : 0;
int tmp = x;
do
{
++digits;
} while ( tmp /= Base );
char *s = malloc( digits + sizeof( ( char )'\0' ) );
if ( s != NULL ) sprintf( s, "%d", x );
return s;
}
int main( void )
{
int num = 0;
printf( "Enter a number: " );
scanf( "%d", &num );
char *s = Conversion( num );
if ( s != NULL )
{
printf( "The entered number converted to string: %s\n", s );
}
else
{
puts( "A conversion error ocured." );
}
free( s );
}
其输出可能如下所示
Enter a number: -12
The entered number converted to string: -12
请注意,根据C标准,不带参数的函数main
应该声明为
int main( void )