32 bits reichen schon...
#include <algorithm>
#include <vector>
#include <cctype>
#include <string>
#include <iostream>
/* Aufbau einer IBAN lt. ECBS EBS 204:
1 2 3
1234 5678 9012 3456 7890 1234 5678 9012 34
IBAN LLPZ [ BBAN ]
LL: 2-stelliger Ländercode lt. ISO 3166
PZ: 2-stellige numerische Prüfziffer (Modulo 97-10 gemäß ISO 7064) über die ganze IBAN
BBAN: bis zu 30-stellige Basic Bank Account Number, bestehend aus Instituts-Identifikation (IID, 4 bis 12 Stellen) und Kontoidentifikation (BAN, 8 bis 20 Stellen) */
class iban_t
{
friend std::ostream & operator<<( std::ostream &, const iban_t & );
private:
static const char * const prefix;
std::string iban;
bool valid;
unsigned calc( ) {
std::string temp = iban.substr( 4, iban.length() ) + iban.substr( 0, 4 );
std::vector< unsigned char > iban_data;
for( std::string::iterator i = temp.begin(); i != temp.end(); ++i ) {
std::string::value_type c = *i;
if( std::isdigit( c ) ) {
iban_data.push_back( c - '0' );
} else if( std::isalpha( c ) ) {
c = c - 'A' + 10;
iban_data.push_back( c / 10 );
iban_data.push_back( c % 10 );
} else {
return false;
}
}
unsigned long block = 0;
unsigned int remainder = 0;
for( std::vector< unsigned char >::size_type i = 0, iban_data_size = iban_data.size(); i < iban_data_size; i += 9 ) {
block = 0;
unsigned long p = 1;
for( std::vector< unsigned char >::size_type j = i + 9 <= iban_data_size ? i + 9 : iban_data_size; j > i; --j, p *= 10 ) {
block += iban_data[ j - 1 ] * p;
}
remainder = block % 97;
unsigned int remainder_digits = remainder / 10 ? 2 : 1;
if( i + 9 < iban_data_size ) {
iban_data.insert( iban_data.begin() + i + 9, remainder_digits, 0 );
if( remainder_digits == 1 ) {
iban_data[ i + 9 ] = remainder;
} else {
iban_data[ i + 9 ] = remainder / 10;
iban_data[ i + 10 ] = remainder % 10;
}
iban_data_size = iban_data.size();
}
}
return remainder;
}
bool validate() {
return calc() == 1;
}
public:
iban_t( const std::string &ibanstring ) : iban( ibanstring ), valid( false )
{
iban.erase( std::remove_if( iban.begin(), iban.end(), std::isspace ), iban.end() );
std::transform( iban.begin(), iban.end(), iban.begin(), std::toupper );
if( iban.substr( 0, 4 ) == "IBAN" ) {
iban = iban.substr( 4, iban.length() );
}
valid = validate( );
}
bool is_valid() const { return valid; }
void recalc() {
iban[ 2 ] = '0';
iban[ 3 ] = '0';
unsigned int remainder = 98 - calc();
iban[ 2 ] = '0' + remainder / 10;
iban[ 3 ] = '0' + remainder % 10;
valid = validate();
}
};
const char * const iban_t::prefix = "IBAN";
std::ostream & operator<<( std::ostream &os, const iban_t &iban )
{
os << iban_t::prefix;
for( std::string::size_type i = 0, length = iban.iban.length(); i < length; i++ ) {
if( i % 4 == 0 ) {
os << ' ';
}
os << iban.iban[ i ];
}
return os;
}
int main()
{
iban_t iban( "DE68210501700012345678" );
std::cout << iban << " is" << ( iban.is_valid() ? "" : " not" ) << " valid.\n";
}
// Hoppala ... die Lösung in C läuft ähnlich