failing like never before

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;
}
Tagged as: , , , No Comments