Data commit
This commit is contained in:
parent
7387c8f97b
commit
cb5bb5e222
199093 changed files with 3378972 additions and 0 deletions
97
Task/IBAN/C/iban.c
Normal file
97
Task/IBAN/C/iban.c
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#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(const 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(const 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 + 1);
|
||||
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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue