Mega Code Archive

 
Categories / C / Development
 

Generating a bar chart

/* Beginning C, Third Edition  By Ivor Horton  ISBN: 1-59059-253-0  Published: Apr 2004  Publisher: apress */ #include <stdio.h> #include <string.h> #include <stdlib.h>  #define PAGE_HEIGHT  20 #define PAGE_WIDTH   40 #define TRUE  1 #define FALSE 0 typedef struct barTAG         /* Bar structure       */ {    double value;              /* Value of bar        */    struct barTAG *pnextbar;   /* Pointer to next bar */ }bar;                         /* Type for a bar      */ typedef unsigned int uint;    /* Type definition     */ /* Function prototype */ int bar_chart(bar *pfirstbar, uint page_width, uint page_height, char *title);   int main() {    bar firstbar;            /* First bar structure */    bar *plastbar = NULL;    /* Pointer to last bar */    char value[80];          /* Input buffer        */    char title[80];          /* Chart title         */      printf("\nEnter the chart title: ");    gets(title);             /* Read chart title    */    for( ;; )                /* Loop for bar input  */    {      printf("Enter the value of the bar, or use quit to end: ");      gets(value);      if(strcmp(value, "quit") == 0)   /* quit entered?       */       break;                          /* then input finished */      /* Store in next bar */      if(plastbar == NULL)             /* First time?         */      {        firstbar.pnextbar = NULL;  /* Initialize next pointer */        plastbar = &firstbar;      /* Use the first           */      }      else      {        /* Get memory */        if((plastbar->pnextbar = malloc(sizeof(bar))) == NULL)              {          printf("Oops! Couldn't allocate memory\n");          return -1;        }        plastbar = plastbar->pnextbar;    /* Old next is new bar  */        plastbar->pnextbar = NULL;        /* New bar next is NULL */      }      plastbar->value = atof(value);      /* Store the value      */    }    /* Create bar-chart */    bar_chart(&firstbar, PAGE_WIDTH, PAGE_HEIGHT, title);        /* We are done, so release all the memory we allocated */    while(firstbar.pnextbar != NULL)    {      plastbar = firstbar.pnextbar;           /* Save pointer to next */      firstbar.pnextbar = plastbar->pnextbar; /* Get one after next   */      free(plastbar);                         /* Free next memory     */    }    return 0; } int bar_chart(bar *pfirstbar, uint page_width, uint page_height,                                                        char *title) {    bar *plastbar = pfirstbar;  /* Pointer to previous bar            */    double max = 0.0;           /* Maximum bar value                  */    double min = 0.0;           /* Minimum bar value                  */    double vert_scale = 0.0;    /* Unit step in vertical direction    */    double position = 0.0;      /* Current vertical position on chart */    uint bar_count = 1;         /* Number of bars - at least 1        */    uint barwidth = 0;          /* Width of a bar                     */    uint space = 2;             /* spaces between bars                */    uint i = 0;                 /* Loop counter                       */    uint bars = 0;              /* Loop counter through bars          */    char *column = NULL;        /* Pointer to bar column section      */    char *blank = NULL;         /* Blank string for bar+space         */    int axis = FALSE;           /* Indicates axis drawn               */     /* Find maximum and minimum of all bar values */    /* Set max and min to first bar value */    max = min = plastbar->value;     while((plastbar = plastbar->pnextbar) != NULL)    {      bar_count++;              /* Increment bar count */      max = (max < plastbar->value)? plastbar->value : max;      min = (min > plastbar->value)? plastbar->value : min;    }     vert_scale = (max - min)/page_height; /* Calculate step length */      /* Check bar width */    if((barwidth = page_width/bar_count - space) < 1)        {      printf("\nPage width too narrow.\n");      return -1;    }    /* Set up a string which will be used to build the columns */     /* Get the memory */    if((column = malloc(barwidth + space + 1)) == NULL)              {      printf("\nFailed to allocate memory in barchart()"                            " - terminating program.\n");      abort();    }    for(i = 0 ; i < space ; i++)      *(column+i)=' ';         /* Blank the space between bars */    for( ; i < space+barwidth ; i++)      *(column+i)='#';         /* Enter the bar characters     */    *(column+i) = '\0';        /* Add string terminator        */    /* Set up a string which will be used as a blank column */       /* Get the memory */    if((blank = malloc(barwidth + space + 1)) == NULL)               {      printf("\nFailed to allocate memory in barchart()"                            " - terminating program.\n");      abort();    }    for(i = 0 ; i < space+barwidth ; i++)      *(blank+i) = ' ';        /* Blank total width of bar+space */    *(blank+i) = '\0';         /* Add string terminator          */     printf("^ %s\n", title);   /* Output the chart title      */    /* Draw the bar chart */    position = max;    for(i = 0 ; i <= page_height ; i++)    {      /* Check if we need to output the horizontal axis */      if(position <= 0.0 && !axis)      {        printf("+");           /* Start of horizontal axis    */        for(bars = 0; bars < bar_count*(barwidth+space); bars++)          printf("-");         /* Output horizontal axis      */        printf(">\n");        axis = TRUE;           /* Axis was drawn              */        position -= vert_scale;/* Decrement position           */        continue;      }      printf("|");             /* Output vertical axis        */      plastbar = pfirstbar;    /* start with the first bar    */       /* For each bar... */      for(bars = 1; bars <= bar_count; bars++)           {        /* If position is between axis and value, output column */        /* otherwise output blank                               */        printf("%s", position <= plastbar->value &&                      plastbar->value >= 0.0 && position > 0.0 ||                     position >= plastbar->value &&                      plastbar->value <= 0.0 &&                      position <= 0.0 ? column: blank);        plastbar = plastbar->pnextbar;      }      printf("\n");            /* End the line of output        */      position -= vert_scale;  /* Decrement position            */    }     if(!axis)            /* Have we output the horizontal axis? */    {                    /* No, so do it now                    */      printf("+");      for(bars = 0; bars < bar_count*(barwidth+space); bars++)        printf("-");      printf(">\n");    }    free(blank);               /* Free memory for blank string   */    free(column);              /* Free memory for column string  */    return 0;  }