CPSC 220: Project 2, a.k.a. The Luhny Bin

No Comments on CPSC 220: Project 2, a.k.a. The Luhny Bin

It turns out a clever mathematician named Luhn (loon) invented an algorithm to dance through the digits that make up your credit card number and run a check to see if it is a valid credit card.

It also turns out I’m a terrible mathematician and have NO idea how Luhn’s Algorithm actually works. But, as a budding computer scientist I don’t need to understand the mathemagical inner workings, just the conceptual steps so that I could complete Project 2 in my CPSC 220 class, using C++.

The real point of Project 2 was to get into using functions, write some of our own, implement them correctly, and behold the wonder and beauty that is compartmentalized code. Yes, I said it.

Wonder and beauty.

Behold:

//*********************************************************************
//
// File: card_checker.cpp
// Author: The WaffleStomper
// with help from the legendary Dr. Anewalt
// Date: February 27, 2014
// Class: CPSC 220
// Language: C++ and other unmentionable words
// Purpose: Validates credit card numbers
// Input : User chooses a file to input credit cards for testing
// Output: Program outputs a validated list of credit cards
//
//*********************************************************************

#include
#include
#include
#include
#include

using namespace std;

int cardLength, digitPosition, sum(0), sumOfDoubleEven(0), sumOfOdd(0), evenDigit(0), oddDigit(0);
string cardNumber, cardType, cardValid, luhncardNumber, filename;

// Function prototypes

bool funcLengthvalidation(string,string);
bool funcPrefixvalidation(string,string);
bool funcLuhnvalidation(string,string);

int main( )
{
cout << “Input a file name of credit card numbers to be validated: ” << endl; cin >> filename;
ifstream fcin; // associate filestream
fcin.open(filename.c_str());

fcin >> cardType >> cardNumber;

while (fcin) // for each line of inputFilename, do these validations: length, prefix, Luhn’s magical hoohah
{
funcLengthvalidation(cardType, cardNumber);
fcin >> cardType >> cardNumber;

}

fcin.close();
return 0;
}

bool funcLengthvalidation(string,string) // check if card length is valid
{
cardLength = cardNumber.length();
if ((cardType == “AmericanExpress”) && (cardLength == 15))
{
cardValid == “yes”;
funcPrefixvalidation(cardType, cardNumber);
return true;
}
if ((cardType == “Visa”) && ((cardLength == 13) || (cardLength == 16)))
{
cardValid == “yes”;
funcPrefixvalidation(cardType, cardNumber);
return true;
}
if ((cardType == “MasterCard”) && (cardLength == 16))
{
cardValid == “yes”;
funcPrefixvalidation(cardType, cardNumber); // move to next validation
return true;
}
else
{
cout << left << setw(15) << cardType << ” ” << setw(16)
<< cardNumber << ” ” << setw(16) << “invalid – length” << endl;
cardValid == “no”;
return false;
}
}
bool funcPrefixvalidation(string,string) // check if card prefix is valid
{
if ((cardType == “AmericanExpress”) && ((cardNumber[0] == ‘3’) &&
(cardNumber[1] == ‘4’) ||
(cardNumber[1] == ‘7’)))
{
cardValid == “yes”;
funcLuhnvalidation(cardType, cardNumber);
return true;
}
if ((cardType == “Visa”) && (cardNumber[0] == ‘4’))
{
cardValid == “yes”;
funcLuhnvalidation(cardType, cardNumber);
return true;
}
if ((cardType == “MasterCard”) && ((cardNumber[0] == ‘5’) &&
(cardNumber[1] == ‘1’) ||
(cardNumber[1] == ‘2’) ||
(cardNumber[1] == ‘3’) ||
(cardNumber[1] == ‘4’) ||
(cardNumber[1] == ‘5’)))
{
cardValid == “yes”;
funcLuhnvalidation(cardType, cardNumber); // move to next validation
return true;
}
else
{
cout << left << setw(15) << cardType << ” ” << setw(16)
<< cardNumber << ” ” << setw(16) << “invalid – prefix” << endl; cardValid == “no”; return false; } } bool funcLuhnvalidation(string cardType,string cardNumber) // check if card passes Luhn’s validation { int sumOfOdd = 0; int sumOfEven = 0; int sum = 0; int evenDigit = 0; int oddDigit = 0; int sumOfDoubleEven = 0; do {//used http://www.danieltouma.com for help on parsing through the digit positions for (int digitPosition=cardNumber.length(); digitPosition>0; digitPosition–)
{
if (digitPosition%2 == 0)
{ // executes if even
oddDigit=(int)cardNumber[digitPosition-1]-‘0’;
sumOfOdd=sumOfOdd+oddDigit;
}
else
{ // executes if odd
evenDigit=((int)cardNumber[digitPosition-1]-‘0’)*2;
evenDigit=evenDigit%10+evenDigit/10;
sumOfDoubleEven=sumOfDoubleEven + evenDigit;
}
}

sum=sumOfOdd+sumOfDoubleEven; // sums the result
if (sum%10==0) // divisible by 10?
{
cardValid == “yes”;
cout << left << setw(15) << cardType << ” ” << setw(16)
<< cardNumber << ” ” << setw(16) << “valid” << endl;
return true;
}
else
{
cout << left << setw(15) << cardType << ” ” << setw(16)
<< cardNumber << ” ” << setw(16) << “invalid – luhns” << endl;
cardValid == “no”;
return false;
}
}while (cardNumber != “n”); // as long as there are digits left in that silly card number

You might be asking yourself, “Hey, why did the WaffleStomper declare all those variables as global?” and well, you’d be justified in noticing that it’s a thing to be avoided. A bad thing. A terrible coding practice, that did not escape the eagle-eye of Dr. Anewalt who gently reminded me that this is 2014 and we don’t do those terrible programming things terrible programmers did back when we first got the intarwebz and we were typing with two fingers by the fire in our cave. No siree-bob-cattail, we are evolved programmers and we write good code with good programming practices.

Homo erectus >> Homo habilis >> Homo codicus.

So, I’m on the road to learning how to pass information around in my code using parameters, arguments, references, what have you.

Lesson learned: save the global variables for constants that will coming up later on, and meanwhile, keep the FUN in functions!

 

Tags: 

Leave a Reply

Your email address will not be published. Required fields are marked *

css.php