2010-06-25 15 views
17

Digamos que tengo un entero llamado 'puntuación', que se ve así:Conseguir cada dígito individuo de un número entero

int score = 1529587; 

Ahora lo que quiero hacer es conseguir cada dígito 1, 5, 2, 9, 5, 8, 7 del puntaje usando los operadores bit a bit (vea la nota de edición a continuación).

Estoy bastante seguro de que esto se puede hacer ya que una vez utilicé un método similar para extraer los valores rojos, verdes y azules de un valor de color hexadecimal.

¿Cómo podría hacer esto?

Editar
No necesariamente tiene que ser en modo bit operadores, sólo pensé que sería más fácil de esa manera.

+1

Dado que no he encontrado en mi compendio operador de poco personal (http://graphics.stanford.edu/~seander/bithacks.html), No creo que esto sea posible sin una elaboración más profunda. – phimuemue

+0

si son decimales, no puede obtenerlos usando bitwise. si son hexadecimales, entonces es posible. Por favor especifica. – Andrey

Respuesta

32

se utiliza el operador de módulo:

while(score) 
{ 
    printf("%d\n", score % 10); 
    score /= 10; 
} 

Tenga en cuenta que esto le dará los dígitos en orden inverso (es decir dígito menos significativo en primer lugar). Si desea primero el dígito más significativo, deberá almacenar los dígitos en una matriz y luego leerlos en orden inverso.

+0

Estoy bastante seguro de que modulo no es un operador bit a bit –

+1

@ Scorpi0: No, no lo es ... pero no hay una forma sensata de hacerlo con operadores bit a bit, y creo que esto es lo que el OP estaba buscando. –

+0

creo que OP significa hexadecimal y es posible resolverlo en bit. – Andrey

4

Los valores RGB se ajustan bien en los límites de bits; los dígitos decimales no. No creo que haya una manera fácil de hacerlo utilizando operadores bit a bit. Necesitarías usar operadores decimales como módulo 10 (% 10).

+1

+1 Tiene razón, los números decimales (base 10) no se dividen en bits (base 2), excepto para los números que son potencias de 2 (como 256 = 2^8 para los colores). Como 10 no es una potencia de 2, no podrá usar operadores bit a bit. – Geoff

4

De acuerdo con respuestas anteriores.

Una pequeña corrección: hay una mejor manera de imprimir los dígitos decimales de izquierda a derecha, sin asignar memoria extra. Además, es posible que desee mostrar una characeter cero si score es 0 (el ciclo sugerido en las respuestas anteriores no imprimirá ninguna).

Esto exige una pasada adicional:

int div; 
for (div = 1; div <= score; div *= 10) 
    ; 

do 
{ 
    div /= 10; 
    printf("%d\n", score/div); 
    score %= div; 
} while (score); 
+1

Esta solución causa una división por cero cuando 'puntaje 'es cero. – Shepmaster

+0

Esta solución también falla debido al desbordamiento cuando la puntuación> = ceil (INT_MAX/10.0). He proporcionado una solución que funciona la corrección para todo el rango [0, UINT_MAX]. –

+0

Esta solución también falla para cualquier número con 0 dígitos en la posición o posiciones menos significativas. Esos ceros no están impresos. La solución corregida que he proporcionado también evita este problema. –

2

No reinventar la rueda. C tiene sprintf por una razón. Como su variable se llama puntaje, supongo que esto es para un juego en el que planea usar los dígitos individuales del puntaje para mostrar los glifos numerales como imágenes. En este caso, sprintf tiene modificadores de formato convenientes que le permiten cero-pad, espacio-almohadilla, etc. la puntuación a un ancho fijo, que es posible que desee utilizar.

+0

Me gusta cómo analizaste EXACTAMENTE para qué iba a usarlo ¡Muchas gracias! –

0

Normalmente, este problema se resuelve con el uso del módulo de un número en un bucle o convierte un número en una cadena. Para convertir un número en una cadena, puede usar la función itoa, por lo que considera la variante con el módulo de un número en un bucle.


contenido de un archivo get_digits.c

$ cat get_digits.c 

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


// return a length of integer 
unsigned long int get_number_count_digits(long int number); 

// get digits from an integer number into an array 
int number_get_digits(long int number, int **digits, unsigned int *len); 

// for demo features 
void demo_number_get_digits(long int number); 


int 
main() 
{ 
    demo_number_get_digits(-9999999999999); 
    demo_number_get_digits(-10000000000); 
    demo_number_get_digits(-1000); 
    demo_number_get_digits(-9); 
    demo_number_get_digits(0); 
    demo_number_get_digits(9); 
    demo_number_get_digits(1000); 
    demo_number_get_digits(10000000000); 
    demo_number_get_digits(9999999999999); 
    return EXIT_SUCCESS; 
} 


unsigned long int 
get_number_count_digits(long int number) 
{ 
    if (number < 0) 
     number = llabs(number); 
    else if (number == 0) 
     return 1; 

    if (number < 999999999999997) 
     return floor(log10(number)) + 1; 

    unsigned long int count = 0; 
    while (number > 0) { 
     ++count; 
     number /= 10; 
    } 
    return count; 
} 


int 
number_get_digits(long int number, int **digits, unsigned int *len) 
{ 
    number = labs(number); 

    // termination count digits and size of a array as well as 
    *len = get_number_count_digits(number); 

    *digits = realloc(*digits, *len * sizeof(int)); 

    // fill up the array 
    unsigned int index = 0; 
    while (number > 0) { 
     (*digits)[index] = (int)(number % 10); 
     number /= 10; 
     ++index; 
    } 

    // reverse the array 
    unsigned long int i = 0, half_len = (*len/2); 
    int swap; 
    while (i < half_len) { 
     swap = (*digits)[i]; 
     (*digits)[i] = (*digits)[*len - i - 1]; 
     (*digits)[*len - i - 1] = swap; 
     ++i; 
    } 

    return 0; 
} 


void 
demo_number_get_digits(long int number) 
{ 
    int *digits; 
    unsigned int len; 

    digits = malloc(sizeof(int)); 

    number_get_digits(number, &digits, &len); 

    printf("%ld --> [", number); 
    for (unsigned int i = 0; i < len; ++i) { 
     if (i == len - 1) 
      printf("%d", digits[i]); 
     else 
      printf("%d, ", digits[i]); 
    } 
    printf("]\n"); 

    free(digits); 
} 

demo con la GNU GCC

$~/Downloads/temp$ cc -Wall -Wextra -std=c11 -o run get_digits.c -lm 
$~/Downloads/temp$ ./run 
-9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9] 
-10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 
-1000 --> [1, 0, 0, 0] 
-9 --> [9] 
0 --> [0] 
9 --> [9] 
1000 --> [1, 0, 0, 0] 
10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 
9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9] 

demo con el LLVM/Clang

$~/Downloads/temp$ rm run 
$~/Downloads/temp$ clang -std=c11 -Wall -Wextra get_digits.c -o run -lm 
setivolkylany$~/Downloads/temp$ ./run 
-9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9] 
-10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 
-1000 --> [1, 0, 0, 0] 
-9 --> [9] 
0 --> [0] 
9 --> [9] 
1000 --> [1, 0, 0, 0] 
10000000000 --> [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 
9999999999999 --> [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9] 

entorno de pruebas

$~/Downloads/temp$ cc --version | head -n 1 
cc (Debian 4.9.2-10) 4.9.2 
$~/Downloads/temp$ clang --version 
Debian clang version 3.5.0-10 (tags/RELEASE_350/final) (based on LLVM 3.5.0) 
Target: x86_64-pc-linux-gnu 
Thread model: posix 
1

Esta solución da resultados correctos en toda la gama [0, UINT_MAX] sin necesidad de dígitos a ser tamponada.

También funciona para tipos más amplios o tipos firmados (con valores positivos) con los cambios de tipo apropiados.

Este tipo de enfoque es particularmente útil en entornos pequeños (por ejemplo Arduino bootloader) porque no termina tirando de todo el inflado printf() cuando printf() no se usa para la salida de demostración. poca RAM Puede echar un vistazo a su valor justo mediante el parpadeo de un LED :)

#include <limits.h> 
#include <stdio.h> 

int 
main (void) 
{ 
    unsigned int score = 42; // Works for score in [0, UINT_MAX] 

    printf ("score via printf:  %u\n", score); // For validation 

    printf ("score digit by digit: "); 
    unsigned int div = 1; 
    unsigned int digit_count = 1; 
    while (div <= score/10) { 
    digit_count++; 
    div *= 10; 
    } 
    while (digit_count > 0) { 
    printf ("%d", score/div); 
    score %= div; 
    div /= 10; 
    digit_count--; 
    } 
    printf ("\n"); 

    return 0; 
} 
Cuestiones relacionadas