IBAN: Difference between revisions

Content added Content deleted
(→‎Ruby: Add implementation)
(→‎C: Add implementation)
Line 4: Line 4:


The task here is to validate the following fictitious IBAN: GB82 WEST 1234 5698 7654 32. Details of the algorithm can be found on the Wikipedia page.
The task here is to validate the following fictitious IBAN: GB82 WEST 1234 5698 7654 32. Details of the algorithm can be found on the Wikipedia page.

=={{header|C}}==
<lang C>#include <alloca.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define V(cc, exp) if (!strncmp(iban, cc, 2)) return len == exp

/* Validate country code against expected length. */
int valid_cc(char *iban, int len)
{
V("AL", 28); V("AD", 24); V("AT", 20); V("AZ", 28); V("BE", 16); V("BH", 22); V("BA", 20); V("BR", 29);
V("BG", 22); V("CR", 21); V("HR", 21); V("CY", 28); V("CZ", 24); V("DK", 18); V("DO", 28); V("EE", 20);
V("FO", 18); V("FI", 18); V("FR", 27); V("GE", 22); V("DE", 22); V("GI", 23); V("GR", 27); V("GL", 18);
V("GT", 28); V("HU", 28); V("IS", 26); V("IE", 22); V("IL", 23); V("IT", 27); V("KZ", 20); V("KW", 30);
V("LV", 21); V("LB", 28); V("LI", 21); V("LT", 20); V("LU", 20); V("MK", 19); V("MT", 31); V("MR", 27);
V("MU", 30); V("MC", 27); V("MD", 24); V("ME", 22); V("NL", 18); V("NO", 15); V("PK", 24); V("PS", 29);
V("PL", 28); V("PT", 25); V("RO", 24); V("SM", 27); V("SA", 24); V("RS", 22); V("SK", 24); V("SI", 19);
V("ES", 24); V("SE", 24); V("CH", 21); V("TN", 24); V("TR", 26); V("AE", 23); V("GB", 22); V("VG", 24);

return 0;
}

/* Remove blanks from s in-place, return its new length. */
int strip(char *s)
{
int i = -1, m = 0;

while(s[++i]) {
s[i - m] = s[i];
m += s[i] <= 32;
}

s[i - m] = 0;
return i - m;
}

/* Calculate the mod 97 of an arbitrarily large number (as a string). */
int mod97(char *s, int len)
{
int i, j, parts = len / 7;
char rem[10] = "00";

for (i = 1; i <= parts + (len % 7 != 0); ++i) {
strncpy(rem + 2, s + (i - 1) * 7, 7);
j = atoi(rem) % 97;
rem[0] = j / 10 + '0';
rem[1] = j % 10 + '0';
}

return atoi(rem) % 97;
}

int valid_iban(char *iban)
{
int i, j, l = 0, sz = strip(iban);
char *rot, *trans;

/* Ensure upper alphanumeric input and count letters. */
for (i = 0; i < sz; ++i) {
if (!isdigit(iban[i]) && !isupper(iban[i]))
return 0;
l += !!isupper(iban[i]);
}

if (!valid_cc(iban, sz))
return 0;

/* Move the first four characters to the end. */
rot = alloca(sz);
strcpy(rot, iban + 4);
strncpy(rot + sz - 4, iban, 4);

/* Allocate space for the transformed IBAN. */
trans = alloca(sz + l);
trans[sz + l] = 0;

/* Convert A to 10, B to 11, etc. */
for (i = j = 0; i < sz; ++i, ++j) {
if (isdigit(rot[i]))
trans[j] = rot[i];
else {
trans[j] = (rot[i] - 55) / 10 + '0';
trans[++j] = (rot[i] - 55) % 10 + '0';
}
}

return mod97(trans, sz + l) == 1;
}

int main(int _, char **argv)
{
while (--_, *++argv)
printf("%s is %svalid.\n", *argv, valid_iban(*argv) ? "" : "in");

return 0;
}</lang>

{{out}}

<pre>iban 'GB82 WEST 1234 5698 7654 32' GB82TEST12345698765432
GB82WEST12345698765432 is valid.
GB82TEST12345698765432 is invalid.</pre>


=={{header|Caché ObjectScript}}==
=={{header|Caché ObjectScript}}==