# Thread: How efficient do you think is this Int To String Converter Function?

1. ## How efficient do you think is this Int To String Converter Function?

Hello! I'm new to this forum!

I'm creating a Dynamic C String Library and i'm not glad about a function i created (About Efficient), because it does so many allocations and deallocations based on the length of the number ( number of digits).

This function takes as input an integer and returns the corresponding string.

Code:
```//Create A CString From A Number.
CString_String *CString_FromInt(int number)
{

//Calculate the length of the number ( #digits ).
int length = floor(log10(abs(number))) + 1;

//Just an int variable.
int digit;

//Is the number negative?
int isNegative = number < 0;

CString_String *final_string = CString_CreateEmpty();;
CString_String *digit_string;
CString_String *temp_string;

//Make sure the number is positive.
number = abs(number);

//Cut the digits from the number.
for (int i = 0; i < length; i++)
{
//Next digit.
digit = number % 10;

//Convert the digit into a CString.
digit_string = CString_FromChar( (char)(digit + '0') );

//Keep a reference to the final string.
temp_string  = final_string;

//Join the digit with to the final string.
final_string = CString_Join(digit_string, final_string);

//Destroy unnecessary memory.
CString_Destroy(digit_string);
CString_Destroy(temp_string);

//Divide the number.
number /= 10;
}

//Add the minus character to the string.
if (isNegative)
{
//Keep a reference to the final string.
temp_string = final_string;

//Create the minus CString.
digit_string = CString_FromChar('-');

//Join it with the final string.
final_string = CString_Join(digit_string, final_string);

//Destroy unnecessary memory.
CString_Destroy(digit_string);
CString_Destroy(temp_string);
}

//Return the CString Successfully.
return final_string;
}```
I did the math and this is the amount of mallocs and frees i'm doing in this algorithm:

Code:
```n: the number of digits

mallocs = 2 + 4*n + 4 = 6 + 4*n
frees   = 4*n + 4

For Example:

if number = 1234567890

n = 10

mallocs = 6 + 4*10 = 46
frees   = 4*10 + 4 = 44```
I guess that's not good.

What if i'm making a game and every frame i need to convert an int to a string using this function? If we say that the game runs at 60fps
i will have to do all this mallocs and frees 60 times per second!!! I think this will not be very efficient.

What do you think? 2. I think you should just use sprintf.

Your code is also broken when you try to convert the largest negative integer. 3. Personally I don't like that the caller has to remember to delete the returned string.
A better interface IMO would be:
Code:
`int CString_FromInt(int number, char *output, int size)`
which you could call like this.
Code:
``` char buffer = {0};
int res = CString_FromInt(1234, buffer, sizeof(buffer));
if (res == 1)
/*handle error*/```
res should be 0 for error, != 0 for success 4. Originally Posted by OldGuy2 Personally I don't like that the caller has to remember to delete the returned string.
A better interface IMO would be:
Code:
`int CString_FromInt(int number, char *output, int size)`
which you could call like this.
Code:
``` char buffer = {0};
int res = CString_FromInt(1234, buffer, sizeof(buffer));
if (res == 1)
/*handle error*/```
res should be 0 for error, != 0 for success
I don't like that either, but i wanted to avoid arrays and sizes, i wanted to be more Java like :P not that i'm a java person, but this way is easier for the eye.
Now about an error, you are right, i can't return an error since i'm returning the pointer. 5. Originally Posted by Salem I think you should just use sprintf.

Your code is also broken when you try to convert the largest negative integer.
Yes you are right. There is not absolute value of INT_MIN since a signed int can't represent it. Math.h documentation says that abs(INT_MIN) result is undefined and u can't expect what you will get, but has anyone solved this problem? 6. Originally Posted by Salem I think you should just use sprintf.

Your code is also broken when you try to convert the largest negative integer.
You are more that right, I should use sprintf.

Code:
```#include <string.h>

int main()
{
float num = 12.34;
char s;

sprintf(s, "%.2f", num);

printf("%s", s);
return 0;
}```
I just want one advice. When i define the dst array, the size must include the null character? For example here 12.34 will be 5 chars + the null char total size is 6.

Also for strcat and strcpy is the same?:

Code:
```#include "../Headers/CString.h"
#include <string.h>

int main()
{
char *s1 = "Hello ";
char *s2 = "World!!!";

char s[strlen(s1) + strlen(s2) + 1];

strcpy(s, s1);
strcat(s, s2);

printf("%s, %d", s, strlen(s));
return 0;
}```
Am i using the buffers correctly? I just wanna be sure not to end up to some buffer overflows. 7. An integer with a finite number of bits has a finite upper bound on the number of bytes you need for it's decimal representation. Why don't you malloc that much just once at the start.

You can realloc to the actual size at the end, but IMO I wouldn't bother. Modern malloc implementations have minimum sizes like 8 or 16 bytes. You can ask for 2 bytes, but the chunk of memory it occupies will be larger. 8. Originally Posted by Salem An integer with a finite number of bits has a finite upper bound on the number of bytes you need for it's decimal representation. Why don't you malloc that much just once at the start.

You can realloc to the actual size at the end, but IMO I wouldn't bother. Modern malloc implementations have minimum sizes like 8 or 16 bytes. You can ask for 2 bytes, but the chunk of memory it occupies will be larger.
Yes, I should probably not bother. Anyway i was making this Library because i'm making a game in C and i need to play with strings. I guess strcpy, strcat, strlen, strcmp, sprintf, atoi, atof, will be enough to do my job and also they will do it fast!!! But i'll probably need to create my own algorithms about replacing characters into a string or string slicing operations like the ones you can do in python  9. So i followed Salem's advice, and i created these function wrappers:

Code:
```//Return's 1 for success, 0 otherwise.
int CString_ToInt(int *dst, char *string){

*dst = atoi(string);

return 1;
}

//Return's 1 for success, 0 otherwise.
int CString_ToFloat(float *dst, char *string){

*dst = atof(string);

return 1;
}

//Return's 1 for success, 0 otherwise.
int CString_ToDouble(double *dst, char *string){

*dst = (double)atof(string);

return 1;
}```
How can i check if the input string is correct? I noticed that atoi() and atof() returns 0 if the string is not a string that represents a number but this is not enough. If i use the string "0" or the string "abs" i will get the same result 0 two times, the first one will be correct but the second means "abs" can't be converted to an integer.

So what can i do for that? 10. You should be using strtol(), strtoul() and strtod() for your conversions.
They return better success/fail information. 11. Originally Posted by Salem You should be using strtol(), strtoul() and strtod() for your conversions.
They return better success/fail information.
What do you have to say about this (i think is good):

Code:
```//Return's 1 for success, 0 otherwise.
int CString_ToInt(int *dst, char *string){

//Reference where the remaining string will be stored.
char *remaining;

//Just Do It!
*dst = strtol(string, &remaining, 10);

//If there is a remaining string, BAD!
if ( strcmp(remaining, "") != 0 )
{
free(remaining);
return 0;
}

//Free the remaining string.
free(remaining);

//Return Successfully.
return 1;
}

//Return's 1 for success, 0 otherwise.
int CString_ToFloat(float *dst, char *string){

//Reference where the remaining string will be stored.
char *remaining;

//Just Do It!
*dst = (float)strtod(string, &remaining);

//If there is a remaining string, BAD!
if ( strcmp(remaining, "") != 0 )
{
free(remaining);
return 0;
}

//Free the remaining string.
free(remaining);

//Return Successfully.
return 1;
}

//Return's 1 for success, 0 otherwise.
int CString_ToDouble(double *dst, char *string){

//Reference where the remaining string will be stored.
char *remaining;

//Just Do It!
*dst = strtod(string, &remaining);

//If there is a remaining string, BAD!
if ( strcmp(remaining, "") != 0 )
{
free(remaining);
return 0;
}

//Free the remaining string.
free(remaining);

//Return Successfully.
return 1;
}``` 12. What on earth are all those free() calls?

You can't free the middle of a buffer allocated with malloc. Also, you break the idea that a function should do one thing only. 13. Originally Posted by Salem What on earth are all those free() calls?

You can't free the middle of a buffer allocated with malloc. Also, you break the idea that a function should do one thing only.
I thought the new reference was a new memory block. So i put that free there on purpose so you can tell me if its wrong  14. Originally Posted by babaliaris There is not absolute value of INT_MIN since a signed int can't represent it. Math.h documentation says that abs(INT_MIN) result is undefined and u can't expect what you will get, but has anyone solved this problem?
The best way to handle INT_MIN is to convert int to unsigned, that way the absolute value of INT_MIN can be represented. As an example:
Code:
```void print_int(int n) {
unsigned u;
if (n < 0) {
u = -(n + 1) + 1;  // carefully convert negative to unsigned
putchar('-');
} else
u = n;
print_uint(u);
}``` 15. Originally Posted by john.c The best way to handle INT_MIN is to convert int to unsigned, that way the absolute value of INT_MIN can be represented. As an example:
Code:
```void print_int(int n) {
unsigned u;
if (n < 0) {
u = -(n + 1) + 1;  // carefully convert negative to unsigned
putchar('-');
} else
u = n;
print_uint(u);
}```
Nice tip!! Popular pages Recent additions dynamic allocation, final_string;, int, number, string 