Iterando a través de dígitos en enteros en C

5 minutos de lectura

avatar de usuario de topgun
topgun

Tengo un número entero como 1191223 y quiero iterar sobre los dígitos. No estoy seguro de cómo hacer esto en C, ¿hay alguna manera fácil de hacerlo?

Gracias.

Avatar de usuario de BRPocock
BRPocock

¿Hacia adelante o hacia atrás?

Suponiendo un entero positivo:

  unsigned int n = 1191223;

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

…funcionará de menor a mayor, o…

EDITAR Había olvidado todo sobre esta solución que no funcionaba que tenía aquí. Tenga en cuenta que Very Smart People™ parece usar la iteración de menor a mayor de manera constante (tanto el kernel de Linux como el de GLibC). printfpor ejemplo, solo iterar hacia atrás) pero aquí hay una forma pésima de hacerlo si realmente no quieres usar snprintf por alguna razón…

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 );
    }
  }
}

Supongo que es muy tonto suponer que tienes log10 y pow pero no snprintfpor lo que un plan alternativo sería

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 );
    }
  }
}

… o, si realmente no tienes hardware para multiplicar/dividir, puedes recurrir al uso de una tabla de potencias de diez.

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;
      }
    }
  }
}

…que he adaptado de http://www.piclist.com/techref/language/ccpp/convertbase.htm en una versión algo más de propósito general.

  • su primera versión es de atrás hacia adelante, cómo obtiene los dígitos de adelante hacia arriba como 1234> 1 2 3 y luego 4 en lugar de 4 3 2 y 1 … gracias

    – topgun

    29 de diciembre de 2011 a las 21:34

  • la iteración funciona bien para adelante, pero se salta los ceros, ¿alguna idea de por qué está haciendo eso?

    – topgun

    29 de diciembre de 2011 a las 22:09

  • Wow, estoy seguro de que cometí un estúpido descuido. Le echaré un vistazo esta noche. 🙁 ¡Tontamente solo lo intenté con “1191123!”

    – BRPocock

    30 de diciembre de 2011 a las 0:29

  • Solo por curiosidad, ¿resolviste esto con 0? He repetido esto muchas veces, no estoy seguro de qué está causando que 0 sea eliminado.

    – topgun

    30 de diciembre de 2011 a las 15:15

avatar de usuario de moooeeeep
moooeeeeep

En lo siguiente, supongo que te refieres a dígitos decimales (base 10). Probablemente puedas adaptar las soluciones a otros sistemas numéricos sustituyendo el 10s.

Tenga en cuenta que la operación de módulo es algo complicado con respecto a los operandos negativos. Por lo tanto, he elegido que el tipo de datos sea un entero sin signo.

Si desea procesar primero el dígito menos significativo, puede probar el siguiente enfoque no probado:

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

Si prefiere recorrer los dígitos a partir del dígito más significativo, puede intentar adaptar el siguiente código no probado:

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);

Desea iterar sobre dígitos de base 10, pero un número entero no tiene concepto de notación árabe y dígitos. Conviértalo en una cadena primero:

int i = 1191223;
char buffer[16];
char *j;
snprintf(buffer, 16, "%i", i);
for ( j = buffer; *j; ++j ) { /* digit is in *j - '0' */ }

  • thiton Solo tengo curiosidad, ¿qué quiere decir aquí con *j – ‘0’, evita el primer 0? Estaba probando esto con un dígito de 0191223 y la longitud no llega a ser la correcta, ¿alguna sugerencia?

    – topgun

    29 de diciembre de 2011 a las 19:58

  • @kforkarim probablemente ese sea el char2int conversión: uint32_t digit = *j-'0';. Asegúrese de manejar el '-' la cadena puede contener.

    – mooooooooooooooooooooooo

    29 de diciembre de 2011 a las 20:06


Puedes usar sprintf() para convertirlo en un char matriz, y luego iterar a través de eso, así (no probado, solo para comenzar):

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]);
}

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);
}

Algo como esto:

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
}

Note que si usa un número octal como 0100 también tienes que cambiar el sprintf(data, "%d", digits); a sprintf(data, "%o", digits);.

Para mis propósitos, el siguiente código corto funcionó.

Tener una variable entera el_enteroy una variable entera suma_de_digitos inicializado (línea 1) Podrías hacer lo siguiente:

1) Convierta la variable entera en una variable de tipo cadena con el uso de la std::a_cadena(int) función.

2) Iterar los caracteres de la cadena resultante. for(char& c: str::to_string(the_integer))

3) Para volver a convertir los caracteres en números enteros, utilice c-‘0’ . Para esta solución, eche un vistazo a la discusión en (Convertir char a int en C y C++).

4) .. y sumándoles los dígitos: suma_de_digitos += c-‘0’

*) luego puede imprimir sus variables: líneas 3 y 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;

Tenga en cuenta que std::a_cadena() tiene algunas notas, consulte las referencias de C++ para ver si el código sigue siendo relevante para sus propósitos.

  • Describa lo que está haciendo su código en su respuesta.

    – CtrlS

    20 de marzo de 2019 a las 17:29

¿Ha sido útil esta solución?