home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_03_01 / 3n01018a < prev    next >
Text File  |  1991-11-19  |  11KB  |  252 lines

  1. /* tech.c
  2.    An "international" sort example program.
  3.    Author:   Peter Gulutzan, Ocelot Computer Services Inc. (403) 421-4187
  4.    Date:     March 17, 1991
  5.    For:      TECH Specialist
  6.    Language: C (tested with Borland C++ and Zortech C++ compilers)
  7.              (If compiling with Zortech: remove the "#include <mem.h>" line)
  8.    Remarks:  This program will ask the alphabet to use.  Then it opens the
  9.              file INPUT.TXT, translates the strings in it to coded
  10.              tags, sorts with the standard qsort() routine supplied by the
  11.              compiler manufacturer, and outputs to file OUTPUT.TXT.
  12.    Limits:   Tags are chopped to be a maximum 20-character size: MAXTAGSIZE.
  13.              Only Characters are sorted.  Digits and punctuation go low.
  14.              The maximum number of tags is 1000: MAXTAGS.
  15.              Qsort() requires that all the tags be in RAM.
  16.    Note:     This only covers a few sets (French, Danish, German, Polish
  17.              and Spanish) to show how it can be done. */
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <mem.h>        /* Remove this line if compiling with Zortech */
  23.  
  24. #define MAXTAGS         1000
  25. #define MAXTAGSIZE      20
  26. #define M               (MAXTAGSIZE)
  27.  
  28. #define FRENCH  0
  29. #define DANISH  1
  30. #define GERMAN  2
  31. #define POLISH  3
  32. #define SPANISH 4
  33.  
  34. /* Definitions of plain-text equivalents.
  35.    Note how we leave interstices, e.g. A=3, B=6, C=9 etc. */
  36. #define __      1                               /* "unknown" or blank */
  37. #define A_      __+2
  38. #define B_      A_+3
  39. #define C_      B_+3
  40. #define D_      C_+3
  41. #define E_      D_+3
  42. #define F_      E_+3
  43. #define G_      F_+3
  44. #define H_      G_+3
  45. #define I_      H_+3
  46. #define J_      I_+3
  47. #define K_      J_+3
  48. #define L_      K_+3
  49. #define M_      L_+3
  50. #define N_      M_+3
  51. #define O_      N_+3
  52. #define P_      O_+3
  53. #define Q_      P_+3
  54. #define R_      Q_+3
  55. #define S_      R_+3
  56. #define T_      S_+3
  57. #define U_      T_+3
  58. #define V_      U_+3
  59. #define W_      V_+3
  60.  
  61. #define X_      W_+3
  62. #define Y_      X_+3
  63. #define Z_      Y_+3
  64.  
  65.   /* The first 128 characters are always the same as defined in  7-bit ASCII.
  66.      Note how we use leave interstices, e.g. A=3, B=6, C=9, etc. */
  67.   char base[128]=  {0,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  68.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  69.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  70.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  71.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  72.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  73.                    __,  __,  __,  __,  __,  A_,  B_,  C_,  D_,  E_, 
  74.                    G_,  H_,  I_,  J_,  K_,  L_,  M_,  N_,  O_,  P_,
  75.                    P_,  Q_,  R_,  S_,  T_,  U_,  V_,  W_,  X_,  Y_, 
  76.                    Z_,  __,  __,  __,  __,  __,  __,  A_,  B_,  C_, 
  77.                    D_,  E_,  F_,  G_,  H_,  I_,  J_,  K_,  L_,  M_, 
  78.                    N_,  O_,  P_,  Q_,  R_,  S_,  T_,  U_,  V_,  W_, 
  79.                    X_,  Y_,  Z_,  __,  __,  __,  __,  __};
  80.   /* Extended characters for French (assumes code page 437) */
  81.   char _fren[128]={C_,  U_, 
  82.                    E_,  A_,  A_,  A_,  A_,  C_,  E_,  E_,  E_,  I_, 
  83.                    I_,  I_,  A_,  A_,  E_,  __,  __,  O_,  O_,  O_, 
  84.                    U_,  U_,  Y_,  O_,  U_,  __,  __,  __,  __,  __, 
  85.                    A_,  I_,  O_,  U_,  N_,  N_,  __,  __,  __,  __, 
  86.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  87.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  88.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  89.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  90.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  91.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  92.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  93.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  94.                    __,  __,  __,  __,  __,  __};
  95.   /* Extended characters for Danish (assumes code page 865)
  96.      NB: Some provision is made for other Scandinavian sets, e.g. 231
  97.      would be the Icelandic thorn if you were using code page 861. */
  98.   char _dani[128]={C_,  U_,
  99.                    E_,  A_,5+Z_,  A_,4+Z_,  C_,  E_,  E_,  E_,  I_, 
  100.                    I_,  I_,5+Z_,4+Z_,  E_,2+Z_,2+Z_,  O_,6+Z_,  O_, 
  101.                    U_,  U_,  Y_,6+Z_,  U_,3+Z_,  __,3+Z_,  __,  __, 
  102.                    A_,  I_,  O_,  U_,  N_,  N_,  __,  __,  __,  __, 
  103.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  104.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  105.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  106.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  107.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  108.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  109.                    __,1+Z_,1+Z_,  __,  __,  __,  __,  __,  __,  __, 
  110.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  111.                    __,  __,  __,  __,  __,  __};
  112.   /* Extended characters for Spanish (assumes code page 437) */
  113.   char _span[128]={C_,  U_,
  114.                    E_,  A_,  A_,  A_,  A_,  C_,  E_,  E_,  E_,  I_, 
  115.                    I_,  I_,  A_,  A_,  E_,  __,  __,  O_,  O_,  O_, 
  116.                    U_,  U_,  Y_,  O_,  U_,  __,  __,  __,  __,  __, 
  117.                    A_,  I_,  O_,  U_,1+N_,1+N_,  __,  __,  __,  __, 
  118.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  119.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  120.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  121.  
  122.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  123.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  124.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  125.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  126.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  127.                    __,  __,  __,  __,  __,  __};
  128.   /* Extended characters for Polish (assumes code page 852) */
  129.   char _poli[128]={C_,  U_,
  130.                    E_,  A_,  A_,  U_,1+C_,  C_,1+L_,  E_,  O_,  O_, 
  131.                    I_,1+Z_,  A_,1+C_,  E_,  L_,  L_,  O_,  O_,  L_, 
  132.                    L_,1+S_,1+S_,  O_,  U_,  T_,  T_,1+L_,  X_,  C_, 
  133.                    A_,  I_,1+O_,  U_,1+A_,1+A_,  Z_,  Z_,1+E_,1+E_, 
  134.                    __,1+Z_,  C_,  S_,  __,  __,  __,  __,  __,  __, 
  135.                    __,  A_,  A_,  E_,  S_,  __,  __,  __,  __,2+Z_, 
  136.                  3+Z_,  __,  __,  __,  __,  __,  __,  __,  A_,  A_, 
  137.                    __,  __,  __,  __,  __,  __,  __,  __,  D_,  D_, 
  138.                    D_,  E_,  D_,  N_,  I_,  I_,  E_,  __,  __,  __, 
  139.                    __,  T_,  U_,  __,1+O_,  __,  O_,  N_,  N_,  N_, 
  140.                    S_,  S_,  R_,  U_,  R_,  U_,  Y_,  Y_,  T_,  __, 
  141.                    __,  __,  __,  __,  __,  __,  __,  __,  __,  __, 
  142.                    __,  U_,  R_,  R_,  __,  __};
  143.  
  144.   char code_set[256];           /* e.g. = base + lan00 sets. */
  145.   unsigned int language;        /* 0=FRENCH, 1=DANISH, 2=SPANISH, etc. */
  146.  
  147. int comp_function (const void *a, const void *b);
  148. int getline(FILE *fp,char *a,const unsigned int b);
  149. void translate (char *s,char *t,unsigned int language,const unsigned int b);
  150. void putline (FILE *fp,char *s);
  151.  
  152. int main ()
  153. {
  154.   unsigned int i,j;
  155.   FILE *fopen(),*ifp,*ofp;
  156.   char tagarray[MAXTAGS * (MAXTAGSIZE+4)];
  157.   char s[255];
  158.   char *t;
  159.  
  160.   language=get_language();                              /* Get language */
  161.   memcpy(code_set,base,128);                            /* Create code set */
  162.   switch (language) {
  163.     case FRENCH: memcpy(code_set+128,_fren,128); break;
  164.     case DANISH: memcpy(code_set+128,_dani,128); break;
  165.     case GERMAN: memcpy(code_set+128,_fren,128); break;
  166.     case POLISH: memcpy(code_set+128,_poli,128); break;
  167.     case SPANISH: memcpy(code_set+128,_span,128); break; }
  168.   ifp=fopen("INPUT.TXT","r");                           /* Open input file */
  169.   for (i=0,t=tagarray; i<MAXTAGS; ++i,t+=MAXTAGSIZE+4) {/* Loop: */
  170.     t+=M; *((long int *) t)=ftell(ifp); t-=M;           /* Save orig pos */
  171.     if (getline(ifp,s,sizeof(s))<0) break;              /* Read. stop @eof */
  172.     translate(s,t,language,MAXTAGSIZE); }               /* Codify. */
  173.   if (i==MAXTAGS) printf("Only sorting 1000 records\n");
  174.   qsort((void *)tagarray,i,MAXTAGSIZE+4,comp_function); /* Standard sort! */
  175.   ofp=fopen("OUTPUT.TXT","w");                          /* Open output file */
  176.   for (j=0,t=tagarray; j<i; ++j,t+=MAXTAGSIZE+4) {      /* For each tag */
  177.     t+=M; fseek(ifp,*((long int *) t),0); t-=M;         /* Find original */
  178.     getline(ifp,s,sizeof(s));                           /* Read original */
  179.     putline(ofp,s); }                                   /* Write new */
  180.   printf("Done.\n");
  181.   return (0); }
  182.  
  183.  
  184. int get_language ()
  185. {
  186.   int i;
  187.  
  188.   for (;;) {
  189.     printf("Alphabets\n");
  190.     printf("---------\n");
  191.     printf("(0) French\n");
  192.     printf("(1) Danish\n");
  193.     printf("(2) German\n");
  194.     printf("(3) Polish\n");
  195.     printf("(4) Spanish\n");
  196.     printf("Enter a number corresponding to one of the above alphabets:");
  197.     scanf("%d",&i);
  198.     if (i>=0 && i<=4) return (i); } }
  199.  
  200. int getline (FILE *fp,char *a,const unsigned int b)
  201. {
  202.   unsigned int i;
  203.   int c;
  204.  
  205.   for (i=0;; ++i) {
  206.     c=getc(fp);
  207.     if (c==EOF) return (-1);
  208.     if (c=='\n') break;
  209.     if (i<b) *(a++)=c; }
  210.   *a='\0';
  211.   return (0); }
  212.  
  213. void translate (char *s,char *t,unsigned int language,const unsigned int b)
  214. {
  215.   unsigned int i;
  216.  
  217.   for (i=0; i<b-1;++i) {
  218.     if ( (*t=code_set[(unsigned char) *(s++)])=='\0') break;
  219.     if (i>0) {
  220.       switch (language) {                               /* digraph tests */
  221.         case SPANISH:
  222.           if (*t==L_ && *(t-1)==L_) *(t-1)=1+L_;                /* LL? */
  223.           else if (*t==H_ && *(t-1)==C_) *(t-1)=1+C_;           /* CH? */
  224.           else ++t;
  225.           break;
  226.         case GERMAN:
  227.           if ((unsigned char) *(s-1)==225) *(t-1)=*(t++)=S_;    /* eszet? */
  228.           ++t;
  229.           break;
  230.         default:
  231.           ++t;
  232.           break; } }
  233.     else ++t; }
  234.   *t='\0'; }
  235.  
  236. int comp_function (const void *a,const void *b)
  237. {
  238.   return (strcmp(a,b)); }
  239.  
  240. void putline (FILE *fp,char *s)
  241. {
  242.   int   c;
  243.  
  244.  
  245.   for (;;) {
  246.     c=*(s++);
  247.     if (c=='\0') {
  248.       putc('\n',fp);
  249.       break; }
  250.     putc(c,fp); } }
  251. /* End of File */
  252.