|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T r
Length: 4816 (0x12d0) Types: TextFile Names: »readtab.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/euug-87hel/sec1/graph/readtab.c«
/* * Copyright (C) 1986 Alan Kent * * Permission is granted to freely distribute part or * all of this code as long as it is not for profit * and this message is retained in the code. * * No resposibility is taken for any damage or incorect * results this program generates. * */ #include <stdio.h> #include <ctype.h> #include <math.h> #include "graph.h" #define BUF_SIZE 512 extern double log10 (); extern double pow (); extern table_st *new_table (); table_st * read_table ( filename , num_cols , num_rows ) char *filename; int num_cols , num_rows; { char *skip_blanks (); char *scan_value (); char buf[ BUF_SIZE ]; char *p; FILE *fp; int rows , cols , i; table_st *table , *tp; double val; /* first, open the file */ if ( ( fp = fopen ( filename , "r" ) ) == NULL ) abort ( "failed to open file '%s'" , filename ); if ( num_cols < 0 || num_rows < 0 ) { /* pass one of file: count rows and cols */ rows = 0; cols = 0; do { if ( fgets ( buf , BUF_SIZE , fp ) == NULL ) { /* empty data file */ fclose ( fp ); return ( NULL ); } } while ( *skip_blanks ( buf ) == '\0' ); p = skip_blanks ( buf ); while ( *p != '\0' ) { cols++; p = scan_value ( p , &val ); if ( p == NULL ) abort ( "Data file '%s' contains non-numeric data" , filename ); p = skip_blanks ( p ); } rows++; while ( fgets ( buf , BUF_SIZE , fp ) != NULL ) { if ( *skip_blanks ( buf ) != '\0' ) rows++; } /* allocate and read new table */ rewind ( fp ); } else { rows = num_rows; cols = num_cols; } /* printf ( "Data file '%s' contains %d columns and %d rows of data\n" , filename , cols , rows ); */ table = new_table ( cols , rows ); i = 0; while ( fgets ( buf , BUF_SIZE , fp ) != NULL && i < rows ) { if ( *skip_blanks ( buf ) != '\0' ) { tp = table; p = skip_blanks ( buf ); while ( *p != '\0' ) { if ( tp == NULL ) break; p = scan_value ( p , &val ); if ( p == NULL ) abort ( "illegal data on data file '%s'" , filename ); p = skip_blanks ( p ); tp->data[i] = val; tp = tp->next; } i++; if ( tp != NULL ) abort ( "line too short in data file '%s'" , filename ); } } /* if table size got from parameters, it is possible that the table */ /* allocated has more rows than was specified (cols are reported as */ /* an error). This is alright, but the table should be shrunk in size. */ /* note that as malloc() does not care about our table size, it does not */ /* matter if the size field is larger than the actual table. */ for ( tp = table; tp != NULL; tp = tp->next ) tp->size = i; fclose ( fp ); return ( table ); } char * scan_value ( in_str , pval ) char *in_str; double *pval; { register char *str; int sign; int num_digits; register int exponent; int exp2; double val; str = in_str; /* register variable for SPEED */ /* get leading +/- sign */ sign = 1; if ( *str == '+' ) str++; else if ( *str == '-' ) { str++; sign = -1; } /* get digit string */ num_digits = 0; val = 0.0; exponent = 0; while ( isdigit ( *str ) ) { val = val * 10.0 + ( *str - '0' ); str++; num_digits++; } if ( *str == '.' ) { str++; while ( isdigit ( *str ) ) { val = val * 10.0 + ( *str - '0' ); exponent--; str++; num_digits++; } } if ( num_digits == 0 ) return ( NULL ); if ( sign < 0 ) val = -val; if ( *str == 'e' || *str == 'E' ) { str++; sign = 1; if ( *str == '+' ) str++; else if ( *str == '-' ) { str++; sign = -1; } if ( ! isdigit ( *str ) ) return ( NULL ); exp2 = 0; while ( isdigit ( *str ) ) { exp2 = exp2 * 10 + ( *str - '0' ); str++; } if ( sign < 0 ) exp2 = -exp2; exponent += exp2; } /* now, merge the value and the exponent */ /* anyone know a PORTABLE and fast way of doing this accurately? */ /* Using the log functions can introduce errors */ if ( exponent < -12 || exponent > 12 ) { /* For speed, use pow for large exponents */ val *= pow ( 10.0 , (double)exponent ); } else { while ( exponent < 0 ) { val *= 0.1; exponent++; } while ( exponent > 0 ) { val *= 10.0; exponent--; } } *pval = val; #ifdef USING_ATOF /* this requires scanning the string twice and does not detect */ /* errors at all */ str = in_str; *pval = atof ( str ); while ( *str != '\0' && ! isspace ( *str ) ) str++; #endif return ( str ); } static char * skip_blanks ( str ) char *str; { while ( isspace ( *str ) ) str++; if ( *str == '#' ) while ( *str != '\0' ) str++; return ( str ); }