11

I am trying to convert an integer number in C into an array containing each of that number's digits

i.e. if I have

int number = 5400

how can I get to

int numberArray[4]

where

numberArray[0] = 0;
numberArray[1] = 0;
numberArray[2] = 4;
numberArray[3] = 5;

Any suggestions gratefully received.

user6123979
  • 209
  • 5
  • 13
droseman
  • 277
  • 3
  • 5
  • 12

8 Answers8

15

Hint: Take a look at this earlier question "Sum of digits in C#". It explains how to extract the digits in the number using several methods, some relevant in C.

From Greg Hewgill's answer:

/* count number of digits */
int c = 0; /* digit position */
int n = number;

while (n != 0)
{
    n /= 10;
    c++;
}

int numberArray[c];

c = 0;    
n = number;

/* extract each digit */
while (n != 0)
{
    numberArray[c] = n % 10;
    n /= 10;
    c++;
}
Community
  • 1
  • 1
Zach Scrivena
  • 29,073
  • 11
  • 63
  • 73
15

This would work for numbers >= 0

#include <math.h>

char * convertNumberIntoArray(unsigned int number) {
    int length = (int)floor(log10((float)number)) + 1;
    char * arr = new char[length];
    int i = 0;
    do {
        arr[i] = number % 10;
        number /= 10;
        i++;
    } while (number != 0);
    return arr;
}

EDIT: Just a little bit more C style but more cryptic.

#include <math.h>

char * convertNumberIntoArray(unsigned int number) {
    unsigned int length = (int)(log10((float)number)) + 1;
    char * arr = (char *) malloc(length * sizeof(char)), * curr = arr;
    do {
        *curr++ = number % 10;
        number /= 10;
    } while (number != 0);
    return arr;
}
vava
  • 24,851
  • 11
  • 64
  • 79
  • why is this function a char pointer ? And what does new char[length] do? It looks like a pointer to the first index of the array, but my compiler doesn't seem to like 'new char' – droseman Feb 05 '09 at 15:36
  • 'new char' is C++speak. The proper way to do it in C is the second bit of code. – Chris Lutz Feb 05 '09 at 15:46
  • Also, it's important that, at the end of your program, you call `free()` on whatever array you got back from this function. Otherwise you leak memory. – Chris Lutz Feb 05 '09 at 15:53
  • 1
    Shouldn't this be returning int *? – Nick Presta Feb 05 '09 at 15:53
  • It might but there's no reason to use 4 byte int to store 4 bit digit. Char is just more compact way to do that, although it could easily be substituted to ints. – vava Feb 06 '09 at 00:25
7

You could calculate the number of digits in an integer with logarithm rather than a loop. Thus,

int * toArray(int number)
{
    int n = log10(number) + 1;
    int i;
    int *numberArray = calloc(n, sizeof(int));
    for ( i = 0; i < n; ++i, number /= 10 )
    {
        numberArray[i] = number % 10;
    }
    return numberArray;
}
Christoffer
  • 12,712
  • 7
  • 37
  • 53
2

Try this,

void initialise_array(int *a, int size, int num) {
    for (int i = 0; i < size; ++i, num /= 10)
        a[(size - 1) - i] = num % 10;
}
1

If you need to take negative numbers into account, you might need some extra logic. In fact, when playing around with arrays you don't know the size of upfront, you may want to do some more safety checking, and adding an API for handling the structure of the data is quite handy too.

// returns the number of digits converted
// stores the digits in reverse order (smalles digit first)
// precondition: outputdigits is big enough to store all digits.
//
int convert( int number, int* outputdigits, int* signdigit ) {

  int* workingdigits = outputdigits;

  int sign = 1;
  if( number < 0 ) { *signdigit = -1; number *= -1; }
  ++workingdigits;

  for ( ; number > 0; ++ workingdigits ) {
    *workingdigits = number % 10;
    number = number / 10;
  }

  return workingdigits - outputdigits;
}

void printdigits( int* digits, int size, int signdigit ) {
  if( signdigit < 0 ) printf( "-" );

  for( int* digit = digits+size-1; digit >= digits; --digit ){
    printf( "%d", *digit );
  }
}

int main() {
   int digits[10];
   int signdigit;
   printdigits( digits, convert( 10, digits, &signdigit ), signdigit );
   printdigits( digits, convert( -10, digits, &signdigit ), signdigit );
   printdigits( digits, convert( 1005, digits, &signdigit ), signdigit );

}
xtofl
  • 40,723
  • 12
  • 105
  • 192
  • no negative numbers required, fortunately. Its an upcounting hours counter. It is possible that this number could get quite large, though. – droseman Feb 05 '09 at 13:50
1
#include <stdio.h>
#include <string.h>

int main(void)
{
  int i, inputNumber;
  char* charArray;

  printf("\nEnter number: ");
  scanf("%d", &inputNumber);

  /* converts int to print buffer which is char array */
  sprintf(charArray, "%d", inputNumber); 
  int size = strlen(charArray);

  int intArray[size];

  for (i = 0; i < size; i++)
  {
    intArray[i] = charArray[i] - '0';
  }

  return 0;
}
Praveen Manupati
  • 434
  • 1
  • 6
  • 12
0

C code:

/* one decimal digit takes a few more than 3 bits. (2^3=8, 2^4=16) */
int digits[(sizeof (int) * CHAR_BIT) / 3 + 1], 
    *digitsp = digits;
do {
    *digitsp++ = number % 10;
    number /= 10;
} while(number > 0);

You will see how many digits you converted by taking the difference

digitsp - digits

If you want to put it into a function:

#define MIN_DIGITS_IN_INT ((sizeof (int) * CHAR_BIT) / 3 + 1)

int to_array(int number, int *digits) {
    int *digitsp = digits;
    do {
        *digitsp++ = number % 10;
        number /= 10;
    } while(number > 0);
    return digitsp - digits;
}

int main() {
    int number = rand();
    int digits[MIN_DIGITS_IN_INT];
    int n = to_array(number, digits);

    /* test whether we're right */
    while(n-- > 0) 
        printf("%d", digits[n]);
    }
    printf(" = %d\n", number);
}

I prefer automatic arrays to dynamic memory allocation in this case, since it's easier to do it right and not leak accidentally.

Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • "A bit more than 3 bits?" I think you just won some kind of phrasing prize. – unwind Feb 05 '09 at 12:34
  • yeah, i figure it sounds strange oO let me change it – Johannes Schaub - litb Feb 05 '09 at 12:35
  • Awesome how different logic path produces the same results :) 32 / 3 + 1 is almost the same as log10(2 ** 32) + 1 == log2(2 ** 32) / log2(10) + 1 == 32 / log2(10) + 1 < 32 / 3 + 1 – vava Feb 05 '09 at 13:06
  • can u explain MIN_DIGITS_IN_INT ((sizeof (int) * CHAR_BIT) / 3 + 1) ? – yesraaj Feb 05 '09 at 15:42
  • rajKumar, it needs to be a compile time constant. so i didn't use log10. you need 3.32193 bits to store one decimal place (ld(10)) - ten binary decisions. that means, that you cannot store more than (sizeof (int) * CHAR_BIT)/3.32193 places in an int, which is 9.63296 – Johannes Schaub - litb Feb 05 '09 at 19:09
  • (here). round up (INT_MAX does not really use all places fully - it's not 9999999999) it's 10 which is also actually the amount of digits in an INT_MAX. well, actually that calcs the places in an unsigned int. but those are always at least as many as places for an int. so that works indeed :) – Johannes Schaub - litb Feb 05 '09 at 19:17
0

using vadim's code, I came up with this test program:

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

char * convertNumberIntoArray(unsigned int number) {
    unsigned int length = (int)(log10((float)number)) + 1;
    char * arr = (char *) malloc(length * sizeof(char)), * curr = arr;
    do {
        *curr++ = number % 10;
        number /= 10;
    } while (number != 0);
    return arr;
}



int main(void)
{
    int InputNumber;
    int arr[5];

    printf("enter number: \n");
    scanf("%d", &InputNumber);

    convertNumberIntoArray(InputNumber);

    printf("The number components are: %d %d %d\n", arr[0],arr[1],arr[2]);

    system("PAUSE");    
    return 0;
}

but the output is garbage. Can anyone advise if I have done something stupid here?

/***** output *****/
enter number:
501
The number components are: 2009291924 2009145456 -1
Press any key to continue . . .

--dave

droseman
  • 277
  • 3
  • 5
  • 12
  • The function returns an array. You need this: `char *arr; arr = convertNumberIntoArray(InputNumber);` Note that `arr` should be a `char *`, not an `int []`. If you want it to be an `int *`, you should change the function to return `int *`, not `char *`. – Chris Lutz Feb 05 '09 at 15:56
  • don't forget to free(arr) after you are done with it. Alternatively, you can use @litb approach and create static array with length (32/3 + 1) == 11 and just fill it in then. – vava Feb 06 '09 at 00:31