home *** CD-ROM | disk | FTP | other *** search
/ Program Metropolis - Software Boutique 95 / SOFTWARECD.iso / stat45 / disk1 / develop.exe / DEMO.C next >
Encoding:
C/C++ Source or Header  |  1992-12-02  |  11.6 KB  |  352 lines

  1. /*===========================================================================*/
  2. /*                                                                           */ 
  3. /* This program demonstrates basic operations on a CSS data file. It will    */
  4. /* read a CSS raw data file, print its basic characteristics (including      */
  5. /* alphanumeric values for the second variable in the data file), and then   */
  6. /* create a new CSS data file with one additional variable.  That variable   */
  7. /* will contain the sum of all variables in the input file.  Arguments (input*/
  8. /* file name, output file name) are passed by command line (from DOS) in the */
  9. /* following manner:                                                         */
  10. /*                                                                           */
  11. /*                       demo input output                                   */
  12. /*                                                                           */
  13. /* This program was developed using a standard subset of the C language, and */
  14. /* it is ANSI compatible.                                                    */
  15. /* Enclosed demo.exe was created with Microsoft C 7.00 using command         */
  16. /*   cl demo.c                                                               */
  17. /*===========================================================================*/
  18.  
  19.  
  20. #include   <stdio.h>
  21. #include   <stdlib.h>
  22.  
  23. #include "demo.h"
  24.  
  25. FILE   *in,   /* input stream */
  26.       *out;   /* output stream */
  27.  
  28. struct   HeadTag   InHeader,   /* header of input file */
  29.                   OutHeader;   /* header of output file */
  30. struct   InfoTag   InArray,    /* information array about input file */
  31.                   OutArray;    /* information array about output file */
  32.  
  33. main(argc,argv)
  34. int argc;
  35. char * argv[];
  36.    /*-- get arguments from command line --*/
  37.    if ( argc <= 2 ) {
  38.       printf("\n To use program enter \ndemo inp_file out_file\n");
  39.       exit(1);
  40.    }
  41.    in = fopen( argv[1], "rb");
  42.    if ( in == NULL ){
  43.       printf("\n Cannot open input file.\n");
  44.       exit(1);
  45.    }
  46.  
  47.    /*-- initializing data structures for the input file --*/
  48.    InitInputFile();
  49.  
  50.    /*-- printing some information about input file --*/
  51.    PrintInputInfo();
  52.  
  53.    /*-- creating second (output) file --*/
  54.    out = fopen( argv[2], "wb");
  55.    if ( in == NULL ){
  56.       printf("\n Cannot create output file.\n");
  57.       exit(1);
  58.    }
  59.  
  60.    /*-- creating information header for output file; writing it to disk --*/
  61.    CreateOutputHeader();
  62.  
  63.    /*-- processing data for output file --*/
  64.    ProcessData();
  65.  
  66.    /*-- closing files and exiting --*/
  67.    fclose(in);
  68.    fclose(out);
  69.    printf("\nNormal program termination.\n");
  70.    exit(0);
  71. }
  72.  
  73. /*------------------------------- end of main ----------------------------------*/
  74.  
  75. void   InitInputFile(void)
  76. /*-- read from disk basic information about input file and store it in
  77.    InHeader and InArray structures --*/
  78. {
  79.    fread( &InHeader, SizeFH, 1, in);
  80.    if ( memcmp( InHeader.Title, "CSS ", 4 ) ||
  81.         (InHeader.Code != -9876L && InHeader.Code != -9877L) ) {
  82.       printf(" This is not a CSS raw data file.");
  83.       exit(1);
  84.    }
  85.    if ( InHeader.NV <= 1 ){
  86.       printf(" The input file for this program must contain at least two variables.");
  87.       exit(1);
  88.    }
  89.    if ( InHeader.NV >= 300 ){
  90.       printf(" Number of variables must not exceed 300. ");
  91.       exit(1);
  92.    }
  93.    switch ((int) InHeader.NArr ){
  94.       case 5 :
  95.          InHeader.SL1Len = 0;
  96.          InHeader.SL2Len = 0;
  97.       case 7 :
  98.          InHeader.SL3Len = 0;
  99.    }
  100.    fseek( in, 24 + InHeader.NArr * 2, SEEK_SET);
  101.    fread( &InArray, SizeFI, 1, in);
  102. }
  103.  
  104. /*------------------------------- end of InitInputFile -------------------------*/
  105.  
  106. void   PrintInputInfo(void)
  107. {
  108.    char Name[8];
  109.    union ValueTag MD;
  110.    long Offset;
  111.    struct FmTag Format;
  112.    int NbAlpha,NbRead,i;
  113.    long OffsAlpha;
  114.    struct LabTag Alpha[10];
  115.  
  116.    printf("\nInput file characteristics:\n Variables: %ld\n Cases: %ld\n Precision: %ldB\n",
  117.           InHeader.NV,InHeader.NC,InHeader.Prec);
  118.    if ( InHeader.Code == -9877L )
  119.       printf("\n This is a STATISTICA/W data file\n");
  120.    /*-- now print specifications for the second variable --*/
  121.    Offset = 24L + 2 * InHeader.NArr + InHeader.NCLen + InHeader.HLen;
  122.    /*-- find name --*/
  123.    fseek( in, Offset + 8, SEEK_SET);
  124.    fread( Name, 8, 1, in);
  125.    Offset += InHeader.VLen;
  126.    fseek( in, Offset + 2, SEEK_SET);
  127.    fread( &Format, 2, 1,in);
  128.    Offset += InHeader.FLen;
  129.    fseek( in, Offset + InHeader.Prec, SEEK_SET);
  130.    fread( &MD, (int)InHeader.Prec, 1, in);
  131.    printf("\nSpecifications for second variable:\n");
  132.    printf(" Name: %.8s\n",Name);
  133.    if ( InHeader.Prec == 4 )
  134.       printf(" MD Code: %f\n",MD.f);
  135.    else
  136.       printf(" MD Code: %lf\n",MD.d);
  137.    printf(" Format: width = %d, decimal = %d\n",(int)Format.Nz,(int)Format.Nd);
  138.    if ( InHeader.NArr >= 7 ){
  139.       /*-- if alphanumeric value labels exist, find out how many--*/
  140.       Offset += InHeader.MDLen;
  141.       fseek( in, Offset + 2, SEEK_SET);
  142.       fread( &NbAlpha, 2, 1, in);
  143.       if ( NbAlpha ){
  144.          /*-- find where they begin --*/
  145.          Offset += InHeader.SL1Len;
  146.          fseek( in, Offset + 4, SEEK_SET);
  147.          fread( &OffsAlpha, 4, 1, in);
  148.          Offset += InHeader.SL2Len;
  149.          /*-- here the offsets to long value labels begin --*/
  150.          Offset += InHeader.SL3Len;
  151.          /*-- here the long variable names begin --*/
  152.          Offset += InArray.MemVar;
  153.          /*-- here alphanumerics starts --*/
  154.          fseek( in, Offset + OffsAlpha, SEEK_SET);
  155.          /*-- read first 10 alphanumeric specification --*/
  156.          fread( Alpha, SizeLT, NbRead = min( NbAlpha, 10), in);
  157.          printf(" Number of alphanumerics: %d\n",NbAlpha);
  158.          for ( i = 0 ; i < NbRead; i++ )
  159.             printf(" Alpha: %.8s Value: %f\n",Alpha[i].T,Alpha[i].V);
  160.       }
  161.       else
  162.          printf(" Second variable contains now alphanumeric value labels\n");
  163.    }
  164.    else
  165.       printf(" There are no alphanumeric value labels in this file.\n");
  166. }
  167.  
  168. /*------------------------------- end of PrintInputInfo ------------------------*/
  169.  
  170. void   CreateOutputHeader(void)
  171. /*-create output file header, make changes to accomodate additional variable-*/
  172. {
  173.    union ValueTag MD;
  174.    int NbAlpha;
  175.    long OffsAlpha,OffsLongAlpha;
  176.  
  177.    /*-- copy basic information --*/
  178.    memcpy( &OutHeader, &InHeader, SizeFH );
  179.    /* we are going to create CSS (not STAT/W) data file;
  180.       STAT/W will read CSS data file */
  181.    OutHeader.Code = -9876L;
  182.    OutHeader.NV++;
  183.    OutHeader.VLen += 8;
  184.    OutHeader.FLen += 2;
  185.    OutHeader.MDLen += OutHeader.Prec;
  186.    if ( OutHeader.SL1Len )
  187.       OutHeader.SL1Len += 2;
  188.    if ( OutHeader.SL2Len )
  189.       OutHeader.SL2Len += 4;
  190.    if ( OutHeader.SL3Len )
  191.       OutHeader.SL3Len += 4;
  192.    fwrite( &OutHeader, (unsigned int)(24 + OutHeader.NArr * 2), 1, out);
  193.  
  194.    /*-- copy information array --*/
  195.    memcpy( &OutArray, &InArray, SizeFI );
  196.    OutArray.ExtraInfo = 0L;
  197.    fwrite( &OutArray, SizeFI, 1, out);
  198.  
  199.    /*-- copy text header --*/
  200.    fseek( in, 24 + OutHeader.NArr * 2 + SizeFI, SEEK_SET );
  201.    fcopy( out, in, 80);
  202.  
  203.    /*-- variable names --*/
  204.    fwrite( "     SUM", 8, 1, out);
  205.    fcopy( out, in, InHeader.VLen);
  206.  
  207.    /*-- variable formats --*/
  208.    fwrite( "", 2, 1, out); /*-- create default 8.3 --*/
  209.    fcopy( out, in, InHeader.FLen);
  210.  
  211.    /*-- MD codes --*/
  212.    if ( InHeader.Prec == 4 )
  213.       MD.f = (float)-9999.0;
  214.    else
  215.       MD.d = -9999.0;
  216.    fwrite( &MD, (int)InHeader.Prec, 1, out);
  217.    fcopy( out, in, InHeader.MDLen );
  218.  
  219.    /*-- number of alphanumeric value labels --*/
  220.    if ( InHeader.SL1Len ){
  221.       NbAlpha = 0;
  222.       fwrite( &NbAlpha, 2, 1, out);
  223.       fcopy( out, in, InHeader.SL1Len );
  224.    }
  225.  
  226.    /*-- offset to alphanumeric value labels --*/
  227.    if ( InHeader.SL2Len ){
  228.       OffsAlpha = 0L;
  229.       fwrite( &OffsAlpha, 4, 1, out);
  230.       fcopy( out, in, InHeader.SL2Len );
  231.    }
  232.  
  233.    /*-- offset to long alphanumeric value labels --*/
  234.    if ( InHeader.SL3Len ){
  235.       OffsLongAlpha = 0L;
  236.       fwrite( &OffsLongAlpha, 4, 1, out);
  237.       fcopy( out, in, InHeader.SL3Len );
  238.    }
  239.  
  240.    /*-- long variable names (labels/formulas) --*/
  241.    fcopy( out, in, (unsigned int)OutArray.MemVar);
  242.  
  243.    /*-- short alphanumeric values for all variables;
  244.       NOTE: make sure that third argument in fcopy is not larger than
  245.       the max unsigned integer value; otherwise write your own fcopy routine --*/
  246.    fcopy( out, in, (unsigned int)OutArray.MemSvl);
  247.  
  248.    /*-- long alphanumerics - same as above --*/
  249.    fcopy( out, in, (unsigned int)OutArray.MemLvl);
  250. }
  251.  
  252. /*----------------------------- end of CreateOutputHeader ----------------------*/
  253.  
  254. void   ProcessData(void)
  255. /*-- copy data, process each case and compute the sum of variables;
  256.    we assume that the file pointers are at the end of header specifications 
  257.    and at the bginning of the data for both files --*/
  258. {
  259.    double * pD,sumD;
  260.    float * pF,sumF;
  261.    long Offset,i;
  262.    int RecordLen,j;
  263.    BYTE * pData;
  264.    char CaseName[20];
  265.  
  266.    /* get offset on input file */
  267.    Offset = ftell( in );
  268.    /* in case of STATISTICA/W we must skip some part of input data file */
  269.    if ( InHeader.Code == -9877L )
  270.       Offset += InArray.ExtraInfo;
  271.    /*-- first move pointers to nearest multiply of 512B --*/
  272.    Ceil512( &Offset );
  273.    fseek( in, Offset, SEEK_SET );
  274.    Offset = ftell( out );
  275.    Ceil512( &Offset );
  276.    fseek( out, Offset, SEEK_SET );
  277.  
  278.    /*-- next allocate memory for one record of data --*/
  279.    if ( (pData = malloc( (unsigned int)(InHeader.Prec*InHeader.NV) )) == NULL ){
  280.       printf("\n Memory allocation error.");
  281.       exit(1);
  282.    }
  283.  
  284.    /*-- process data --*/
  285.    for ( i = 0, RecordLen = (int)(InHeader.Prec * InHeader.NV);
  286.          i < InHeader.NC;
  287.          i++ ){
  288.       if ( InArray.LCName > 0 ){
  289.          fread( CaseName, (int)InArray.LCName, 1, in);
  290.          fwrite( CaseName, (int)InArray.LCName, 1, out);
  291.       }
  292.       fread( pData, RecordLen, 1, in);
  293.       if (InHeader.Prec == 4) {
  294.          /*-- compute sum of variables --*/
  295.          for ( j = 0, sumF = (float)0, pF = (float *)pData;
  296.                j < InHeader.NV;
  297.                j++, pF++ )
  298.             sumF += *pF;
  299.          /*-- write results to output file --*/
  300.          fwrite( &sumF, 4, 1, out);
  301.       }
  302.       else {
  303.          /*-- compute sum of variables --*/
  304.          for ( j = 0, sumD = (double)0, pD = (double *)pData;
  305.                j < InHeader.NV;
  306.                j++, pD++ )
  307.             sumD += *pD;
  308.          /*-- write results to output file --*/
  309.          fwrite( &sumD, 8, 1, out);
  310.       }
  311.       /*-- write remaining part of record to the output --*/
  312.       fwrite( pData, RecordLen, 1, out);
  313.    }
  314.    /*-- free allocated memory buffer --*/
  315.    free(pData);
  316. }
  317.  
  318. /*-------------------------------- end of ProcessData --------------------------*/
  319.  
  320. void fcopy( FILE * out, FILE * in, unsigned int size )
  321. /*-- copy SIZE bytes from input stream to output stream using dynamically
  322.    allocated buffer --*/
  323. {
  324.    BYTE * p;
  325.  
  326.    if ( size == 0 )
  327.       return;
  328.    if ( (p = malloc(size)) == NULL ){
  329.       printf("\n Memory allocation error.");
  330.       exit(1);
  331.    }
  332.    fread( p, size, 1, in);
  333.    fwrite( p, size, 1, out);
  334.    free(p);
  335. }
  336.  
  337. /*--------------------------------- end of fcopy -------------------------------*/
  338.  
  339. void Ceil512( long * pL )
  340. /*-- adjust number to nearest multiple of 512 --*/
  341. {
  342.   ldiv_t S;
  343.  
  344.   S = ldiv( *pL, 512L );
  345.   if ( S.rem != 0L )
  346.      *pL = (S.quot + 1L) * 512L;
  347. }
  348.  
  349. /*--------------------------------- end of Ceil512 ------------------------------*/
  350.  
  351.