Skip to content

Instantly share code, notes, and snippets.

Created October 7, 2013 20:49
Show Gist options
  • Save anonymous/6874721 to your computer and use it in GitHub Desktop.
Save anonymous/6874721 to your computer and use it in GitHub Desktop.
/***********************************************************************
* This programs plots histograms.
* Input is fed through the console/command-line/terminal.
* To compile issue :
* gcc -o hist <name_you_saved>.c
* Ignore warnings... (Remove them if you can. :) )
* Run as ./hist with options.
*
* Options :
* 1. -c<space><character> specifies the character which will be used to
* draw bars.
* 2. -m specifies to print the mean.
* 3. -v specifies to print the value on top of the bar.
*
* Sample Input :
* ./hist -v -c $ -m 2 3 10 5 7
*
* Output :
* $$ 2
* $$$ 3
* $$$$$$$$$$ 10
* $$$$$ 5
* $$$$$$$ 7
* The mean is : 5.400000
*
* It is easy to add more options. Look in the code. !
*
* License : Do what the fuck you want to with this code...
*
* ********************************************************************/
#include <stdio.h>
#include <stdlib.h>
/* The structure below holds program options */
typedef struct
{
unsigned int start ; /* Determines from where the data starts. */
char unit_bar ; /* Character to draw. */
char verbose ; /* Whether to print value. */
char mean ; /* Whether to display mean. */
} print_options ;
/* Checks whether the string is a valid unsigned int */
char isuint(const char* string)
{
unsigned int i ;
for(i=0; string[i]!='\0'; ++i)
if(string[i] < 48 || string[i] > 57)
return 0 ;
return 1 ;
}
void print_usage_message()
{
puts("Usage : hist-plot [OPTIONS] ...data list... \n\n Options : \n\t-c character to draw\n\t-v to display value on top of bars\n\t-m to display mean\n");
}
void print_error_message()
{
puts("Something went wrong...");
}
unsigned int find_max(const unsigned int *data, unsigned int size)
{
unsigned int i = 1u, max = data[0];
for(; i<size; ++i)
if(max < data[i])
max = data[i] ;
return max ;
}
float mean(const unsigned int *data, unsigned int size)
{
unsigned int i ;
float sum = 0.0f ;
for(i=0; i<size; ++i)
sum += (float)data[i] ;
return sum/(float)size ;
}
/* Prints the histogram */
char printh(const unsigned int *data, unsigned int size, print_options ops)
{
unsigned int i, j, max ;
char **matrix = malloc(sizeof(char*)*size);
if(!matrix)
return 0 ;
max = find_max(data, size);
for(i=0; i<size; ++i)
{
matrix[i] = malloc(sizeof(char)*(max+1));
if(!matrix[i])
return 0 ;
for(j=0; j<max; ++j)
matrix[i][j] = ((j < data[i]) ? ops.unit_bar : ' ') ;
matrix[i][max] = '\0' ; /* Make a valid string. */
}
for(i=0; i<size; ++i)
(ops.verbose) ? printf("%s %u\n", matrix[i], data[i]) :
printf("%s\n", matrix[i]);
if(ops.mean)
printf("The mean is : %f\n", mean(data, size));
return 1 ;
}
char parse_options(const char** argv, print_options* options)
{
unsigned int i = 1 ;
int ret = 1 ;
while((argv[i][0] == '-') && (argv[i] != NULL))
{
switch(argv[i][1])
{
/* If -c option, then read the character to draw */
case 'c' :
++i ;
(*options).unit_bar = argv[i][0] ;
break ;
case 'v' :
(*options).verbose = 1 ;
break ;
case 'm' :
(*options).mean = 1 ;
break ;
default :
return 0 ;
}
++i ;
}
(*options).start = i ;
return ret ;
}
char parse_data(int argc, const char** argv, print_options ops)
{
unsigned int* data, i, j ;
data = malloc(sizeof(unsigned int)*(argc-ops.start));
if(!data)
return 0 ;
for(i=ops.start, j=0; i<argc; ++i)
{
if(isuint(argv[i]))
{
data[j] = atoi(argv[i]);
++j ;
}
else
return 0 ;
}
return printh(data, j, ops);
}
int main(int argc, char **argv) {
/* Default options : All turned off, draws '=' character. */
print_options ops = { .start = 1, .unit_bar = '=', .verbose = 0, .mean = 0 } ;
if(argc < 2 || !parse_options(argv, &ops))
{
print_usage_message() ;
return 0 ;
}
if(!parse_data(argc, argv, ops))
print_error_message() ;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment