Task: IBAN

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


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;
}


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;
}


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;

    
    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;

    
    rot = alloca(sz);
    strcpy(rot, iban + 4);
    strncpy(rot + sz - 4, iban, 4);

    
    trans = alloca(sz + l + 1);
    trans[sz + l] = 0;

    
    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;
}










Fortran: program ibancheck

   use ISO_FORTRAN_ENV

   implicit none

   character(4), dimension(75) :: cc = (/ &
            "AD24","AE23","AL28","AT20","AZ28","BA20","BE16","BG22","BH22","BR29", &
            "BY28","CH21","CR22","CY28","CZ24","DE22","DK18","DO28","EE20","ES24", &
            "FI18","FO18","FR27","GB22","GE22","GI23","GL18","GR27","GT28","HR21", &
            "HU28","IE22","IL23","IQ23","IS26","IT27","JO30","KW30","KZ20","LB28", &
            "LC32","LI21","LT20","LU20","LV21","MC27","MD24","ME22","MK19","MR27", &
            "MT31","MU30","NL18","NO15","PK24","PL28","PS29","PT25","QA29","RO24", &
            "RS22","SA24","SC31","SE24","SI19","SK24","SM27","ST25","SV28","TL23", &
            "TN24","TR26","UA29","VG24","XK20" /)

    character(34), dimension(12) :: ibans = (/ "GB82 WEST 1234 5698 7654 32       ", &
                                               "GB82WEST12345698765432            ", & 
                                               "gb82 west 1234 5698 7654 32       ", &
                                               "GB82 TEST 1234 5698 7654 32       ", &
                                               "GR16 0110 1250 0000 0001 2300 695 ", &
                                               "GB29 NWBK 6016 1331 9268 19       ", &
                                               "SA03 8000 0000 6080 1016 7519     ", &
                                               "CH93 0076 2011 6238 5295 7        ", &
                                               "IL62 0108 0000 0009 9999 999      ", &
                                               "IL62-0108-0000-0009-9999-999      ", &
                                               "US12 3456 7890 0987 6543 210      ", &
                                               "GR16 0110 1250 0000 0001 2300 695X" /)

    integer :: i
    
    do i=1, size(ibans)
        if (checkIBAN(trim(ibans(i)))) then
            print *, "  valid IBAN: ", trim(ibans(i))
        else
            print *, "invalid IBAN: ", trim(ibans(i))
        end if
    end do

    return
 
contains

    function checkIBAN(ibancode) result(valid)
        character(len=*), intent(in) :: ibancode
        character(len=len(ibancode)) :: iban
        logical :: valid
        integer(int32) :: j, ascii, ibanSize 
        character(100) :: ibanRearrange, ibantoint
        character(2) :: temp
        valid = .false.

        iban = remove_blanks(ibancode)
        ibanSize = checkCountryCode(iban)
        if (ibanSize == len(trim(iban))) then
            ibanRearrange = iban(5:ibanSize)//iban(1:4)
            ibantoint = ""
            do j=1, ibanSize
                ascii = ichar(ibanRearrange(j:j))
                if ((ascii >= 65) .and. (ascii<=90)) then
                    write (temp,fmt='(I2)') ascii-55
                    ibantoint = trim(ibantoint) // temp
                else
                    ibantoint = trim(ibantoint) // ibanRearrange(j:j)
                end if 
            end do
            if (mod97(ibantoint) == 1) then
                valid = .true.
            end if
        end if
    end function checkIBAN
    
    function mod97(strint) result(res)
        character(len=*), intent(in) :: strint
        integer :: i, num, res
        res = 0
        do  i=1, len(trim(strint))
            read(strint(i:i),*) num
            res = mod((res*10 + num),97);
        end do
    end function mod97

    function checkCountryCode(iban) result(ibanlength)
        character(len=*), intent(in) :: iban
        integer(int16) :: ibanlength, i
        ibanlength = 0
        do i=1, size(cc)
            if (iban(1:2) == cc(i)(1:2)) then
                read(cc(i)(3:4),*) ibanlength
                exit
            end if
        end do
    end function checkCountryCode
 
    Recursive Function Stripper(string,ch) Result(stripped)
        Implicit None
        character(len=*), intent(in) :: string
        character, intent(in) :: ch
        character(:), allocatable :: stripped

        IF (LEN(string)==1) THEN
           IF (string==ch) THEN 
              stripped = ''
           ELSE
              stripped = string
           END IF
        ELSE
           IF (string(1:1)==ch) THEN
              stripped = stripper(string(2:),ch)
           ELSE
              stripped = string(1:1)//stripper(string(2:),ch)
           END IF
        END IF
    END Function stripper

    Function Remove_Blanks(string) Result(stripped)
        Implicit None
        character(len=*), intent(in) ::   string
        character(:), allocatable :: stripped

        stripped = trim(Stripper(trim(Stripper(string,' ')),achar(9)))
    END Function Remove_Blanks

end program ibancheck