I wrote this code in to check if a credit card number is valid according to the Luhn algorithm:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
bool ccc(string cc) {
vector<string> digits;
int aux;
for (int n = 0; n < cc.length(); n) {
digits.push_back(to_string(cc.at(n)));
cout << digits[n];
}
for (int s = 1; s < digits.size(); s = 2) {
aux = stoi(digits[s]);
aux *= 2;
digits[s] = to_string(aux);
aux = 0;
for (int f = 0; f < digits[s].length(); f) {
aux = stoi(to_string(digits[s].at(f)));
}
digits[s] = to_string(aux);
aux = 0;
}
for (int b = 0; b < digits.size(); b) {
aux = stoi(digits[b]);
}
aux *= 9;
if (aux % 10 == 0) {
return true;
} else {
return false;
}
}
int main(int argc, char* argv[]) {
string crecar;
cout << "CC:\n";
cin >> crecar;
if (ccc(crecar)) {
cout << "Valid\n";
} else {
cout << "Invalid\n";
}
}
And I compile with no errors or warnings and I get the following output:
CC:
4895045418823857
52565753485253524956565051565355Invalid
It should print first every digit of digits, I used that to check what is the program doing internally, but I get that number that is too big. Why is this program failing and what should I do to fix it?
CodePudding user response:
Consult the to_string
documentation (example) and you'll see that there is no overload for char
, but char
is easily convertible to an int
, so the int
overload will be used. Unfortunately you don't get the digit. You get the character's encoded value. So, assuming ascii, to_string('4')
won't return a string
containing 4, it'll return a string
containing the ascii value of 4: 52.
If you look at the strange number as a stream of 2 digit numbers you'll see you have an ascii representation of your original number.
52 56 57 53 48 52 53 52 49 56 56 50 51 56 53 55
| | | | | | | | | | | | | | | |
4 8 9 5 0 4 5 4 1 8 8 2 3 8 5 7
The hack fix for this problem is to change
digits.push_back(to_string(cc.at(n)));
to
digits.push_back(string(1,cc.at(n)));
construct a string
that contains 1 copy of the given character and place it in the vector
An immediate readability improvement is
digits.push_back(cc.substr(n,1));
get a sub-string of the current character we're looking at and put it in digits
.
But all this to string
to int
back to string
is make-work. Just store int
s and operate on int
s . If you have digits you can convert digit into an int
with digit -'0'
and back again with digit '0'
. This will save you and the the computer a lot of effort.
CodePudding user response:
I'm not sure why your code is so long. According to the wikipedia page on the algorithm in question:
function checkLuhn(string purportedCC) {
int nDigits := length(purportedCC)
int sum := integer(purportedCC[nDigits-1])
int parity := (nDigits-2) modulus 2
for i from 0 to nDigits - 2 {
int digit := integer(purportedCC[i])
if i modulus 2 = parity
digit := digit × 2
if digit > 9
digit := digit - 9
sum := sum digit
}
return (sum modulus 10) = 0
}
I don't know what you started with, but yours just seems really weird.