Advertisement
ahmedmasud

a simple approach to handling arrays of structures

May 6th, 2013
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.82 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. #include <sys/types.h>
  5.  
  6. struct point { double x, y; };
  7.  
  8. struct map {
  9.     size_t count;           /* number of points in this map */
  10.     struct point *points;   /* array of points in the map */
  11. };
  12.  
  13.     /* lets initialize some of them */
  14.  
  15. struct map * map_init(size_t count)
  16. {
  17.         struct map *m = (struct map *) malloc(sizeof (struct map));
  18.         if ( !m )
  19.                 return NULL;
  20.         m->count = count;
  21.         m->point = (struct point *)malloc (count * sizeof(struct point));
  22.         if ( !m->point ) {
  23.                 free(m);
  24.                 m = NULL;
  25.         }
  26.         return m;
  27. }
  28.  
  29.  
  30. void map_free(struct map *m)
  31. {
  32.         if ( m ) {
  33.                 if ( m->points )
  34.                         free (m->points);
  35.                 free(m);
  36.         }
  37. }
  38.  
  39.  
  40. struct point *map_set_point(struct map *m, int index, struct point *p)
  41. {
  42.     if ( !m )
  43.         return NULL;
  44.  
  45.     if ( index < m->count ) {
  46.         m->points[index].x = p->x;
  47.         m->points[index].y = p->y;
  48.         return &m->points[index];
  49.     }
  50.  
  51.     return NULL;
  52. }
  53.  
  54. struct point *map_get_point(struct map *m, int index)
  55. {
  56.  
  57.     if ( !m || index < 0 || index >= m->count ) {
  58.         return NULL;
  59.     }
  60.  
  61.     return &m->points[index];
  62. }
  63.  
  64. struct point *map_set_point_xy(struct map *m, int index, double x, double y)
  65. {
  66.     struct point p;
  67.     p.x = x;
  68.     p.y = y;
  69.     return map_set_point(m, index, &p);
  70. }
  71.  
  72. size_t map_get_count(struct map *m)
  73. {
  74.     if ( m )
  75.         return m->count;
  76.  
  77.     return ((size_t)-1);
  78. }
  79.  
  80.  
  81. typedef int (*point_callback_func_t)(struct point *p);
  82.  
  83. int for_each_point_call(struct map *m, point_callback_func_t f, int *error)
  84. {
  85.     int k;
  86.     int rv; /* return value from call back function */
  87.     for (k = 0; k < m->count; k++) {
  88.         if ((rv = f(&m->points[k])) != 0 ) {
  89.             if (error != NULL)
  90.                 *error =rv;
  91.             break;
  92.         }
  93.     }
  94.     return (k - m->count); /*
  95.                 * if we go through all of the points this will be zero
  96.                 * otherwise it will be a negative number  indicating how far
  97.                 * we were able to go in the loop
  98.                 */
  99. }
  100.  
  101.  
  102. struct mapset {
  103.     size_t count;       /* number of maps in this set */
  104.     struct map **maps;  /* a NULL terminated array of maps in this set */
  105. };
  106.  
  107.  
  108. /*
  109.  * The read_maps_from_file  reads a text file of the format:
  110.  
  111.  MAP
  112.  <M>
  113.  <x1>, <y1>
  114.  <x2>, <y2>
  115.   ...
  116.  <xM>, <yM>
  117.  
  118.  MAP
  119.  <N>
  120.  <x1>, <y1>
  121.  <x2>, <y2>
  122.   ...
  123.  <xN>, <yN>
  124.  
  125.  
  126.  and so on and can return a struct mapset filled with the map
  127.  coordinates
  128.  
  129.  A file with 3 maps would be:
  130.  
  131. --CUT-HERE--
  132.  MAP
  133.  3
  134.  5.5, 2.2
  135.  -3.5, 5.9
  136.  2.0, -125.0
  137.  
  138.  MAP
  139.  5
  140.  2.2, -89.0
  141.  551, 223.5
  142.  7.5, -8.9
  143.  7.8, 6.9
  144.  4.3, -9.9
  145.  
  146.  MAP
  147.  1
  148.  2.5, 0.3
  149.  
  150. --CUT-HERE--
  151.  
  152. */
  153.  
  154. /* A NOTE ON GOTOs:
  155.  * this function uses gotos to get out of the sitations where it's unable to build a
  156.  * proper map for whatever reason; and before any puritan structural programmers
  157.  * jump down my throat for using gotos I would like you to examine the code
  158.  * and determine that it is actually the better and cleaner way to program
  159.  * error handling using the approach given here.
  160.  */
  161.  
  162. void free_mapset(struct mapset *set) {
  163.     int k;
  164.     if ( set ) {
  165.         if ( set->maps ) {
  166.             for(k = 0; k < set->count; k++) {
  167.                 map_free(set->maps[k]);
  168.             }
  169.         }
  170.         free(set);
  171.     }
  172. }
  173.  
  174. struct mapset *load_mapset(const char *filename)
  175. {
  176.     FILE * fp;
  177.     struct mapset *set;
  178.     size_t mapcnt = 0; /* number of maps in this set */
  179.  
  180.     char buf[1024]; /* line buffer */
  181.  
  182.     struct map *tmpmap;
  183.     size_t tmpcnt;
  184.  
  185.     struct map **tmp_maps_arr;
  186.  
  187.     double x, y;
  188.  
  189.     int k;
  190.  
  191.     set = (struct mapset*) malloc(sizeof(struct mapset));
  192.  
  193.     if ( !set )
  194.         goto build_error;
  195.  
  196.     set->count = 0;
  197.     set->maps = NULL;
  198.  
  199.     fp = fopen("somefile.txt", "r");
  200.  
  201.     while(!feof(fp)) {
  202.  
  203.         fgets(buf, sizeof(buf), fp); /* read a line */
  204.  
  205.         if ( strcmp ( buf, "MAP") != 0 )  /* look for keyword 'MAP' */
  206.             continue; /* nope, let's reloop */
  207.  
  208.         /* found 'MAP' read the next line to get the count */
  209.  
  210.         fgets(buf, sizeof(buf), fp);
  211.  
  212.         if (feof(fp))
  213.             goto build_error;
  214.  
  215.         sscanf(buf, "%lu", &tmpcnt); /* number of points in this map */
  216.  
  217.         tmpmap = map_init(tmpcnt);   /*  make a tmpmap of tmpcnt points */
  218.  
  219.         if ( !tmpmap )
  220.             goto build_error;
  221.                    
  222.         for ( k = 0; k < tmpcnt; k++ ) {
  223.             fgets(buf, sizeof(buf), fp);
  224.             if (feof(fp))
  225.                 goto build_error;
  226.  
  227.             sscanf(buf, "%lf , %lf", &x, &y);
  228.             map_set_point_xy(tmpmap, k, x, y); /* add x, y to index k */
  229.         }
  230.  
  231.         /* try to increase the size of maps array */
  232.         tmp_maps_arr= (struct map **) realloc(set->maps, sizeof(struct map *) * (1+set->count));
  233.         if ( !tmp_maps_arr )
  234.             goto build_error;
  235.        
  236.         set->maps  = tmp_maps_arr;
  237.         set->maps[set->count] = tmpmap; /* save the pointer to the map */
  238.         set->count++;
  239.         tmpmap = NULL;
  240.     }
  241.  
  242.     return set;
  243.  
  244. build_error:
  245.     free_mapset(set);
  246.     if (tmpmap)
  247.         map_free(tmpmap);
  248.  
  249.     return NULL;
  250. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement