web-dev-qa-db-fra.com

Obtenir chaque chiffre individuel à partir d'un entier entier

Disons que j'ai un entier appelé "score", qui ressemble à ceci:

int score = 1529587;

Maintenant, ce que je veux faire, c'est obtenir chaque chiffre 1, 5, 2, 9, 5, 8, 7 du score à l'aide d'opérateurs au niveau du bit(Voir ci-dessous la note d'édition).

Je suis presque sûr que cela peut être fait car j'ai déjà utilisé une méthode similaire pour extraire les valeurs rouge vert et bleu d'une valeur de couleur hexadécimale.

Comment pourrais-je faire ça?

Modifier
Il ne doit pas nécessairement s'agir d'opérateurs au niveau du bit, je pensais simplement que ce serait plus simple de cette façon.

21
Johannes Jensen

Vous utilisez l'opérateur modulo:

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

Notez que cela vous donnera les chiffres dans l'ordre inverse (c'est-à-dire le chiffre le moins significatif en premier). Si vous voulez d'abord le chiffre le plus significatif, vous devrez stocker les chiffres dans un tableau, puis les lire dans l'ordre inverse.

40
Martin B

D'accord avec les réponses précédentes.

Une petite correction: il y a une meilleure façon d'imprimer les chiffres décimaux de gauche à droite, sans allouer de tampon supplémentaire. De plus, vous souhaiterez peut-être afficher un caractère zéro si le score est 0 (la boucle suggérée dans les réponses précédentes ne s'imprimera pas).

Cela nécessite un laissez-passer supplémentaire:

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

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

Les valeurs RVB tombent bien sur les limites des bits; les chiffres décimaux ne le font pas. Je ne pense pas qu'il existe un moyen facile de le faire en utilisant des opérateurs au niveau du bit. Vous devez utiliser des opérateurs décimaux comme modulo 10 (% 10).

4
David M

Ne réinventez pas la roue. C a sprintf pour une raison. Étant donné que votre variable est appelée score, je suppose que c'est pour un jeu où vous prévoyez d'utiliser les chiffres individuels de la partition pour afficher les glyphes numériques sous forme d'images. Dans ce cas, sprintf a des modificateurs de format pratiques qui vous permettront de mettre à zéro, à espace, etc. la partition à une largeur fixe, que vous voudrez peut-être utiliser.

2
R..

Cette solution donne des résultats corrects sur toute la plage [0, UINT_MAX] sans nécessiter la mise en mémoire tampon des chiffres.

Il fonctionne également pour les types plus larges ou les types signés (avec des valeurs positives) avec des changements de type appropriés.

Ce type d'approche est particulièrement utile sur des environnements minuscules (par exemple, le chargeur de démarrage Arduino) car il ne finit pas par tirer tous les ballonnements printf () (lorsque printf () n'est pas utilisé pour la sortie de démonstration) et utilise très peu de RAM. Vous pouvez obtenir un aperçu de la valeur simplement en faisant clignoter une seule 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;
}
1
Britton Kerin
#include<stdio.h>

int main() {
int num; //given integer
int reminder;
int rev=0; //To reverse the given integer
int count=1;

printf("Enter the integer:");
scanf("%i",&num);

/*First while loop will reverse the number*/
while(num!=0)
{
    reminder=num%10;
    rev=rev*10+reminder;
    num/=10;
}
/*Second while loop will give the number from left to right*/
while(rev!=0)
{
    reminder=rev%10;
    printf("The %d digit is %d\n",count, reminder);
    rev/=10;
    count++; //to give the number from left to right 
}
return (EXIT_SUCCESS);}
0
RohitK
//this can be easily understandable for beginners     
int score=12344534;
int div;
for (div = 1; div <= score; div *= 10)
{

}
/*for (div = 1; div <= score; div *= 10); for loop with semicolon or empty body is same*/
while(score>0)
{
    div /= 10;
    printf("%d\n`enter code here`", score / div);
    score %= div;
}
0
Esann

Habituellement, ce problème se résout à utiliser le modulo d'un nombre dans une boucle ou à convertir un nombre en chaîne. Pour convertir un nombre en chaîne, vous pouvez utiliser la fonction itoa , donc en considérant la variante avec le modulo d'un nombre dans une boucle.


Contenu d'un fichier 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);
}

Démo avec le 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]

Démo avec le 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]

Environnement de test

$~/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
0
Seti Volkylany