0

I am writing a bit of an operating system, and I require the ability to print the addition of a variable. I have a working atoi function and so I reversed it to give me an itoa function. There is no way to access free memory, so I need to figure out the the number of digits in order to create the proper sized char array. I figured I would need to divide by 10 to get that, and then modulus the values into the correct spot. This is my c code so far:

char* itoa(int res) {
    int size = 0;
    int t = res;

    while(t / 10 != 0) {
        t = t/10;
        size ++;
    }
    char ret[size+1];
    ret[size] = '\0';

    t = res;
    int i = size - 1;
    while(i > 0) {
        ret[i] = t % 10;
        t = t/10;
        i--;
    }

    return ret;
}

As of right now, it prints nothing. What is wrong with it?

Dylan Turner
  • 322
  • 1
  • 12

3 Answers3

3

It has a few bugs. Here's a working version for positive numbers at least:

char* itoa(int res) {
    int size = 0;
    int t = res;

    while(t / 10 != 0) {
        t = t/10;
        size++;
    }
    static char ret[64];
    size++;
    ret[size] = '\0';
    t = res;
    int i = size - 1;
    while(i >= 0) {
        ret[i] = (t % 10) + '0';
        t = t/10;
        i--;
    }

    return ret;
}
Rudi Cilibrasi
  • 885
  • 4
  • 12
2

There are a lot of things wrong here. Most obviously:

  • You're returning the value of a temporary. ret is on the stack and doesn't exist after popping.
  • You're trying to dynamically allocate something on the stack. This might actually work, but you shouldn't unless you know what you're doing.

Put together, these basically kill your implementation. So, to be helpful, here's some untested code:

void putc(char c) {
    /*Output "c" via BIOS interrupt or VGA write.  Or whatever.*/
}
void print(int num) {
    if (num!=0) {
        /*Largest num is `2,147,483,64(7|8)`*/
        char temp[10];
        int i = 0;
        if (num<0) { putc('-'); num=-num; }
        if (num>0); else { temp[i++]='8'; num=-(num/10); } //signed wraparound
        while (num>0) {
            temp[i++] = num%10 + '0';
            num /= 10;
        }
        while (--i>=0) putc(temp[i]);
    } else putc('0');
}
geometrian
  • 14,775
  • 10
  • 56
  • 132
  • 3
    Note: Fails with `INT_MIN`. Candidate fix: `if (num<0) putc('-'); else num=-num; char temp[10]; int i = 0; do { temp[i++] = '0' - num%10; num /= 10; } while (num);` – chux - Reinstate Monica Jul 10 '15 at 01:51
  • 1
    @chux Fixed for the benefit of people of the future. Also now more branch predictor friendly. I like how the `-` order matters here. :D – geometrian Jul 10 '15 at 02:05
  • This was really helpful, thank you. I was going about this all wrong, as I didn't need to convert all "strings" to ints; I simply needed to output the integer (for now anyways). So thanks. – Dylan Turner Jul 10 '15 at 02:24
1

If you can put up with the caller providing a buffer large enough for all expected outputs, then you can:

#include <stdio.h> 

    char * rIntToAscii(int num, char * result){ 
        if( num == 0 ) return result; 
        else{ 
             result=rIntToAscii( num/10, result );
             *result = '0'+num%10;
            return result+1; 
        } 
    };

    void intToAscii(int num,char *output){
      if (num==0){
        *output++='0';
        *output='\0';
      }
        else
        {
          if(num<0){
            *output++='-';
            num=-num;
          };
          *rIntToAscii(num, output) = '\0';
        };
    };

    int main(void) 
    { 
        int test = -10;
        char testOutput[ 32 ];
        intToAscii(test,testOutput);
        printf( "%s", testOutput );
        return 0; 
    }
Martin James
  • 24,453
  • 3
  • 36
  • 60