/*
* This implementation of the above algorithm has some distinct   
* limitations, although I believe they are not a serious problem.   
* This is intended for processing short strings of digits (10 or so),   
* not arbitrarily long digit strings. Each of the substrings that are   
* broken out by the code below are assumed to be a value that can   
* be assigned to a long when converted to an integral type. This   
* limitation requires that the input string not be more than about 20   
* characters in length, which is more than adequate for the intended   
* application. I'm assuming that a long is at least 32 bits.      
* Further, it assumes a character set where the digits' collating   
* sequence mimics that of ASCII, so that things like:   
*      x = val - '0';   
* will evaluate to an integer value of 3 in the case where val == '3'.   
*/     

#include <stdio.h>     
#define MOD10 10  
#define MOD11 11        
/*   
* ----------------------------- check_digit() -------------------   *   
* Calculates a check digit according to the algorithm given above. 
* NOTE   
* that there are no checks for array bounds overflow. Beware.   
*/     
     check_digit (string, mod)      
     char * string;      
     int mod;      
          {
          char tmpbuf[20];      
          int i, j, sum;      
          unsigned long odd, even;         
     /* extract the odd digits */      
     j = strlen (string);      
     for ( j--, i = 0 ; j >= 0 ; j -= 2, i++ )
          {          
          tmpbuf[i] = string[j];          
          }
     tmpbuf[i] = '\0';      
     odd = atol (tmpbuf);         
     /* extract the even digits */      
     j  = strlen (string);      
     for ( j -= 2, i = 0 ; j >= 0 ;  j -= 2, i++ )          
          {
          tmpbuf[i] = string[j];
          }
          tmpbuf[i] = '\0';      
          even = atol (tmpbuf);         
     /* now make the composite string & sum the digits */      
     sprintf (tmpbuf, "%lu%lu", even, 2L * odd);      
     i  = strlen (tmpbuf);      
     for ( sum = j = 0 ; j < i ; j++)          
          {
          sum += tmpbuf[j] - '0';          
          }
     /* now do the mod10 or mod11 operation */  
      i = (mod - (sum % mod));      
     if (i == mod)          
          i = 0;      
     return (i);      
     }
#ifdef TEST  
     main ()      
     {
      char buf[30];         
     while (1)          
          {
          gets (buf);          
          if (strlen (buf) == 0)  
               break;          
          printf ("string: %s, mod10 checkdigit: %d, "
               "mod11 checkdigit %d:n",  
               buf, check_digit (buf, MOD10), 
               check_digit (buf, MOD11));          
          }
     }
#endif /* TEST */     

