home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / graph+ / part03 / readtab.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-03-01  |  4.7 KB  |  246 lines

  1. /*
  2.  * Copyright (C) 1986   Alan Kent
  3.  *
  4.  * Permission is granted to freely distribute part or
  5.  * all of this code as long as it is not for profit
  6.  * and this message is retained in the code.
  7.  *
  8.  * No resposibility is taken for any damage or incorect
  9.  * results this program generates.
  10.  * 
  11.  */
  12.  
  13.  
  14. #include <stdio.h>
  15. #include <ctype.h>
  16. #include <math.h>
  17. #include "graph.h"
  18.  
  19.  
  20. #define BUF_SIZE    512
  21.  
  22.  
  23. extern double log10 ();
  24. extern double pow ();
  25. extern table_st *new_table ();
  26.  
  27.  
  28. table_st *
  29. read_table ( filename , num_cols , num_rows )
  30. char *filename;
  31. int num_cols , num_rows;
  32. {
  33.     char *skip_blanks ();
  34.     char *scan_value ();
  35.  
  36.     char buf[ BUF_SIZE ];
  37.     char *p;
  38.     FILE *fp;
  39.     int rows , cols , i;
  40.     table_st *table , *tp;
  41.     double val;
  42.  
  43.  
  44.     /* first, open the file */
  45.  
  46.     if ( ( fp = fopen ( filename , "r" ) ) == NULL )
  47.     abort ( "failed to open file '%s'" , filename );
  48.     
  49.     if ( num_cols < 0 || num_rows < 0 ) {
  50.  
  51.     /* pass one of file: count rows and cols */
  52.  
  53.     rows = 0;
  54.     cols = 0;
  55.     do {
  56.         if ( fgets ( buf , BUF_SIZE , fp ) == NULL ) {
  57.         /* empty data file */
  58.         fclose ( fp );
  59.         return ( NULL );
  60.         }
  61.     } while ( *skip_blanks ( buf ) == '\0' );
  62.     p = skip_blanks ( buf );
  63.     while ( *p != '\0' ) {
  64.         cols++;
  65.         p = scan_value ( p , &val );
  66.         if ( p == NULL )
  67.         abort ( "Data file '%s' contains non-numeric data" , filename );
  68.         p = skip_blanks ( p );
  69.     }
  70.     rows++;
  71.     while ( fgets ( buf , BUF_SIZE , fp ) != NULL ) {
  72.         if ( *skip_blanks ( buf ) != '\0' )
  73.         rows++;
  74.     }
  75.  
  76.     /* allocate and read new table */
  77.  
  78.     rewind ( fp );
  79.     }
  80.     else {
  81.     rows = num_rows;
  82.     cols = num_cols;
  83.     }
  84.  
  85.     /*
  86.     printf ( "Data file '%s' contains %d columns and %d rows of data\n" ,
  87.     filename , cols , rows );
  88.     */
  89.  
  90.     table = new_table ( cols , rows );
  91.     i = 0;
  92.     while ( fgets ( buf , BUF_SIZE , fp ) != NULL  &&  i < rows ) {
  93.     if ( *skip_blanks ( buf ) != '\0' ) {
  94.         tp = table;
  95.         p = skip_blanks ( buf );
  96.         while ( *p != '\0' ) {
  97.         if ( tp == NULL )
  98.             break;
  99.         p = scan_value ( p , &val );
  100.         if ( p == NULL )
  101.             abort ( "illegal data on data file '%s'" , filename );
  102.         p = skip_blanks ( p );
  103.         tp->data[i] = val;
  104.         tp = tp->next;
  105.         }
  106.         i++;
  107.         if ( tp != NULL )
  108.         abort ( "line too short in data file '%s'" , filename );
  109.     }
  110.     }
  111.  
  112.     /* if table size got from parameters, it is possible that the table */
  113.     /* allocated has more rows than was specified (cols are reported as */
  114.     /* an error). This is alright, but the table should be shrunk in size. */
  115.     /* note that as malloc() does not care about our table size, it does not */
  116.     /* matter if the size field is larger than the actual table. */
  117.  
  118.     for ( tp = table; tp != NULL; tp = tp->next )
  119.     tp->size = i;
  120.  
  121.     fclose ( fp );
  122.     return ( table );
  123. }
  124.  
  125.  
  126.  
  127. char *
  128. scan_value ( in_str , pval )
  129. char *in_str;
  130. double *pval;
  131. {
  132.     register char *str;
  133.     int sign;
  134.     int num_digits;
  135.     register int exponent;
  136.     int exp2;
  137.     double val;
  138.  
  139.  
  140.     str = in_str;    /* register variable for SPEED */
  141.  
  142.     /* get leading +/- sign */
  143.  
  144.     sign = 1;
  145.     if ( *str == '+' )
  146.     str++;
  147.     else if ( *str == '-' ) {
  148.     str++;
  149.     sign = -1;
  150.     }
  151.  
  152.     /* get digit string */
  153.  
  154.     num_digits = 0;
  155.     val = 0.0;
  156.     exponent = 0;
  157.     while ( isdigit ( *str ) ) {
  158.     val = val * 10.0 + ( *str - '0' );
  159.     str++;
  160.     num_digits++;
  161.     }
  162.     if ( *str == '.' ) {
  163.     str++;
  164.     while ( isdigit ( *str ) ) {
  165.         val = val * 10.0 + ( *str - '0' );
  166.         exponent--;
  167.         str++;
  168.         num_digits++;
  169.     }
  170.     }
  171.  
  172.     if ( num_digits == 0 )
  173.     return ( NULL );
  174.     
  175.     if ( sign < 0 )
  176.     val = -val;
  177.     
  178.     if ( *str == 'e'  ||  *str == 'E' ) {
  179.     str++;
  180.     sign = 1;
  181.     if ( *str == '+' )
  182.         str++;
  183.     else if ( *str == '-' ) {
  184.         str++;
  185.         sign = -1;
  186.     }
  187.     if ( ! isdigit ( *str ) )
  188.         return ( NULL );
  189.     exp2 = 0;
  190.     while ( isdigit ( *str ) ) {
  191.         exp2 = exp2 * 10 + ( *str - '0' );
  192.         str++;
  193.     }
  194.     if ( sign < 0 )
  195.         exp2 = -exp2;
  196.     exponent += exp2;
  197.     }
  198.  
  199.     /* now, merge the value and the exponent */
  200.     /* anyone know a PORTABLE and fast way of doing this accurately? */
  201.     /* Using the log functions can introduce errors */
  202.  
  203.     if ( exponent < -12  ||  exponent > 12 ) {
  204.     /* For speed, use pow for large exponents */
  205.     val *= pow ( 10.0 , (double)exponent );
  206.     }
  207.     else {
  208.     while ( exponent < 0 ) {
  209.         val *= 0.1;
  210.         exponent++;
  211.     }
  212.     while ( exponent > 0 ) {
  213.         val *= 10.0;
  214.         exponent--;
  215.     }
  216.     }
  217.  
  218.     *pval = val;
  219.  
  220. #ifdef USING_ATOF
  221.     /* this requires scanning the string twice and does not detect */
  222.     /* errors at all */
  223.     str = in_str;
  224.     *pval = atof ( str );
  225.     while ( *str != '\0'  &&  ! isspace ( *str ) )
  226.     str++;
  227. #endif
  228.  
  229.     return ( str );
  230. }
  231.  
  232.  
  233.  
  234. static char *
  235. skip_blanks ( str )
  236. char *str;
  237. {
  238.     while ( isspace ( *str ) )
  239.     str++;
  240.     if ( *str == '#' )
  241.     while ( *str != '\0' )
  242.         str++;
  243.     return ( str );
  244. }
  245.  
  246.