Skip to content

Instantly share code, notes, and snippets.

@YenHub
Created March 17, 2021 18:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YenHub/2fe2aeeef3788fb56002e1126d5a9d8b to your computer and use it in GitHub Desktop.
Save YenHub/2fe2aeeef3788fb56002e1126d5a9d8b to your computer and use it in GitHub Desktop.
Luhn's Algorithm in C
#include <stdio.h>
#include <cs50.h>
string cardType;
// Prompt for a valid card number
long getCardNumber(void)
{
long cardNumber;
cardNumber = get_long("Please enter the card number: ");
return cardNumber;
}
int getDigitCount(long n)
{
int digits = 0;
while (n > 0)
{
n /= 10;
digits++;
}
return digits;
}
int getFirstDigit(long n)
{
while (n > 10)
{
n /= 10;
}
return n;
}
int getFirstTwoDigits(long n)
{
while (n > 100)
{
n /= 10;
}
return n;
}
// Basic validation against known card types using digit count & card prefixes
bool digitCheck(long cardNumber)
{
int cardDigits = getDigitCount(cardNumber);
int firstTwoDigits = getFirstTwoDigits(cardNumber);
int firstDigit = getFirstDigit(cardNumber);
switch (cardDigits)
{
case 13: // Visa
if (firstDigit == 4)
{
cardType = "VISA";
return true;
}
case 16: // Visa & Mastercard
// Visa Cards begin with a 4
if (firstDigit == 4)
{
cardType = "VISA";
return true;
}
// Master cards are 51, 52, 53, 54, or 55
if (firstTwoDigits >= 51 && firstTwoDigits <= 55)
{
cardType = "MASTERCARD";
return true;
}
case 15: // Amex
// Amex cards only begin with 34 &37
if (firstTwoDigits == 34 || firstTwoDigits == 37)
{
cardType = "AMEX";
return true;
}
}
return false;
}
bool cardRangeCheck(long cardNumber)
{
int cardDigits = getDigitCount(cardNumber);
if (cardDigits < 13) return false;
if (cardDigits > 16) return false;
if (cardDigits == 14) return false;
return true;
}
bool luhnsCheck(long cardNumber)
{
// Multiply every other digit by 2, starting with the number’s second-to-last digit then add those products’ digits together.
int count = 0;
int result = 0;
long odd_check = cardNumber;
while (odd_check > 0)
{
if (count % 2 == 1)
{
int value = (odd_check % 10) * 2;
int sum = 0;
while (value != 0)
{
sum += value % 10;
value /= 10;
}
result += sum;
}
odd_check /= 10;
count++;
}
// Sum the result with each of the digits that weren’t multiplied by 2.
count = 0;
long even_check = cardNumber;
while (even_check > 0)
{
if (count % 2 == 0)
{
int value = (even_check % 10);
int sum = 0;
while (value != 0)
{
sum += value % 10;
value /= 10;
}
result += sum;
}
even_check /= 10;
count++;
}
// If the total modulo 10 is congruent to 0, the number is valid!
return result % 10 == 0;
}
bool validateCard(long cardNumber)
{
// Basic range check for the number of digits
if (cardRangeCheck(cardNumber) == false) return false;
// Check the digit length for known cards
if (digitCheck(cardNumber) == false) return false;
// Finally, run Luhn's Algorithm against the num check approved card number
if (luhnsCheck(cardNumber) == false) return false;
return true;
}
int main(void)
{
// Prompt the user for a valid card number
long cardNumber = getCardNumber();
// Validate the card
bool isValidCard = validateCard(cardNumber);
if (isValidCard)
{
printf("%s\n", cardType);
}
else
{
printf("INVALID\n");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment