Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Some questions concerning a C integer to string function

Tags:

c

Whilst reading through K&R, I came across the integer to string function. I gave it a quick read, and decided to implement it myself, but instead of printing, it updates a character array.

Here is what I have

void inttostr(int number, char str[]) {
    static int i;  
    if (number / 10) {
        inttostr(number / 10, str); 
    }       
    str[i++] =  number % 10 + '0';      
}

It seemed to work for the few integers I gave it, but I have some questions.

  1. I haven't explicitly included the nul byte \0 at the end, so why does the string work fine when printed with printf("%s\n", str);?
  2. I don't think I'm very good at thinking recursively. When I try and step through the program in my mind, I lose track of what is still awaiting execution. Is there a better way of seeing what is happening internally, to help me learn?
  3. Any other suggestions on the code?

I'm using Xcode.

This is not homework. I'm just learning.

Thanks!

like image 429
alex Avatar asked Apr 09 '26 12:04

alex


2 Answers

You're correct that you're never writing NUL, which is a bug.

In general, you don't have to think through the entire solution. You just have to make sure every step is correct. So in this case, you say:

1 . inttostr(number / 10, str);

will take care of all but the last digit.

2 . Then I will take care of the last one.

You can trace what's happening, though. For e.g. 54321 it looks like:

inttostr(54321, str); // str = ...;
inttostr(5432, str); // str = ...;
inttostr(543, str); // str = ...;
inttostr(54, str); // str = ...;
inttostr(5, str); // str = ...;
str[0] = '5'; // str = "5...";
str[1] = '4'; // str = "54...";
str[2] = '3'; // str = "543...";
str[3] = '2'; // str = "5432...";
str[4] = '1'; // str = "54321...";

Note that when you don't return from any of the functions until you write the first character, then you return in the opposite order from the calls.

The ... signifies that you haven't NUL-terminated. Another issue is that you're using a static variable, so your code isn't reentrant; this means it breaks in certain scenarios, including multi-threading.

To address the reentrancy and NUL issue, you can do something like the code below. This creates a helper function, and passes the current index to write.

void inttostr_helper(int number, char str[], int *i)
{
    if (number / 10) {
        inttostr_helper(number / 10, str, i); 
    }       
    str[(*i)++] =  number % 10 + '0';
    str[*i] = '\0';
}

void inttostr(int number, char str[])
{
  int i = 0;
  inttostr_helper(number, str, &i);
}

EDIT: Fixed non-static solution.

like image 199
Matthew Flaschen Avatar answered Apr 12 '26 03:04

Matthew Flaschen


I am impressed of the creativity to use recursive, despite that it is not necessary. I think the code should remove statically-allocated i variable because this variable will persist through calls. So the second time you use this function from your code, e.g. from main(), it will not be initiated and will be the same value from previous call. I would suggest using return value as follow:

int inttostr(int number, char *str) {
   int idx = 0;
   if (number / 10) {
        idx = inttostr(number / 10, str); 
   }       
   str[idx++] =  number % 10 + '0';
   return idx;
}
like image 45
tia Avatar answered Apr 12 '26 02:04

tia



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!