-3

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;
}
Paweł Dymowski
  • 840
  • 7
  • 14
  • 1
    if your code is working, please consider posting it in [codereview.se]. – Sourav Ghosh Jan 04 '17 at 10:32
  • 1
    What is your actual question? Are you looking for a [Code Review](https://codereview.stackexchange.com/)? – Hermann Döppes Jan 04 '17 at 10:32
  • `char` **is** an integer type. So just: `int i = 42; char c = (char)i;` – too honest for this site Jan 04 '17 at 10:35
  • 2
    You don't seem to grasp the difference between a pointer and the thing it points too, like in this fragment `*myString = *(myString - i); //move pointer back to the beggining of string`. There are other small problems but you have to fix this one first. – n. m. could be an AI Jan 04 '17 at 10:36
  • my code is not working, its just idea, my question is: Howto Convert Integer to Char array, taking digit by digit and puting it to dynamic char array using pointers – Paweł Dymowski Jan 04 '17 at 10:37
  • whats wrong with: *myString = *(myString - i); if pointer points to lest say myString[5], I want to "reset" it that it points back to myString[0] – Paweł Dymowski Jan 04 '17 at 10:41
  • 1
    What's wrong with it is that you are not moving any pointers. `*myString` is not a pointer, and indeed one line above you are using the exact same expression `*myString` to manipulate a character. How could one and the same `*myString` be both a pointer and a character? – n. m. could be an AI Jan 04 '17 at 10:45
  • By the way if you need to talk to a specific user, use the @ convention. – n. m. could be an AI Jan 04 '17 at 10:48
  • 1
    If you know the number (along with its base) to be converted you can immediately derive from it the number of characters you need to allocate. Hint: Read about the Logarithm function. – alk Jan 04 '17 at 11:00
  • Even if you can't use the log function, you can work out the number of digits before allocating the char buffer by repeatedly dividing a copy of the number by 10 while it is non-zero (but you'll need to treat 0 as a special case, and allocate an extra char for the '-' if necessary). This also makes it easy to construct the string with the digits not in reverse order. – Ian Abbott Jan 04 '17 at 11:17
  • "*by repeatedly dividing a copy of the number by 10*" or what ever the base in question would be. `16` for displaying `0x4D2` for example. – alk Jan 04 '17 at 11:33
  • @alk I know there are easier ways, but I`m currently learning about pointers and dynamic allocation, and my task is to do it specifically that way (allocate space for every new char) – Paweł Dymowski Jan 04 '17 at 11:35
  • Please don't change your question significantly after comments/answer had been given, as this might render the latter un-understandbale. I just rolled back your last edit therefore. – alk Jan 04 '17 at 11:38
  • *Add* "changes* as updates to your question. – alk Jan 04 '17 at 11:39
  • You cannot call `realloc` and pass it a pointer to the *middle* of the allocated string. You always need to keep a pointer to the beginning of the string (but then when you realloc, the pointer to the middle becomes invalid, so you have to do something about it). Also, you are trying to realloc when you add a digit, but not when you add a minus sign. – n. m. could be an AI Jan 04 '17 at 12:59
  • Thanks @n.m. that was helpful, I fixed my code :) – Paweł Dymowski Jan 04 '17 at 13:30
  • try `int myNumber = -1234;` – BLUEPIXY Jan 04 '17 at 13:33
  • @BLUEPIXY thanks, I need to fix that – Paweł Dymowski Jan 04 '17 at 13:38
  • Voting to close because this question has already been posted to Code Review: http://codereview.stackexchange.com/questions/151711/converting-integer-to-dynamically-allocated-char-array-digit-by-digit-using-poi – Cody Gray - on strike Jan 05 '17 at 10:08

1 Answers1

0

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()");
    }
  }
}
Stargateur
  • 24,473
  • 8
  • 65
  • 91