I started following Harvard's CS50 (Introduction to Computer Science) on edX, and as part of their Hacker edition set 1 was the following assignment:
I am supposed to write a program (in C), that takes as input a long long int from the user and proceeds to check whether the entered number is a valid credit card number. For the purposes of this assignment, I am only interested in Visa, American Express and MasterCard number formats. The validation is done with Luhn's algorithm.
/* This program checks whether an entered number is a valid
* credit card number (only American Express, Visa and
* MasterCard formats are supported).
*/
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
int main(void)
{
long long int credit_card;
int digits = 0;
string bank = "";
printf("Number: ");
credit_card = GetLongLong();
// calculate number of digits
for (long long int temporary = credit_card; temporary > 0;
temporary /= 10, digits++);
// check if number length corresponds to valid format
switch (digits)
{
case 13:
if ( (credit_card / (long long int) pow(10, digits - 1) ) == 4)
{
bank = "VISA";
break;
}
case 15:
if ( ( (credit_card / (long long int) pow(10, digits - 2)) == 34 ) ||
(credit_card / (long long int) pow(10, digits - 2)) == 37)
{
bank = "AMEX";
break;
}
case 16:
if ( ( (credit_card / (long long int) pow(10, digits - 2)) >= 51) &&
(credit_card / (long long int) pow(10, digits - 2)) <= 55)
{
bank = "MASTERCARD";
break;
}
else if ( (credit_card / (long long int) pow(10, digits - 1) ) == 4)
{
bank = "VISA";
break;
}
// sets bank to invalid if it doesn't satisfy any of the standards.
default:
bank = "INVALID";
}
if (strcmp(bank, "INVALID") != 0)
{
// used for summing up the digits of the credit card number.
int odd_sum = 0, even_sum = 0, total = 0;
// looping through all the digits, decreasing credit_card on every iteration
for (int i = 1; i <= digits; i++, credit_card /= 10)
{
// gets the last digit of credit_card
int digit = credit_card % 10;
// performs the necessary tasks on every other digit, starting from the next-to-last one.
if (i % 2 == 0)
{
int prod_dig_sum = 0;
digit *= 2;
prod_dig_sum += (digit % 10) + (digit / 10);
even_sum += prod_dig_sum;
}
else
{
odd_sum += digit;
}
}
total = odd_sum + even_sum;
if (total % 10 == 0)
{
printf("%s\n", bank);
return 0;
}
else
{
printf("INVALID\n");
return 0;
}
}
printf("INVALID\n");
return 0;
}
Notes:
- The cs50.h library is custom-made by the Harvard staff
- the function
GetLongLong()
is part of that library, and I currently don't know all the details of how this function works - This assignment is fairly early in the course, so we are only supposed to use the most basic tools of C. Basically, only conditions and loops.
- I focused mainly on code readability, sometimes on expense of exactness
Having said all that, I am wondering if there is maybe a more elegant way to do all the checking involved in my program. The way it is now, I think I may have over-complicated the process a bit.
credit_card
in the for loop. Okay here since you don't need it later, but let's say 1 month from now there's a new criteria they add to credit card numbers that says the sum of the even digits must equal the sum of the odd digits. Your code is less flexible because this variable is gone. If the credit card was passed.by reference, you may have unintentionally mutated a shared variable. \$\endgroup\$