Skip to content

Instantly share code, notes, and snippets.

@anupdhml
Created November 28, 2013 15:08
Show Gist options
  • Save anupdhml/7693332 to your computer and use it in GitHub Desktop.
Save anupdhml/7693332 to your computer and use it in GitHub Desktop.
basic emulation of the unix sort command
/*
* ============================================================================
* sort.c
* basic emulation of the unix sort command. Default sort is in dictionary order
* Input: a file with numbers. Args -r (reverse), -u (unique), -n (num sort)
* Output: sorted list
*
* <[email protected]>, 15/04/12 20:16:35
* =============================================================================
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARGS_ALLOWED 3 // -r, -u, -n
#define MAXENTRIES 200 // Total number of numbers to read
#define LINE_LENGTH 20 // Can't exceed this no in a line of file
void quicksort (int *nums, int l, int r, int numsort);
static int partition (int *nums, int l, int r, int pivot_index, int numsort);
static void swap(int *a,int *b);
static int a_lt_b (int a, int b, int numsort);
static int read_file(FILE *fp, int *numbers);
static void rev_list(int *list, int length);
static void printnos (int *nums, int n, int unique);
/* -------------------------------------------------------------------------*/
int main(int argc, char *argv[]) {
int unique, reverse, numsort;
unique = reverse = numsort = 0;
FILE *fp = NULL;
int numbers[MAXENTRIES];
int total_nos;
int file_count = 0;
// BEGIN ARGUMNET PARSING----------------------------------------------------
// run through the input commands looking for switches.
// Could have included all this in a separate function, but easier this way
while(argc > 1) {
if (argv[1][0] == '-') { // switches begin with this
int i;
for (i=1; i <= ARGS_ALLOWED; i++) {
if(argv[1][i] == 0)
break;
// argv[1][i] is the actual option
switch (argv[1][i]) {
case 'r':
reverse = 1;
break;
case 'u':
unique = 1;
break;
case 'n':
numsort = 1;
break;
default:
printf("Usage: bad option %c in %s\n", argv[1][i], argv[1]);
break;
}
}
}
else { // The arg is considered as a filename now
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "File %s not found\n", argv[1]);
exit(2);
}
file_count++;
}
// decrement the number of arguments left
// increment the argv pointer to the next argument
argc--; argv++;
}
// END OF ARGUMNET PARSING---------------------------------------------------
if (fp == NULL) {
fprintf(stderr, "No file provided.\n");
exit(1);
}
if (file_count > 1)
printf("More than one file provided. Using the last file.... \n");
// Main processing begins here
total_nos = read_file(fp, numbers);
quicksort(numbers, 0, total_nos - 1, numsort);
if (reverse)
rev_list(numbers, total_nos);
printnos(numbers, total_nos, unique);
return(0);
}
/* SORTING ------------------------------------------------------------------*/
// Implement the quicksort algorithm.
void quicksort (int *nums, int l, int r, int numsort) {
int pivot_index, pivot_index_new;
// Proceed only if the list has 2 or more entries
if (l < r) {
// Choose a pivot sandwiched between left and right
pivot_index = (l+r)/2;
// Divide the list
pivot_index_new = partition (nums, l, r, pivot_index, numsort);
// Sort entries lesser than pivot
quicksort (nums, l, pivot_index_new - 1, numsort);
// Sort entries bigger or equal to pivot
quicksort (nums, pivot_index_new + 1, r, numsort);
}
}
// l is leftmost index and r is the rightmost. helper for quicksort.
int partition (int *nums, int l, int r, int pivot_index, int numsort) {
int k_index = l; // moving pivot
int pivot_val = nums[pivot_index];
// Move pivot to the end
swap(&nums[pivot_index], &nums[r]);
int i;
for (i=l; i<r; i++) {
if ( a_lt_b (nums[i], pivot_val, numsort) ) {
swap(&nums[i], &nums[k_index]);
k_index++;
}
}
// Final place for pivot
swap(&nums[k_index], &nums[r]);
return k_index;
}
// Swap values of two inputs
void swap(int *a,int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
// Determine if a is less than b, whether in numerical order or dictionary order
int a_lt_b (int a, int b, int numsort) {
if (numsort)
return a < b;
else {
char a1[LINE_LENGTH], b1[LINE_LENGTH];
sprintf(a1, "%d", a);
sprintf(b1, "%d", b);
int n = strcmp (a1, b1);
if (n < 0)
return 1;
else
return 0;
}
}
/* HELPER FUNCTIONS----------------------------------------------------------*/
int read_file(FILE *fp, int *numbers) {
int i = 0;
int val;
while (i < MAXENTRIES) {
val = fscanf(fp, "%d", &numbers[i]);
// When no numbers were read in the line
if (val == 0) {
fprintf(stderr, "File must have numbers only\n");
fclose(fp);
exit(1);
}
// End of file
if ( val == EOF ) {
numbers[i] = -1; // don't really need this...
fclose(fp);
break;
}
i++;
}
int total_read = i;
return total_read;
}
// Reverse a given list
void rev_list(int *list, int length) {
int i,j;
int temp;
for (i = 0, j = length - 1 ; i <= j; i++, j--) {
temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
// Print the list of numbers
void printnos (int *nums, int n, int unique) {
int i;
int temp = -1;
for (i=0; i < n; i++) {
if (unique && temp == nums[i]);
else
printf("%d\n", nums[i]);
temp = nums[i];
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment