Example 2: Sorting Arrays and Selective Reads

In this example, we will work with the site list from the Time Attribute Example. Recall that the data has three dimensions, five string attributes, and one decimal attributes. However, in this example we are writing a program which only uses two dimensional attributes and one decimal attribute.

Follow along in this skeleton C program and remember that, in real code, you should always check return values!

#include "site.h"           /* include definitions and prototypes */
#include "gis.h"            /* includes stdio.h for file I/O */
int main (argc, argv)
  char **argv;
  int argc;
{
  int sites_alloced=5, n=0;
  Site **mysite;               /* pointer to pointer to Site */

  /* 
   * We allocate memory for an array of Site structs.
   */
  mysites=(Site **) G_malloc(sites_alloced*sizeof(Site *));

 
  /* 
   * Here we only allocate space for 2 dimensions and one decimal attribute.
   * Thus any calls to G_site_get() will ingore dimensional fields
   * past the first two, any category attribute, and all string attributes 
   */
  mysites[n] = G_site_new_struct (2, 0, 1);
 
  while ((i=G_site_get (fp, mysites[n])) != EOF)
  {
    /*
     * (we should test for i==2 and deal with appropriately)
     */
    G_site_put(stdout,mysites[n++],0);
    /* 
     * This snippet could have been left out for compactness since
     * it is not critical to this example. However, this shows how
     * to read an unknown number of sites in a robust fashion.
     */
    if (n==sites_alloced)
    {
      sites_alloced+=100;
      mysites=(Site **) G_realloc(mysites, sites_alloced*sizeof(Site *));
      if (mysites==NULL)
        G_fatal_error("memory reallocation error");
    }

    /*
     * We must call G_site_new_struct() for each element
     * in this array. Doing this inside the while loop instead of
     * before the while loop saves memory (since we are only allocating
     * on an as-needed basis).
     */
    mysites[n] = G_site_new_struct (2, 0, 1);
  }
  free(mysites[n]);      /* We did not need the last one */
  printf("\n");
 
  /* sort the array of sites into ascending order */
  qsort (mysites, n, sizeof (Site *), G_site_d_cmp); 
 
  /* write the sorted array to standard output */
  for(i=0;i<n;++i)
    G_site_put(stdout,mysites[i],0);
 
  printf("\n");
  
  /* write only dimensional fields and no attributes */
  for(i=0;i<n;++i)
  {
    mysites[i]->dbl_alloc=0;
    G_site_put(stdout,mysites[i],0);
  }

  return 0;
}
Running our sample program, we get:
Mapset <PERMANENT> in Location <temporal>
GRASS 4.1 > s.egsort time-h
10.8|0|%31.4 
11|5.5|%36.4 
5.1|3.9|%28.4 

5.1|3.9|%28.4 
10.8|0|%31.4 
11|5.5|%36.4 
 
5.1|3.9|
10.8|0|
11|5.5|
Compare the above output to the input site list given earlier. We read only the first two dimensional attributes and the first decimal attribute--all others were safely ignored.

The resulting site list is sorted into ascending order according to the first decimal attribute. Similar functions exist for sorting by the first string attribute or by category attribute. For sorting by second or third specific fields, you may write your own qsort comparison functions using these examples.

We can selectively write some or none of attribute fields by altering the Site structure. For situations requiring writing of variable attributes (more complex than this example), pointer manipulation may be necessary.

In this example, we read selectively read dimension and attribute fields,

Key Points

After studying the above, you should:
Darrell McCauley (mccauley@ecn.purdue.edu)
Last modified on