Nehmen wir an, ich habe eine Ganzzahl namens “score”, die so aussieht:
int score = 1529587;
Jetzt möchte ich jede Ziffer 1, 5, 2, 9, 5, 8, 7 aus der Partitur erhalten mit bitweisen Operatoren(Siehe unten Bearbeitungshinweis).
Ich bin mir ziemlich sicher, dass dies möglich ist, da ich einmal eine ähnliche Methode verwendet habe, um die roten, grünen und blauen Werte aus einem hexadezimalen Farbwert zu extrahieren.
Wie würde ich das tun?
Bearbeiten
Es müssen nicht unbedingt bitweise Operatoren sein, ich dachte nur, dass es so einfacher wäre.
Sie verwenden den Modulo-Operator:
while(score)
{
printf("%d\n", score % 10);
score /= 10;
}
Beachten Sie, dass Sie dadurch die Ziffern in umgekehrter Reihenfolge erhalten (dh die niedrigstwertige Ziffer zuerst). Wenn Sie die höchstwertige Ziffer zuerst wollen, müssen Sie die Ziffern in einem Array speichern und sie dann in umgekehrter Reihenfolge auslesen.
RGB-Werte fallen gut auf Bitgrenzen; Dezimalziffern nicht. Ich glaube nicht, dass es eine einfache Möglichkeit gibt, dies mit bitweisen Operatoren zu tun. Sie müssten Dezimaloperatoren wie Modulo 10 (% 10) verwenden.
Stimme den vorherigen Antworten zu.
Eine kleine Korrektur: Es gibt einen besseren Weg, die Dezimalziffern von links nach rechts zu drucken, ohne zusätzlichen Puffer zuzuweisen. Außerdem möchten Sie möglicherweise ein Nullzeichen anzeigen, wenn die score
ist 0 (die in den vorherigen Antworten vorgeschlagene Schleife druckt nichts).
Dies erfordert einen zusätzlichen Pass:
int div;
for (div = 1; div <= score; div *= 10)
;
do
{
div /= 10;
printf("%d\n", score / div);
score %= div;
} while (score);
Erfinden Sie das Rad nicht neu. C hat sprintf
aus einem Grund.
Da Ihre Variable Punktzahl heißt, schätze ich, dass dies für ein Spiel gilt, bei dem Sie die einzelnen Ziffern der Punktzahl verwenden möchten, um die numerischen Glyphen als Bilder anzuzeigen. In diesem Fall, sprintf
verfügt über praktische Formatmodifikatoren, mit denen Sie die Partitur mit Nullen, Leerzeichen usw. auf eine feste Breite setzen können, die Sie möglicherweise verwenden möchten.
Diese Lösung liefert über den gesamten Bereich korrekte Ergebnisse [0,UINT_MAX]
ohne dass Ziffern gepuffert werden müssen.
Es funktioniert auch für breitere Typen oder vorzeichenbehaftete Typen (mit positiven Werten) mit entsprechenden Typänderungen.
Diese Art von Ansatz ist besonders nützlich in winzigen Umgebungen (z. B. Arduino-Bootloader), da es nicht dazu führt, dass das gesamte printf()-Bloat (wenn printf() nicht für die Demoausgabe verwendet wird) gezogen wird und sehr wenig RAM verwendet wird. Sie können den Wert sehen, indem Sie einfach eine einzelne LED blinken lassen 🙂
#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;
}
Normalerweise lässt sich dieses Problem lösen, indem das Modulo einer Zahl in einer Schleife verwendet oder eine Zahl in eine Zeichenfolge konvertiert wird. Um eine Zahl in eine Zeichenfolge umzuwandeln, können Sie die Funktion verwenden Itoabetrachtet also die Variante mit dem Modulo einer Zahl in einer Schleife.
Inhalt einer Datei 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 mit dem 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 mit 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]
Testumgebung
$~/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
#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);}
Da ich es in meinem persönlichen Bitoperator-Kompendium nicht gefunden habe (graphics.stanford.edu/~seander/bithacks.html), glaube ich nicht, dass dies ohne eine tiefere Ausarbeitung möglich ist.
– phimuemue
25. Juni 2010 um 13:49 Uhr
Wenn sie dezimal sind, können Sie sie nicht bitweise abrufen. wenn sie hexadezimal sind, dann ist es möglich. bitte angeben.
– Andrej
25. Juni 2010 um 13:52 Uhr