home *** CD-ROM | disk | FTP | other *** search
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "utils.h"
-
- #ifdef TESTING
- int
- main ()
- {
- int i, j, t, k, K, T;
- float **data;
- char *cstring, *ustring;
- char **labels;
- int *table, tablesize;
-
- #ifdef FROMSTDIN
- data = LoadFile ("-", &K, &T, FALSE, cstring, ustring,
- &labels, &table, &tablesize);
- if (data == NULL)
- return 1;
- printf ("K=%d, T=%d\n", K, T);
- for (t = 0; t < T; t++)
- {
- for (k = 0; k < K; k++)
- printf (" %f ", data[t][k]);
- printf ("\n");
- }
- return 0;
- #endif /* STDIN */
-
- /*--------------------------------------------------*/
- printf ("Input data file:\n");
- system ("cat demo.dat");
- printf ("\n");
-
- cstring = ustring = (char *) NULL;
- printf ("No picking of fields:\nExpect x y z\n");
- data = LoadFile ("demo.dat", &K, &T,
- FALSE, cstring, ustring, &labels, &table, &tablesize);
- if (NULL == data)
- {
- printf ("LoadFile failed.\n");
- return 1;
- }
-
- for (k = 0; k < K; k++)
- printf (" %s ", labels[k]);
- printf ("\n");
- for (t = 0; t < T; t++)
- {
- for (k = 0; k < K; k++)
- printf (" %f ", data[t][k]);
- printf ("\n");
- }
- printf ("\nMapping table:\n");
- for (i = 0; i < tablesize; i++)
- printf ("Table[%d] = %d\n", i, table[i]);
- printf ("\n");
-
-
- /*--------------------------------------------------*/
- cstring = strdup ("x y z");
- ustring = strdup ("z x");
- printf ("With picking of fields:\nExpect z x\n");
- data = LoadFile ("demo.dat", &K, &T,
- TRUE, cstring, ustring, &labels, &table, &tablesize);
- if (NULL == data)
- {
- printf ("LoadFile failed.\n");
- return 1;
- }
- for (k = 0; k < K; k++)
- printf (" %s ", labels[k]);
- printf ("\n");
- for (t = 0; t < T; t++)
- {
- for (k = 0; k < K; k++)
- printf (" %f ", data[t][k]);
- printf ("\n");
- }
- printf ("\nMapping table:\n");
- for (i = 0; i < tablesize; i++)
- printf ("Table[%d] = %d\n", i, table[i]);
- printf ("\n");
-
- return 0;
- }
-
- #endif /* TESTING */
-
- /* Look for a given words in a table of words */
- int
- findword (char *word, char **manywords, int maxwords)
- {
- int i;
-
- for (i = 0; i < maxwords; i++)
- if (0 == strcmp (word, manywords[i]))
- return i;
- return -1;
- }
-
- #define MAXFIELDS 1024
- /* When you change this, be sure to make implied changes in
- messages in err_mktable below. */
-
- /* Error codes */
- #define TOOMANYFIELDS_C -1 /* more than MAXFIELDS fields in cstring */
- #define TOOMANYFIELDS_U -2 /* more than MAXFIELDS fields in ustring */
- #define OUT_OF_MEMORY -3 /* ran out of RAM someplace. */
- #define USING_BUTNOT_CONTAINS -4 /* a variable in ustring but not in cstring */
-
- int
- mktable (char *safe_cstring, char *safe_ustring, int *cNF,
- int **table, int *tablesize, int *NumColumns,
- char ***labels)
- {
- char *cstring, *ustring;
- int uNF;
- static char *cwords[MAXFIELDS], *uwords[MAXFIELDS];
- int i, j;
-
- cstring = strdup (safe_cstring);
- ustring = strdup (safe_ustring);
- /* screw around with copies. */
-
- if (MAXFIELDS <= (*cNF = split (cstring, cwords, MAXFIELDS, "")))
- return TOOMANYFIELDS_C;
-
- if (MAXFIELDS <= (uNF = split (ustring, uwords, MAXFIELDS, "")))
- return TOOMANYFIELDS_U;
-
- *NumColumns = *tablesize = uNF;
- if (NULL == (*labels = (char **) malloc (uNF * sizeof (char *))))
- return OUT_OF_MEMORY;
- if (NULL == (*table = (int *) malloc (uNF * sizeof (int))))
- return OUT_OF_MEMORY;
-
- for (i = 0; i < uNF; i++)
- { /* processing for uwords[i] */
- (*labels)[i] = strdup (uwords[i]);
- j = findword (uwords[i], cwords, *cNF);
- if (j == -1)
- return USING_BUTNOT_CONTAINS;
- (*table)[i] = j;
- }
-
- free (cstring);
- free (ustring);
- return 0;
- }
-
- /* Converting error codes of mktable into strings; after K&R, page 113 */
- char *
- err_mktable (int n)
- {
- static char *messages[] =
- {
- /*0*/ "Error in call to err_mktable.",
- /*1*/ "'Contains' string contains too many variables; atmost 1024 allowed.",
- /*2*/ "'Using' string contains too many variables; atmost 1024 allowed.",
- /*3*/ "Out of Memory inside MkTable.",
- /*4*/ "There is a variable in 'Using' which is not in 'Contains'."
- };
-
- return (n < -4 || n > -1) ? messages[0] : messages[-n];
- }
-
-
- /* Function which takes
- string containing one line
- mapping table
- and returns
- pointer to float * which contains required numbers.
- */
-
- float *
- mkrowptr (char *line, int expectNF, int *table, int tablesize)
- {
- float *tmp; /* this is the array which will be built up. */
- char *words[MAXFIELDS];
- int i, NF;
-
- if (expectNF != (NF = split (line, words, MAXFIELDS, "")))
- return NULL;
-
- tmp = (float *) malloc (tablesize * sizeof (float));
- for (i = 0; i < tablesize; i++)
- tmp[i] = (float) atof (words[table[i]]); /* atof is slow! */
-
- return tmp;
- }
-
- #define INITIALSIZE 100
- #define GROWTHFACTOR 1.5
- /* the float** starts off as INITIALSIZE row pointers.
- Each time the data gets bigger than it's current size,
- the size is increased by a factor of GROWTHFACTOR. */
-
- #define MAXCHARSINLINE 16384
- /* Largest line we can read from input file. */
-
- float **
- LoadFile (char *dfname,
- int *NumColumns, int *ObsNum,
- int pickfields, char *cstring, char *ustring,
- char ***labels, int **table, int *tablesize)
- {
- int errorcode;
- float **data;
- int capacity, rows;
- char *linebuffer; /* one line from data file starts off here. */
- FILE *filehandle;
- char *words[MAXFIELDS];
- int i, NF, cNF;
- char *hiteof, *linecopy;
- float *p;
- if (0 == (strncmp (dfname, "-", 1)))
- filehandle = stdin;
- else
- {
- if (NULL == (filehandle = fopen (dfname, "r")))
- {
- fprintf (stderr, "Failed to open file %s.\n", dfname);
- return NULL;
- }
- }
- if (pickfields == TRUE)
- {
-
- errorcode = mktable (cstring, ustring, &cNF, table,
- tablesize, NumColumns, labels);
-
- if (errorcode < 0)
- {
- fprintf (stderr, "%s", err_mktable (errorcode));
- return NULL;
- }
- }
-
- data = (float **) malloc (INITIALSIZE * sizeof (float *));
- capacity = INITIALSIZE;
- rows = 0;
- linebuffer = (char *) malloc (MAXCHARSINLINE * sizeof (char));
-
- if (NULL == fgets (linebuffer, MAXCHARSINLINE, filehandle))
- {
- fprintf (stderr, "Premature EOF on Input.\n");
- return NULL;
- }
- linebuffer[strlen (linebuffer) - 1] = 0;
- /* the last char of linebuffer given us by fgets is
- "\n". The confuses Henry Spencer's split function
- who has been asked to use whitespace delimiters;
- split claims the "\n" is a field. This hack
- eliminates that problem */
-
- if (pickfields == FALSE)
- { /* learn layout from 1st row */
- linecopy = strdup (linebuffer); /* protecting linebuffer */
- cNF = NF = split (linecopy, words, MAXFIELDS, "");
- if (NF <= 0)
- {
- fprintf (stderr, "No data found on 1st line!\n");
- return NULL;
- }
- *tablesize = *NumColumns = NF;
- *table = (int *) malloc (NF * sizeof (int));
- *labels = (char **) malloc (NF * sizeof (char *));
-
- for (i = 0; i < NF; i++)
- {
- (*table)[i] = i;
- (*labels)[i] = (char *) malloc (5 * sizeof (char));
- sprintf ((*labels)[i], "$%d", (i + 1));
- }
- free (linecopy);
- }
-
- /* The main loop. Notice lines are read at bottom. */
- do
- {
- if (NULL ==
- (p = mkrowptr (linebuffer, cNF, *table, *tablesize)))
- {
- fprintf (stderr, "On row %d, expect %d fields.\n", 1 + rows, cNF);
- return NULL;
- }
- rows++;
- if (rows > capacity)
- {
- capacity = (int) ((float) GROWTHFACTOR * capacity);
- data = (float **) realloc (data, capacity * sizeof (float *));
- }
- data[rows - 1] = p;
- hiteof = fgets (linebuffer, MAXCHARSINLINE, filehandle);
- linebuffer[strlen (linebuffer) - 1] = 0;
- /* Same problem -- remove \n for splitting */
- }
- while (hiteof != NULL); /* End of main loop. */
-
- *ObsNum = rows;
- data = (float **) realloc (data, rows * sizeof (float *));
- free (linebuffer);
- return data;
- }
-