9Feb/090
A Simple Weird Sorter
This is a little toy program written for one of my CS classes. The program takes a positive integer N as an argument and reads from stdin until it gets an EOF. The program then sorts the input using qsort, while assuming that each element to be supported is N bytes long.
Fun facts: the output from this program looks kinda cool if you do "./program_name 1 < index.html" where index.html is some large webpage.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define MEM_SIZE 100
// for the sake of ease, token length and input array are global
unsigned long global_token;
char * in_ptr;
// comparator for qsort,
// returns 1 if a is bigger, -1 is smaller, 0 if equal
int comparator(const void * a, const void * b)
{
unsigned int i;
int r_value = 0;
for(i = 0; i < global_token; ++i)
{
if( *(i + (char*)a) < *(i + (char*)b))
return -1;
else if ( *(i + (char*)a) > *(i + (char*)b))
return 1;
}
return 0;
}
// get input from stdin and save it to dynmaically allocated memory
unsigned long get_input()
{
char* temp_in_ptr;
unsigned long ar_size, n_ar_size;
unsigned long max_size = MEM_SIZE;
for(ar_size = 0; !feof(stdin); ++ar_size) // loop until EOF
{
if(max_size == (1 + ar_size)) // check if more memory is needed
{
temp_in_ptr =(char *)realloc(in_ptr,
(size_t)(MEM_SIZE + max_size));
if(!temp_in_ptr) // returns error and exits if realloc fails
{
fprintf(stderr, "Error in allocating memory for input.");
fprintf(stderr, "Input data may be too large.\n");
free(in_ptr); // free dynamically allocated memory
exit(1);
}
in_ptr = temp_in_ptr;
max_size += MEM_SIZE;
}
*(in_ptr + ar_size) = fgetc(stdin); // get next char from input
if(ferror(stdin)) // check for read error
{
fprintf(stderr, "Error encountered in reading input.\n");
free(in_ptr); // free dynamically allocated memory
exit(1);
}
}
ar_size --; // get rid of EOF char
// if string was not multiple of token length, need to make it
// a multiple of token length and fill end with '\0'
if(ar_size % global_token != 0)
{
n_ar_size =
(global_token * (unsigned int)(ar_size / global_token + 1));
if(n_ar_size > max_size) // check if more memory is needed
{
temp_in_ptr = (char *)realloc(in_ptr, (size_t)n_ar_size);
if(!temp_in_ptr) // check for error in mem allocation
{
fprintf(stderr, "Error in allocating memory for input.");
fprintf(stderr, "Input data may be too large.\n");
free(in_ptr); // free dynamically allocated memory
exit(1);
}
in_ptr = temp_in_ptr;
}
for(; ar_size != n_ar_size; ++ar_size) // fill with '\0'
{
*(ar_size + in_ptr) = '\0';
}
}
return ar_size;
}
int main(int argc, char** argv)
{
unsigned long ar_size, i;
in_ptr = (char *)malloc(MEM_SIZE * sizeof(char));
if (argc < 2)
{
fprintf(stderr, "Must provide at least one argument.\n");
free(in_ptr); // free dynamically allocated memory
exit(1);
}
// use strtoul() to convert char to long int
// and use errno to check for error in conversion
errno = 0;
global_token = strtoul(*(argv + 1), NULL, 0);
if(!global_token || errno == ERANGE)
{
fprintf(stderr, "Argument must be a positive integer.\n");
free(in_ptr); // free dynamically allocated memory
exit(1);
}
ar_size = get_input(); // get data from stdin
// sort with qsort
qsort(in_ptr, (size_t)(ar_size / global_token),
(size_t)(sizeof(char) * global_token) , comparator);
for(i = 0; i < ar_size; ++i) //print sorted data
{
printf("%c", *(in_ptr + i));
}
free(in_ptr); // free dynamically allocated memory
return 0;
}
