IBAN: Difference between revisions
Content added Content deleted
Alextretyak (talk | contribs) m (→{{header|11l}}) |
(→{{header|C++}}: format the code in a more common way) |
||
Line 655: | Line 655: | ||
#include <algorithm> |
#include <algorithm> |
||
#include <cctype> |
#include <cctype> |
||
using namespace boost::algorithm ; |
|||
using namespace boost::algorithm; |
|||
bool isValid ( const std::string &ibanstring ) |
|||
{ |
|||
static std::map<std::string, int> countrycodes |
|||
{ {"AL" , 28} , {"AD" , 24} , {"AT" , 20} , {"AZ" , 28 } , |
|||
{"BE" , 16} , {"BH" , 22} , {"BA" , 20} , {"BR" , 29 } , |
|||
{"BG" , 22} , {"CR" , 21} , {"HR" , 21} , {"CY" , 28 } , |
|||
{"CZ" , 24} , {"DK" , 18} , {"DO" , 28} , {"EE" , 20 } , |
|||
{"FO" , 18} , {"FI" , 18} , {"FR" , 27} , {"GE" , 22 } , |
|||
{"DE" , 22} , {"GI" , 23} , {"GR" , 27} , {"GL" , 18 } , |
|||
{"GT" , 28} , {"HU" , 28} , {"IS" , 26} , {"IE" , 22 } , |
|||
{"IL" , 23} , {"IT" , 27} , {"KZ" , 20} , {"KW" , 30 } , |
|||
{"LV" , 21} , {"LB" , 28} , {"LI" , 21} , {"LT" , 20 } , |
|||
{"LU" , 20} , {"MK" , 19} , {"MT" , 31} , {"MR" , 27 } , |
|||
{"MU" , 30} , {"MC" , 27} , {"MD" , 24} , {"ME" , 22 } , |
|||
{"NL" , 18} , {"NO" , 15} , {"PK" , 24} , {"PS" , 29 } , |
|||
{"PL" , 28} , {"PT" , 25} , {"RO" , 24} , {"SM" , 27 } , |
|||
{"SA" , 24} , {"RS" , 22} , {"SK" , 24} , {"SI" , 19 } , |
|||
{"ES" , 24} , {"SE" , 24} , {"CH" , 21} , {"TN" , 24 } , |
|||
{"TR" , 26} , {"AE" , 23} , {"GB" , 22} , {"VG" , 24 } } ; |
|||
std::string teststring( ibanstring ) ; |
|||
erase_all( teststring , " " ) ; //defined in boost/algorithm/string.hpp |
|||
if ( countrycodes.find( teststring.substr(0 , 2 )) == countrycodes.end( ) ) |
|||
return false ; |
|||
if ( teststring.length( ) != countrycodes[ teststring.substr( 0 , 2 ) ] ) |
|||
return false ; |
|||
if (!all(teststring, is_alnum())) |
|||
return false ; |
|||
to_upper( teststring ) ; |
|||
std::rotate(teststring.begin(), teststring.begin() + 4, teststring.end()); |
|||
bool isValid(const std::string &ibanstring) { |
|||
std::string numberstring ;//will contain the letter substitutions |
|||
static std::map<std::string, int> countrycodes { |
|||
for (const auto& c : teststring) |
|||
{"AL", 28}, {"AD", 24}, {"AT", 20}, {"AZ", 28 }, |
|||
{ |
|||
{"BE", 16}, {"BH", 22}, {"BA", 20}, {"BR", 29 }, |
|||
if (std::isdigit(c)) |
|||
{"BG", 22}, {"CR", 21}, {"HR", 21}, {"CY", 28 }, |
|||
numberstring += c ; |
|||
{"CZ", 24}, {"DK", 18}, {"DO", 28}, {"EE", 20 }, |
|||
if (std::isupper(c)) |
|||
{"FO", 18}, {"FI", 18}, {"FR", 27}, {"GE", 22 }, |
|||
numberstring += std::to_string(static_cast<int>(c) - 55); |
|||
{"DE", 22}, {"GI", 23}, {"GR", 27}, {"GL", 18 }, |
|||
} |
|||
{"GT", 28}, {"HU", 28}, {"IS", 26}, {"IE", 22 }, |
|||
//implements a stepwise check for mod 97 in chunks of 9 at the first time |
|||
{"IL", 23}, {"IT", 27}, {"KZ", 20}, {"KW", 30 }, |
|||
// , then in chunks of seven prepended by the last mod 97 operation converted |
|||
{"LV", 21}, {"LB", 28}, {"LI", 21}, {"LT", 20 }, |
|||
//to a string |
|||
{"LU", 20}, {"MK", 19}, {"MT", 31}, {"MR", 27 }, |
|||
int segstart = 0 ; |
|||
{"MU", 30}, {"MC", 27}, {"MD", 24}, {"ME", 22 }, |
|||
int step = 9 ; |
|||
{"NL", 18}, {"NO", 15}, {"PK", 24}, {"PS", 29 }, |
|||
std::string prepended ; |
|||
{"PL", 28}, {"PT", 25}, {"RO", 24}, {"SM", 27 }, |
|||
long number = 0 ; |
|||
{"SA", 24}, {"RS", 22}, {"SK", 24}, {"SI", 19 }, |
|||
while ( segstart < numberstring.length( ) - step ) { |
|||
{"ES", 24}, {"SE", 24}, {"CH", 21}, {"TN", 24 }, |
|||
number = std::stol( prepended + numberstring.substr( segstart , step ) ) ; |
|||
{"TR", 26}, {"AE", 23}, {"GB", 22}, {"VG", 24 } |
|||
int remainder = number % 97 ; |
|||
}; |
|||
prepended = std::to_string( remainder ) ; |
|||
std::string teststring(ibanstring); |
|||
if ( remainder < 10 ) |
|||
erase_all(teststring, " "); //defined in boost/algorithm/string.hpp |
|||
prepended = "0" + prepended ; |
|||
if (countrycodes.find(teststring.substr(0, 2)) == countrycodes.end()) |
|||
segstart = segstart + step ; |
|||
return false; |
|||
if (teststring.length() != countrycodes[teststring.substr(0, 2)]) |
|||
} |
|||
return false; |
|||
number = std::stol( prepended + numberstring.substr( segstart )) ; |
|||
if (!all(teststring, is_alnum())) |
|||
return ( number % 97 == 1 ) ; |
|||
return false; |
|||
to_upper(teststring); |
|||
std::rotate(teststring.begin(), teststring.begin() + 4, teststring.end()); |
|||
std::string numberstring; // will contain the letter substitutions |
|||
for (const auto &c : teststring) { |
|||
if (std::isdigit(c)) |
|||
numberstring += c; |
|||
if (std::isupper(c)) |
|||
numberstring += std::to_string(static_cast<int>(c) - 55); |
|||
} |
|||
// implements a stepwise check for mod 97 in chunks of 9 at the first time, |
|||
// then in chunks of seven prepended by the last mod 97 operation converted |
|||
// to a string |
|||
int segstart = 0; |
|||
int step = 9; |
|||
std::string prepended; |
|||
long number = 0; |
|||
while (segstart < numberstring.length() - step) { |
|||
number = std::stol(prepended + numberstring.substr(segstart, step)); |
|||
int remainder = number % 97; |
|||
prepended = std::to_string(remainder); |
|||
if (remainder < 10) |
|||
prepended = "0" + prepended; |
|||
segstart = segstart + step; |
|||
step = 7; |
|||
} |
|||
number = std::stol(prepended + numberstring.substr(segstart)); |
|||
return (number % 97 == 1); |
|||
} |
} |
||
void SayValidity(const std::string |
void SayValidity(const std::string &iban) { |
||
{ |
|||
std::cout << iban << (isValid(iban) ? " is " : " is not ") << "valid\n"; |
std::cout << iban << (isValid(iban) ? " is " : " is not ") << "valid\n"; |
||
} |
} |
||
int main( |
int main() { |
||
SayValidity("GB82 WEST 1234 5698 7654 32"); |
|||
{ |
|||
SayValidity(" |
SayValidity("GB82TEST12345698765432"); |
||
return 0; |
|||
SayValidity("GB82TEST12345698765432"); |
|||
return 0 ; |
|||
}</lang>{{out}} |
}</lang>{{out}} |
||
GB82 WEST 1234 5698 7654 32 is valid! |
GB82 WEST 1234 5698 7654 32 is valid! |