Generating a bar chart : Bar Chart « Development « C / ANSI-C






Generating a bar chart

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



           
       








Related examples in the same category