16

I have an integer like 1191223 and I want to iterate over the digits. I am not sure how to do this in C, is there any easy way to do this?

Thanks.

thiton
  • 35,651
  • 4
  • 70
  • 100
topgun
  • 2,463
  • 8
  • 31
  • 46

9 Answers9

17

Forwards, or backwards?

Assuming a positive integer:

  unsigned int n = 1191223;

  while (n != 0) {
       doSomething (n % 10);
       n /= 10;
  }

…will work smallest to largest, or…

EDIT I'd forgotten all about this non-working solution I had here. Note that Very Smart People™ seem to use the smallest-to-largest iteration consistently (both Linux kernel and GLibC's printf, for example, just iterate backwards) but here's a lousy way to do it if you really don't want to use snprintf for some reason…

int left_to_right (unsigned int n) {
  unsigned int digit = 0;

  if (0 == n) {
    doSomething (0);
  } else {
    digit = pow(10, 1.0+ floor(log10(n)));
    while (digit /= 10) {
      doSomething ( (n / digit) % 10 );
    }
  }
}

I assume that it's very silly to assume that you have log10 and pow but not snprintf, so an alternate plan would be

int left_to_right_fixed_max (unsigned int n) {
  unsigned int digit = 1000000000; /* make this very big */
  unsigned int n10 = 10 * n;

  if (0 == n) {
    doSomething (0);
  } else {
    while (digit > n10) { digit /= 10; }
    while (digit /= 10) {
      doSomething ( (n / digit) % 10 );
    }
  }
}

… or, if you really don't have hardware multiply/divide, you can resort to using a table of powers of ten.

int left_to_right (unsigned int n) {
  static const unsigned int digit [] = 
    { 1,
      10,
      100,
      1000,
      10000,
      100000,
      1000000,
      10000000,
      100000000,
      1000000000 /* make this very big */
    };
  static const unsigned char max_place = 10;
  /* length of the above array */

  unsigned char decimal;
  unsigned char place;
  unsigned char significant = 0; /* boolean */

  if (0 == n) {
    doSomething (0);
  } else {
    place = max_place;
    while (place--) {
      decimal = 0;
      while (n >= digit[place]) {
        decimal++;
        n -= digit[place];
      }
      if (decimal | significant) {
        doSomething (decimal);
        significant |= decimal;
      }
    }
  }
}

…which I have adapted from http://www.piclist.com/techref/language/ccpp/convertbase.htm into a somewhat more general-purpose version.

BRPocock
  • 13,638
  • 3
  • 31
  • 50
  • your first version is from backwards to forwards, how you get the digits from forward and up like 1234 > 1 2 3 and then 4 rather 4 3 2 and 1.. thanks – topgun Dec 29 '11 at 21:34
  • the iteration works fine for forward but its skipping zero's, any idea why it be doing that? – topgun Dec 29 '11 at 22:09
  • 1
    Wow, I'm sure I made some stupid oversight -- I'll take a look tonight. :-( I foolishly only tried it with "1191123!" – BRPocock Dec 30 '11 at 00:29
  • Just curious, did you happen to solve with 0's for this? I have iterated through this many times, not sure what is causing 0 to be eliminated. – topgun Dec 30 '11 at 15:15
5

In the following I assume you mean decimal digits (base 10). Probably you are able to adapt the solutions to other numeral systems by substituting the 10s.

Note, that the modulo operation is a tricky thing concerning negative operands. Therefore I have chosen the data type to be an unsigned integer.

If you want to process the least significant digit first, you could try the following untested approach:

uint32_t n = 1191223;
do {
  uint32_t digit = n%10;
  // do something with digit
}
while (n/=10);

If you prefer to walk through the digits starting from the most significant digit, you could try to adapt the following untested code:

uint32_t n = 1191223;
#define MAX_DIGITS 10 // log10((double)UINT32_MAX)+1
uint32_t div = pow(10, MAX_DIGITS);

// skip the leading zero digits
while ( div && !(n/div) ) div/=10;
if ( !div ) div = 10; // allow n being zero

do {
  uint32_t digit = (n/div)%10;
  // do something with digit
}
while (div/=10);
moooeeeep
  • 31,622
  • 22
  • 98
  • 187
3

You want to iterate over base-10 digits, but an integer has no concept of arabic notation and digits. Convert it to a string first:

int i = 1191223;
char buffer[16];
char *j;
snprintf(buffer, 16, "%i", i);
for ( j = buffer; *j; ++j ) { /* digit is in *j - '0' */ }
thiton
  • 35,651
  • 4
  • 70
  • 100
  • thiton I am just curious what do you mean here by *j - '0', does it avoid the first 0? I was trying this with a digit of 0191223 and the length doesn't comes to be right, any suggestions? – topgun Dec 29 '11 at 19:58
  • 1
    @kforkarim probably that's the `char2int` conversion: `uint32_t digit = *j-'0';`. Make sure to handle the `'-'` the string may contain. – moooeeeep Dec 29 '11 at 20:06
2

Something like this:

char data[128];
int digits = 1191223;
sprintf(data, "%d", digits);
int length = strlen(data);
for(int i = 0; i < length; i++) {
   // iterate through each character representing a digit
}

Notice that if you use an octal number like 0100 you also need to change the sprintf(data, "%d", digits); to sprintf(data, "%o", digits);.

Cyclonecode
  • 29,115
  • 11
  • 72
  • 93
2

You can use sprintf() to convert it into a char array, and then iterate through that, like so (untested, just to get you started):

int a = 1191223;
char arr[16];
int rc = sprintf(arr, "%d", a);

if (rc < 0) {
    // error
}

for (int i = 0; i < rc; i++) {
    printf("digit %d = %d\n", i, arr[i]);
}
Dan Fego
  • 13,644
  • 6
  • 48
  • 59
2
void access_digits(int n)
{
        int digit;
        if (n < 0) n = -n;
        do {
                digit = n % 10;
                /* Here you can do whatever you
                   want to do with the digit */
        } while ((n/=10) > 0);
}
Sangeeth Saravanaraj
  • 16,027
  • 21
  • 69
  • 98
1

For my purposes the following short code did the trick.

Having a an integer variable the_integer, and an integer variable sum_of_digits initialized. (line 1) You could do the following:

1) Convert the integer variable to a variable of type string with use of the std::to_string(int) function.

2) Iterate of the characters of the resulting string. for(char& c: str::to_string(the_integer))

3) To convert the characters back to integers use c -'0' . For this solution take a look at the discussion in (Convert char to int in C and C++).

4) .. and adding them the digits together: sum_of_digits += c-'0'

*) you can then print your variables: lines 3 and 4.

int the_integer = 123456789; int sum_of_digits;

for (char& c: std::to_string(the_integer)) {sum_of_digits += c-'0';}

std::cout << "Integer: " << the_integer << std::endl;
std::cout << "Sum of Digits << sum_of_digits << std::endl;

Note that std::to_string() has some notes, please consult the c++ references to see if the code is still relevant for your purposes.

Nick
  • 26
  • 4
0

A hackish way is to convert this to string (see strtol) and then reconvert this to a number. you could use something like character you want - '0'

Alexander Oh
  • 24,223
  • 14
  • 73
  • 76
0

Off the top of my head: "i % 100000", "i % 100000", ...

A recursive solution would let you start from "i%10".

paulsm4
  • 114,292
  • 17
  • 138
  • 190