简体   繁体   English

从整个整数中获取每个单独的数字

[英]Getting each individual digit from a whole integer

Let's say I have an integer called 'score', that looks like this:假设我有一个名为“score”的整数,它看起来像这样:

int score = 1529587;

Now what I want to do is get each digit 1, 5, 2, 9, 5, 8, 7 from the score using bitwise operators (See below edit note).现在我想要做的是 使用按位运算符 从分数中获取每个数字 1, 5, 2, 9, 5, 8, 7 (见下面的编辑说明)。

I'm pretty sure this can be done since I've once used a similar method to extract the red green and blue values from a hexadecimal colour value.我很确定这是可以做到的,因为我曾经使用过类似的方法从十六进制颜色值中提取红色绿色和蓝色值。

How would I do this?我该怎么做?

Edit编辑
It doesn't necessarily have to be bitwise operators, I just thought it'd be simpler that way.它不一定必须是按位运算符,我只是认为那样会更简单。

You use the modulo operator:您使用模运算符:

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

Note that this will give you the digits in reverse order (ie least significant digit first).请注意,这将以相反的顺序为您提供数字(即最低有效数字在前)。 If you want the most significant digit first, you'll have to store the digits in an array, then read them out in reverse order.如果您首先想要最重要的数字,则必须将数字存储在数组中,然后以相反的顺序读出它们。

RGB values fall nicely on bit boundaries; RGB 值很好地落在位边界上; decimal digits don't.十进制数字没有。 I don't think there's an easy way to do this using bitwise operators at all.我认为根本没有使用按位运算符的简单方法来做到这一点。 You'd need to use decimal operators like modulo 10 (% 10).您需要使用像模 10 (% 10) 这样的十进制运算符。

Agree with previous answers.同意之前的回答。

A little correction: There's a better way to print the decimal digits from left to right, without allocating extra buffer.一点更正:有一种更好的方法可以从左到右打印十进制数字,而无需分配额外的缓冲区。 In addition you may want to display a zero characeter if the score is 0 (the loop suggested in the previous answers won't print anythng).此外,如果score为 0,您可能希望显示零字符(先前答案中建议的循环不会打印任何内容)。

This demands an additional pass:这需要额外的通行证:

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

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

Don't reinvent the wheel.不要重新发明轮子。 C has sprintf for a reason. C 有sprintf是有原因的。

Since your variable is called score, I'm guessing this is for a game where you're planning to use the individual digits of the score to display the numeral glyphs as images.由于您的变量称为分数,我猜这适用于您计划使用分数的各个数字将数字字形显示为图像的游戏。 In this case, sprintf has convenient format modifiers that will let you zero-pad, space-pad, etc. the score to a fixed width, which you may want to use.在这种情况下, sprintf具有方便的格式修饰符,可以让您零填充、空格填充等将分数设置为固定宽度,您可能想要使用它。

This solution gives correct results over the entire range [0,UINT_MAX] without requiring digits to be buffered.此解决方案可在整个范围 [0,UINT_MAX] 内提供正确结果,而无需缓冲数字。

It also works for wider types or signed types (with positive values) with appropriate type changes.它也适用于具有适当类型更改的更宽类型或带符号类型(具有正值)。

This kind of approach is particularly useful on tiny environments (eg Arduino bootloader) because it doesn't end up pulling in all the printf() bloat (when printf() isn't used for demo output) and uses very little RAM.这种方法在微型环境(例如 Arduino 引导加载程序)中特别有用,因为它最终不会导致所有 printf() 膨胀(当 printf() 不用于演示输出时)并且使用很少的 RAM。 You can get a look at value just by blinking a single led :)您只需闪烁单个 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;
}

Usually, this problem resolve with using the modulo of a number in a loop or convert a number to a string.通常,此问题通过在循环中使用数字的模或将数字转换为字符串来解决。 For convert a number to a string, you may can use the function itoa , so considering the variant with the modulo of a number in a loop.要将数字转换为字符串,您可以使用函数itoa ,因此考虑循环中数字模数的变体。


Content of a file get_digits.c文件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 with the GNU GCC使用 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 with the LLVM/Clang使用 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]

Testing environment测试环境

$~/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
//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;
}
#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);}

First convert your integer to a string using sprintf , then do whatever you want with its elements, that are chars .首先使用sprintf将您的整数转换为字符串,然后对其元素执行任何您想要的操作,即chars Assuming an unsigned score:假设一个unsigned分数:

unsigned int score = 1529587, i;
char stringScore [11] = { 0 };

sprintf( stringScore, "%d, score );

for( i=0; i<strlen(stringScore); i++ )
    printf( "%c\n", stringScore[i] );

Please note how:请注意如何:

  • It prints digits starting from the most significant one它从最重要的数字开始打印数字
  • stringScore is 11 characters long assuming that the size of int , in your platform, is 4 bytes, so that the maximum integer is 10 digits long. stringScore为 11 个字符,假设您的平台中int的大小为 4 个字节,因此最大整数长度为 10 位。 The eleventh one is for the string terminator character '\\0' .第 11 个用于字符串终止符'\\0'
  • sprintf makes all the work for you sprintf为您完成所有工作

Do you need to have an integer for every single digit?每个数字都需要一个整数吗?

Since we are sure that stringScore contains only digits, the conversion is really easy.由于我们确定stringScore仅包含数字,因此转换非常简单。 If dig is the character containing the digit, the corresponding integer can be obtained in this way:如果dig是包含数字的字符,则可以通过以下方式获得相应的整数:

int intDigit = dig - '0';

I've made this solution, it-s simple instead read an integer, i read a string (char array in C), then write with a for bucle, the code also write the sum of digits我做了这个解决方案,它很简单,而不是读取一个整数,我读取一个字符串(C 中的字符数组),然后用 for bucle 写,代码也写数字的总和

// #include<string.h>

scanf("%s", n);
int total = 0;

for (int i = 0; i< strlen(n); i++){
    printf("%c", n[i]);
    total += (int)(n[i]) -48;
}

printf("%d", total);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM