Created
November 28, 2013 15:08
-
-
Save anupdhml/7693332 to your computer and use it in GitHub Desktop.
basic emulation of the unix sort command
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* ============================================================================ | |
* 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