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