|
|
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 );
}