Credit Card
General
- All submissions must include a work history to be worth credit.
- Make sure to name files exactly as specified, including capitalization.
- Make sure your program accepts input in exactly the order and format specified. Do not ask for extra input or change the order of inputs. (If you want to make an expanded version of a program and get feedback on it, email it to me or show me in person.)
- Output the requested information in the specified order. Slight variations in output wording/formatting are usually fine, as long as formatting isn't part of the assignment. If you cannot get the right final output, print out some evidence of the work your program did to demonstrate your progress.
- Readability and maintainability of your code counts. Poor formatting, confusing variable names, unnecessarily complex code, etc. can result in deductions from your score.
Objective
Upon completion of this assignment, the student will be able to write functions and use unit tests to verify their functionality.
Background
The last digit of a credit card number is always chosen to provide a checksum of the other digits. (The scheme used is called the Luhn algorithm). If one digit in a credit card is changed, or they are typed in the wrong order, the checksum should detect the data entry mistake.
To check a credit card number, you need to:
- Working your way from RIGHT to LEFT add up the digits. The first, third, fifth, etc... digits
use as is. For the second, fourth, sixth, etc... digit do the following:
- Double the number (i.e. 4 --> 8, 6 --> 12)
- If the number ends up being two digits, add the two digits (i.e. 12 --> 1 + 2 --> 3) and use that as the final value for the digit.
- If the total is evenly divisible by 10, the number is valid. If not, the number is invalid.
Examples of the process
Given the number "79927398713", we would start on the right with the 3 - since it is the first digit it would not be doubled. The next digit is 1 - since it is second it would be doubled to make 2. Next is 7 and it is not doubled (since it is third). Then is 8 and it is doubled which makes 16; because 16 is no longer one digit, we would turn it into 7 (1 + 6)...
The sum of all the final digit values is 70, which is divisible by 10. So that is possibly a valid credit card.
Given the number "12345671234567", we would start on the right with the 7 - it would not be doubled. The next digit is 6 - it is doubled, which makes 12 and since that is two digits we turn it into 3 (1 + 2)...
This time, the sum of the final digit values is 57, which is not divisible by 10 and thus NOT a possible credit card number.
Assignment Instructions
Use the UnitTestProject template folder.
Then open tests.cpp and replace it with the starter code from this copy of tests.cpp.
The starter code has a series of unit tests for functions you need to write.
Uncomment individual tests to work on them. Other than uncommenting TEST_CASE
s, you
are NOT allowed to modify the existing code.
If a given TEST_CASE
fails to compile, or crashes while running, comment
it back out before submission so I can see the rest of the tests run. Leave in
code that you wrote for the test as you can still get partial credit for untested
code. If a TEST_CASE
does compile and run but fails, leave it uncommented. A
failed test is better than a commented out one - it represents working code that clearly
identifies a problem that could be worked on more.
In terms of scoring for each function:
Passing Test > Failing Test > Commented-Out Test > Does not Compile OR Missing
See below for tips on specific functions.
Submission
Submit file: assign6.zip
I should be able to compile and run your program by doing:
g++ -std=c++17 tests.cpp -o program.exe
.\program.exe (./program.exe on a mac)
Functions Guide
The following functions are what you need to actually implement. There is one or more unit test for each function.
Each function must be preceded by a doxygen comment with a brief description of the function overall, and descriptions of its parameters and return value.
It is strongly recommended you attack them by working on one unit test at a time. Uncomment the next unit test in the file and build a new function (or modify existing functions) until you pass the test.
int charToInt(char digit)
Turns a char like '3' into the number it represents (3).
Behavior is undefined for chars that do not representing digits. (Your code does not have to worry about them).
int doubledDigitValue(int number)
Take a number doubles it. If the number is still a single digit, that value is returned. If the doubled value is two digits long, returns the sum of those digits.
Examples: Calling doubledDigitValue(4) should give 8. Calling doubledDigitValue(8) should give 7.
Behavior is undefined for numbers above 9. (Your code does not have to worry about them).
string cardType(const string& cardNumber)
Returns a string representing the type of credit card a number is: Visa, Mastercard, American Express, or Unknown. The card type can be determined by the first digit or two of the credit card number:
- Starts with 4 : Visa
- Starts with 5 : Mastercard
- Starts with 34 or 37 : American Express
If the cardNumber
is less than 2 digits, or starts with anything else, you should return Unknown.
int luhnDigitSum(const string& cardNumber)
Sums the digits of a credit card number according to the Luhn algorithm. i.e. Calling sumOfDigits("79927398713") should result in 70.
For full credit this function should make use of charToInt and doubledDigitValue instead of duplicating their code.
Hint: you can just use the current digit's position to calculate "should I double this one", but it might be less tricky to use a separate variable that tracks "do I double the next value" and then switch it after each digit.
bool isValid(const string& cardNumber)
Returns true/false indicating if a credit card number is potentially a valid number according to the Luhn algorithm.
This should use a call to luhnDigitSum and not reimplement the logic of that function.
void printCardInfo(const string& cardNumber)
Given a credit card number, this function should print out to the console a message that specifies the card number, if it looks valid, and what type of card it looks like.
This should use your existing functions as helpers.
Note:
Because this function prints directly to the console, our unit test can't actually test that it is working correctly. All it does is call the function a few times and display both what we expect to see and the results of the function. We have to manually verify that the function worked correctly.
If we wanted to make this function easier to test, we could redesign it to return a string with the result instead of printing it directly to the console. This would actually be a more flexible and thus powerful function than what we currently have.