I'm taking CS50 Intro to CS. In this assignment, we're asked to make a program that can identify what type of credit card (AMEX, Visa, MasterCard) is given in the input (and whether it is valid.) Validity is checked using Luhn's Algorithm. Here's how the algorithm works:
- Multiply every other digit by 2, starting with the number’s second-to-last digit, and then add those products’ digits together. (We're not adding the products together, rather the digits of the products!)
- Add the sum to the sum of the digits that weren’t multiplied by 2.
- If the total’s last digit is 0, the number is valid!
Then, the type of credit card is checked by checking the first few digits of the credit card. I.e American Express numbers start with 34 or 37, VISA starts with 4, etc etc. Here's my implementation:
#include <stdio.h>
#include <cs50.h>
#include <math.h>
#include <stdlib.h>
bool check_is_card_valid(long card);
int checksum(long card);
bool array_consists(const unsigned int arr[], int val, int arrlen);
string get_card_type(long card);
int get_nth_digit(long card, int digit);
int get_card_length(long card);
const unsigned int accepted_card_length[] =
{
15, // AMEX uses 15 digit numbers
16, // MasterCard and VISA uses 16 digit numbers
13 // VISA uses 13 digit numbers
};
const size_t acc_card_len = sizeof(accepted_card_length) / sizeof(*accepted_card_length);
const unsigned int AMEX_first_digits[] = {34, 37};
const size_t amex_digits_len = sizeof(AMEX_first_digits) / sizeof(*AMEX_first_digits);
const unsigned int MASTERCARD_first_digits[] = {51, 52, 53, 54, 55};
const size_t mc_digits_len = sizeof(MASTERCARD_first_digits) / sizeof(*MASTERCARD_first_digits);
const unsigned int VISA_first_digit = 4;
int main(void)
{
long card_number = get_long("Card number: ");
if (check_is_card_valid(card_number) == true)
{
printf("%s\n", get_card_type(card_number));
}
else
{
printf("INVALID\n");
}
}
/*
Luhn's algorithm. Starting from the right, multiply every other digit by 2 and add up the digits
add this sum to the sum of the digits that were not multiplied by 2.
*/
int checksum(long card)
{
int checksum = 0;
for (int i = 0; i < get_card_length(card); i++)
{
if (i % 2 == 0)
{
checksum += get_nth_digit(card, i);
}
else if (i % 2 == 1)
{
int num = get_nth_digit(card, i) * 2;
if (num > 9)
{
num = get_nth_digit(num, 0) + get_nth_digit(num, 1);
}
checksum += num;
}
}
return checksum;
}
bool array_consists(const unsigned int arr[], int val, int arrlen)
{
for (int i = 0; i < arrlen; i++)
{
if (val == arr[i])
{
return true;
}
}
return false;
}
// Luhn's algorithm states that if the last digit of the checksum is 0, it is valid
bool check_is_card_valid(long card)
{
if (array_consists(accepted_card_length, get_card_length(card), acc_card_len) == true)
{
return checksum(card) % 10 == 0;
}
else
{
return false;
}
}
string get_card_type(long card)
{
int card_length = get_card_length(card);
int first_digit = get_nth_digit(card, card_length - 1);
int second_digit = get_nth_digit(card, card_length - 2);
int first_two_digits = (first_digit * 10) + second_digit;
if (first_digit == VISA_first_digit)
{
return "VISA";
}
else if (array_consists(AMEX_first_digits, first_two_digits, amex_digits_len) == true)
{
return "AMEX";
}
else if (array_consists(MASTERCARD_first_digits, first_two_digits, mc_digits_len) == true)
{
return "MASTERCARD";
}
else
{
return "INVALID";
}
}
// gets nth digit from the right, starting with 0, using modulo
int get_nth_digit(long card, int digit)
{
return fmod(floor(card / pow(10, digit)), 10);
}
int get_card_length(long card)
{
return floor(log10(card)) + 1;
}
I would like some feedback on my code and how I could improve it; things like style, readability, cleanness, efficiency, etc. Is my code easily understandable? What about the comments - is there not enough comments? I try not to comment on my code when the function of something seems obvious. How do I improve the style, and are there any code conventions I'm not following? Can I optimize this to make it a faster process? Or maybe there's a better way to do the same thing? Basically, how do I improve my code?