CSCI 208 – Introduction to Computer Science II Fall 2013 M.Doman Homework 2 Programming Problem: Luhn Checksum Validation Due September 2, 2013 Lessons Challenges in input processing Converting input strings to numeric data Problem solving Review in C++ coding Printed Name: ______________________________________________ Signature: _______________________________________________ You are asked to perform identification number validation. Identification numbers are used throughout data collections. Books have ISBN numbers; databases have customer number, vendor numbers, etc. Sometimes these numbers are entered in the computer by hand. This may introduce potential errors by mistakenly entering wrong numbers, transposing numbers or omitting numbers. To avoid this situation, systems have developed various techniques to validate numbers. These techniques work by running the identification number through a formula that generates one or more extra (hidden) digits, which become part of the original number. If any of the digits are changed in the original part of the number, the extra digits no longer match and the number can be rejected. Luhn Checksum Validation The Luhn formula is a widely used system for validating identification numbers. Using the original number, double the value of every other digit. Then add the values of the individual digits together. Note: if a doubled value has two digits, then the values of the individual digits together. The identification number is valid if the sum is divisible by 10. Write a program that takes an identification number of arbitrary length and determines whether the number is valid under the Luhn formula. Constraint: The program must process each character before reading the next one. In other words, the programs will not store the characters in a data structure for later processing. Here’s an example to help explain the problem. Note that your program only has to validate the identification number. But to help explain, I’ll show how the checksum number is generated. Computing the checksum digit The original number is 18926. This is represented in the following illustration. Every other digit starting from the rightmost digit will be doubled. After which all digits will be added together. If, after doubling, a two digit result occurs, both digits are added to the sum. 1 8 9 2 2 1 + 8 + Add digits together 1 2 6 8 + 8 1 + 2 + 1 6 Double every other digit 2 + 2 = 24 + 6 = 30 Include check digit to make checksum divisible by 10 Validating the number after checksum The number after checksum is 189266 which now includes the check digit. As before, every second digit, starting with the digit to the left of the check digit, will be doubled. Add the values of all digits, including the check digit, to determine if the checksum is divisible by 10. This will indicate if the number is valid. Break Down the Problem PLAN Make a list of the issues we have to tackle Knowing which digits to double Treating doubled numbers 10 and greater according to their individual digits Knowing when we reached the end of the number Reading each digit separately. Convert characters to digits START WITH THE EASIEST… or the most interesting Treating doubled numbers 10 and greater according to their individual digits There are two possibilities for a result after doubling: 1) value is less than 10 -> No work required 2) value is 10 or greater int digitDoubled (int digit) { int returnSum; int doubleValue = digit * 2; if (doubleValue >= 10) { returnSum = 1 + (doubleValue % 10);} else { returnSum = doubleValue; } return returnSum; } Convert characters to digits If you use a straight cast from int=char, you get the ascii representation of the character. Ex ‘0’ = 48 There are different ways to do the conversion: Using atoi Note requires #include <stdlib.h> // Convert on character to a digit int charToInt (char inputChar) { int returnInt = atoi(inputChar); return returnInt; } Reading each digit separately: Knowing which digits to double Reduce to 1) Reading one character char charDigit; int intDigit; int checksum; cout <<" \n\nEnter a 1 digit number: "; cin >> charDigit; intDigit = charToInt(&charDigit); checksum = checksum + intDigit; cout << " \n\nNumber entered: " << intDigit; 2) Reading a fixed length Lift constraint. Figure out how to validate checksum for a string of a fix length. Use 6 Reduce problem even further… Lift doubling constraint. checksum = 0; cout <<" \n\nEnter a 6 digit number: "; for (int position=1; position <=6; position++) { cin >> charDigit; intDigit = charToInt(charDigit); checksum = checksum + intDigit; cout << " \nNumber entered: " << intDigit; 3) For fixed length .. Add doubling for every other digit starting from the second digit from the right. checksum = 0; cout <<" \n\nEnter a 6 digit number: "; for (int position=1; position <=6; position++) { cin >> charDigit; intDigit = charToInt(charDigit); if ( position % 2 ==0) {} else {intDigit = digitDoubled(intDigit);} checksum = checksum + intDigit; cout << " \nNumber added: " << intDigit; } cout << "\nChecksum: " << checksum; Knowing when we reached the end of the number Experiment!! #define EndOfInput ‘\n’ Handle both even and odd number of digits ,,, FINAL Program // Final program #include <iostream> #include <cstdlib> #define EndOfInput '\n' using namespace std; int charToInt (char); int digitDoubled (int); int main() { // Identify program runing cout <<" \n\nLuhn Checksum Programs" ; // Declare and initialize local variables int checksumEven = 0; int checksumOdd = 0; int digitCount= 0; int position = 1; char charDigit; int intDigit =0; int checksum =0; // Request input cout <<" \nEnter the number to be verified \n"; // Read in the first character charDigit = cin.get(); // Loop to validate the number one character at a time. while (charDigit != EndOfInput){ digitCount++; intDigit = charToInt(charDigit); // Collect all data require for both an odd size or even size id number if ( position % 2 ==0) { // Even input position // If the id number turns out to be an even number of digits checksumOdd += digitDoubled(intDigit); / / If the id number turns out to be an odd number of digits checksumEven += intDigit; } else { // Odd input position // If the id number turns out to be an even number of digits checksumOdd += intDigit; // If the id number turns out to be an odd number of digits checksumEven += digitDoubled(intDigit); }; charDigit = cin.get(); position++; } // end of while loop // set output for both even and odd digit count if ( digitCount % 2 ==0) { // Even number of digits checksum = checksumEven;} else { // Odd number of digits checksum = checksumOdd; } // Validate checksum if (checksum % 10 == 0) { cout << "Checksum is divisible by 10. The identification number is valid"; } else { cout << "Checksum is NOT divisible by 10. The identification number is invalid"; } cout << "\nChecksum: " << checksum; } // End of main //////////////////////////////////////////////////////////////////////////////////////////////////////// // function: charToInt // // Convert on character to a digit // I'll used the atoi function. It requires the value to be passed by reference /////////////////////////////////////////////////////////////////////////////////////////////////////// int charToInt (char inputChar) { int returnInt = atoi(&inputChar); return returnInt; } //////////////////////////////////////////////////////////////////////////////////////////////////////// // function: digitDoubled // //Return value of integer doubled. If the value is greater than 10, then add the two digits. // // Since the doubled value is never greater than 19, I can assume that if the value is greater than 10, // the left most digit is 1. So,I'll add 1 to the rightmost digit. //////////////////////////////////////////////////////////////////////////////////////////////////////// int digitDoubled (int digit) { int returnSum; int doubleValue = digit * 2; if (doubleValue >= 10) { returnSum = 1 + (doubleValue % 10);} else { returnSum = doubleValue; } return returnSum; }