Converting Integer to dynamically allocated Char array, digit by digit using pointers

797 views Asked by At

I need to convert Integer to Char, I can use only pointers without array indexes. Char array must be dynamically allocated. Can anybody review my code and tell my what am I doing wrong?

#include <stdio.h>
#include <stdlib.h>

int main(){

    int myNumber = 1234;
    char *myString = (char*)malloc(2 * sizeof(char));  //memory for 1 char and '\0'
    int i = 0; //parameter for tracking how far my pointer is from the beggining

    if (myNumber < 0){
        *myString = '-';    //if myNumber is negative put '-' in array
        *myString = *(myString + 1);    //move pointer to next position
        i++;
    }

    while (myNumber != 0){

        myString = (char*)realloc(myString, (i + 2) * sizeof(char));    //increse memory =+1
        *myString = (myNumber % 10) + '0'; //put digit as char to array
        myNumber /= 10;

        *myString = *(myString + 1);    //move pointer to next position

        i++;
    }
    *myString = '\0';   //mark end of string
    *myString = *(myString - i);    //move pointer back to the beggining of string

    printf("\n%s", *myString); // print char array (not working..)

    return 0;
}

I know there are better ways of converting Int to String (sprintf), but my task is to do it that way. In the code above I`m taking the digits from Int backwards, can it be done in correct order?

edit. as mentioned in the comments the part:

*myString = *(myString + 1);

is wrong, correct way of redirecting pointer by one space is:

myString++;

same with:

*myString = *(myString - i);    //wrong
myString -=i;    //ok

Edit2: Now my code works! But I need to think how to correct the order of the digits.

#include <stdio.h>
#include <stdlib.h>

int main(){

    int myNumber = 1234;
    char *myString = (char*)malloc(2 * sizeof(char));  //memory for 1 char and '\0'
    char * position = myString;

    int i = 0;

    if (myNumber < 0){
        *position = '-';    //if myNumber is negative put '-' in array
        position += i;  //move pointer to next position
        i++;
    }

    while (myNumber != 0){

        myString = (char*)realloc(myString, ((i + 2) * sizeof(char)));  //increse memory =+1
        position = myString + i; // getting current position after reallocating
        *position = (myNumber % 10) + '0'; //put digit to array
        myNumber /= 10;

        position++; //move pointer to next position

        i++;
    }
    *position = '\0';   //mark end of string

    char * temp = myString;

    while (*temp != '\0'){      
        printf("%c", *temp); // print char array (not working..)
        temp++;
    }

    return 0;
}

Edit 3 Problem solved, thanks for comments, I`m posting code in case anybody will look for similar solution.

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

// move each character in array one place to the right
// we need to make place for new character on the left
void moveArrayElementsRight(char *ptr, int len) {
    for (int j = len; j > 1; j--) {
        *(ptr + j - 1) = *(ptr + j - 2);
    }
}

void intToStr(int myNumber, char* myString){
    int i = 1;    //track size of allocated memory
    bool isMinus = false;

    if (myNumber < 0) {

        myNumber *= -1;    //without this (myNumber % 10) + '0' wont work
        isMinus = true;
    }

    if (myNumber == 0){    //special case for 0

        myString = (char*)realloc(myString, ((i + 1) * sizeof(char)));
        *myString = '0';
        *(myString + 1) = '\0';
    }

    while (myNumber != 0) {

        myString = (char*)realloc(myString, ((i + 1) * sizeof(char)));  //increse memory =+1 for next digit
        i++;
        moveArrayElementsRight(myString, i);
        *myString = (myNumber % 10) + '0'; //put digit to array
        myNumber /= 10;
    }

    if (isMinus) {

        myString = (char*)realloc(myString, ((i + 1) * sizeof(char)));  //increse memory =+1 for '-' sign
        i++;
        moveArrayElementsRight(myString, i);
        *myString = '-'; //put sign at the beginning
    }
}

int main() {

    int numberToConvert = -10;
    char *numberAsString = (char*)malloc(sizeof(char));  //create empty array, with place only for '\0'
    *numberAsString = '\0';    //mark the end of array

    intToStr(numberToConvert, numberAsString);

    printf("%s", numberAsString);

    return 0;
}
1

There are 1 answers

0
Stargateur On BEST ANSWER

SPOILER: Don't read or copy this if you don't want the solution.

The following is an example of implementation, using recursive:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <limits.h>
#include <string.h>
#include <time.h>
#include <errno.h>

static size_t int_to_str_size(int n, size_t acc, int base_size) {
  int next = n / base_size;
  if (next != 0) {
    return int_to_str_size(next, acc + 1, base_size);
  } else {
    return n < 0 ? acc + 2 : acc + 1;
  }
}

static void int_to_str_write(int n, char *str, char *base, int base_size) {
  *str = base[abs(n % base_size)];

  int next = n / base_size;
  if (next != 0) {
    int_to_str_write(next, str - 1, base, base_size);
  } else {
    if (n < 0) {
      *(str - 1) = '-';
    }
  }
}

static char *int_to_str(int n, char *base) {
  size_t base_size = strlen(base);
  if (base_size < 2 || base_size > INT_MAX) {
    errno = EINVAL;
    return NULL;
  }

  size_t size = int_to_str_size(n, 0, (int)base_size);
  char *str = malloc(size + 1);
  if (str == NULL) {
    return NULL;
  }

  str[size] = '\0';
  int_to_str_write(n, str + size - 1, base, (int)base_size);

  return str;
}

int main(void) {
  srand((unsigned int)time(NULL));

  for (uintmax_t i = 0; i < 42; i++) {
    int n = rand() % 2 ? rand() : -rand();

    char *str = int_to_str(n, "0123456789");
    if (str != NULL) {
      printf("%d == %s\n", n, str);

      free(str);
    } else {
      perror("int_to_str()");
    }
  }
}