简体   繁体   中英

How to add product digits rather than products themselves in C?

I am trying to finish an assignment in C for the CS50 course in which I must implement Luhn's algorithm to validate a credit card number. Here is a quick example to elaborate:


credit card number: 4003600000000014.
Now for every other digit, starting with the number's second-to-last digit:

1-0-0-0-0-6-0-4

Let's multiply each of the digits by 2:

1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2

That gives us:

2 + 0 + 0 + 0 + 0 + 12 + 0 + 8

Now let's add those products' digits (ie, not the products themselves) together:

2 + 0 + 0 + 0 + 0 + 1 + 2 + 0 + 8 = 13

Now let's add that sum (13) to the sum of the digits that weren't multiplied by 2 (starting from the end):

13 + 4 + 0 + 0 + 0 + 0 + 0 + 3 + 0 = 20

Yup, the last digit in that sum (20) is a 0, so the number is valid.


I figured out how to extract each number in the credit card individually (I know my way is boring and probably not practical), so the next step is to multiply every other number by two and add (the products' digits, not the digits themselves) and this is what I need help of how to do it? MY code:

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

int main(void)
{
    long credit_card_number;
    do
    {
        credit_card_number = get_long("Enter your credit card number: ");

    }
    while (credit_card_number < 1 || credit_card_number > 9999999999999999);

    //American Express uses 15-digit numbers. American Express numbers start with 34 or 37
    //MasterCard uses 16-digit numbers. MasterCard numbers start with 51, 52, 53, 54, or 55.
    //Visa uses 13- and 16-digit numbers. Visa numbers start with 4.
    // checksum

    long last_number;
    long credit_card_without_last_number;
    long second_to_last_number;
    long credit_card_without_second_number;
    long third_number;
    long credit_card_without_third_number;
    long fourth_number;
    long credit_card_without_fourth_number;
    long fifth_number;
    long credit_card_without_fifth_number;
    long sixth_number;
    long credit_card_without_sixth_number;
    long seventh_number;
    long credit_card_without_seventh_number;
    long eighth_number;
    long credit_card_without_eighth_number;
    long ninth_number;
    long credit_card_without_ninth_number;
    long tenth_number;
    long credit_card_without_tenth_number;
    long eleventh_number;
    long credit_card_without_eleventh_number;
    long twelfth_number;
    long credit_card_without_twelfth_number;
    long thirteenth_number;
    long credit_card_without_thirteenth_number;
    long fourteenth_number;
    long credit_card_without_fourteenth_number;
    long fifteenth_number;
    long credit_card_without_fifteenth_number;
    long sixteenth_number;

    long multiply_digits;

    //separating each number starting from the last (right)in its own variable.
    last_number = credit_card_number % 10;
    credit_card_without_last_number = credit_card_number / 10;

    second_to_last_number = credit_card_without_last_number % 10;
    credit_card_without_second_number = credit_card_without_last_number / 10;

    third_number = credit_card_without_second_number % 10;
    credit_card_without_third_number = credit_card_without_second_number / 10;

    fourth_number = credit_card_without_third_number % 10;
    credit_card_without_fourth_number = credit_card_without_third_number / 10;

    fifth_number = credit_card_without_fourth_number % 10;
    credit_card_without_fifth_number = credit_card_without_fourth_number / 10;

    sixth_number = credit_card_without_fifth_number % 10;
    credit_card_without_sixth_number = credit_card_without_fifth_number / 10;

    seventh_number = credit_card_without_sixth_number % 10;
    credit_card_without_seventh_number = credit_card_without_sixth_number / 10;

    eighth_number = credit_card_without_seventh_number % 10;
    credit_card_without_eighth_number = credit_card_without_seventh_number / 10;

    ninth_number = credit_card_without_eighth_number % 10;
    credit_card_without_ninth_number = credit_card_without_eighth_number / 10;

    tenth_number = credit_card_without_ninth_number % 10;
    credit_card_without_tenth_number = credit_card_without_ninth_number / 10;

    eleventh_number = credit_card_without_tenth_number % 10;
    credit_card_without_eleventh_number = credit_card_without_tenth_number / 10;

    twelfth_number = credit_card_without_eleventh_number % 10;
    credit_card_without_twelfth_number = credit_card_without_eleventh_number / 10;

    thirteenth_number = credit_card_without_twelfth_number % 10;
    credit_card_without_thirteenth_number = credit_card_without_twelfth_number / 10;

    fourteenth_number = credit_card_without_thirteenth_number % 10;
    credit_card_without_fourteenth_number = credit_card_without_thirteenth_number / 10;

    fifteenth_number = credit_card_without_fourteenth_number % 10;
    credit_card_without_fifteenth_number = credit_card_without_fourteenth_number / 10;

    sixteenth_number = credit_card_without_fifteenth_number % 10;

    //Here I need the help to multiply these numbers by two and then add each product's
    //digits to the rest of the unused numbers.
    multiply_digits = (second_to_last_number*2)+(fourth_number*2)+(sixth_number*2)+(eighth_number*2)+(tenth_number*2)+(twelfth_number*2)+(fourteenth_number*2)+(sixteenth_number*2);

}

Try doing this instead

int main(){
    long cNo = 4003600000000014;
    int arr[16];

    for(int i=0; i<16; i++){
        arr[15-i] = cNo % 10;
        cNo /= 10;
    }

    int multipliedSum = 0;
    for(int i=0; i<16; i++){
        if(i%2==1)
            multipliedSum += arr[i];
        else{
            if(arr[i]*2<10){
                multipliedSum += (arr[i]*2);
            }else{
                int num = arr[i]*2;
                while(num){
                    multipliedSum += num%10;
                    num/=10;
                }
            } 
        }
    }

    printf("valid = %s\n",multipliedSum%10==0?" True": " False");
}

You will get the following

valid = True

A general algorithm for adding digits (assuming an integer type):

  1. Initialize your sum to 0: sum = 0
  2. Extract the lowest digit from the number using the % modulus operator: digit = number % 10
  3. Add the value of that digit to the sum: sum += digit (shorthand for sum = sum + digit )
  4. Divide the number by 10: number /= 10 (shorthand for number = number / 10
  5. If the number is non-zero after dividing by 10, go back to 2
  6. End

The modulus operator % returns the integer remainder of an integer division - 123 / 10 == 12 rem 3 . So the remainder of dividing the number by 10 is the least significant decimal digit of the number. Notice that integer division gives you an integer result - 123 / 10 == 12 , not 12.3 .

You'll want to put this in a separate function, so you can write something like

int sumdig( int v )
{
  ...
}

int main( void )
{
   int value = 123;
   int sum = sumdig( value ); // sumdig will return 1 + 2 + 3, or 6
   ...
}

When you find yourself creating a bunch of separate variables of the same type with the same name except for some tacked-on ordinal ( var1 , var2 , var3 or first_thing , second_thing , third_thing ), that's a real strong hint you want to use an array . You can use an array to store the individual digits of your card number:

int number[16];

and use the % 10 method as described above to extract the individual digits:

long tmp = credit_card_number; // use a temporary so we preserve the original card number
for ( int i = 0; i < 16; i++ )
{
  number[i] = tmp % 10;
  tmp /= 10;
}

This means that the least significant (rightmost) card number digit will be stored in number[0] and the most significant (leftmost) card number digit will be stored in number[15] , so be aware of that. For the purposes of validating the number it doesn't matter, but if you want to display the contents of the array you'll have to take that into account.

Using an array makes it easier to extract subsets of digits:

for ( int i = 1; i < 16; i += 2 ) // hit every other element starting at element 1
{
  number[i] *= 2; // multiply these digits by 2
}

That loop above executes the "1•2 + 0•2 + 0•2 + 0•2 + 0•2 + 6•2 + 0•2 + 4•2" portion of your algorithm.

You should be able to figure out the rest from there. Hope this helps.

Hint: to extract one digit from a number, mod it by 10 . So say that you want to figure out the sum of the digits of a number, say 123456 , you will do the following: (pseudocode)

number=123456;
sum=0;
loop if number is not 0{
sum+=number % 10;
number-=number % 10;
number=(int)(number/10);
}

Now try to implement it as a function, say digit() , and when you are trying to add some numbers digit-wise, say 123 and 456 , just do digit(123)+digit(456) instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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