Untitled
unknown
plain_text
3 years ago
3.1 kB
15
Indexable
/*
* CS107 Assignment 4
* Code by Brent Ju
*
* This program will take in either standard input or
* a provided file and sort its contents and print them
* in default sorted order (lexicographical). Two flags,
* 'l' and 'n', are mutually exclusive, and these two flags
* will sort the output either by string length or string
* numberical value, respectively. The 'r' and 'u' flags will
* print the result in reverser order and maintain only
* unique values in the output, respectively.
* */
#include <assert.h>
#include <errno.h>
#include <error.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "samples/prototypes.h"
#define MAX_LINE_LEN 4096
#define MIN_NLINES 100
typedef int (*cmp_fn_t)(const void *p, const void *q);
// compares 2 strings by lexicographical order, default
int cmp_pstr(const void *p, const void *q) {
return strcmp(*(char**)p, *(char**)q);
}
// compares strings by length
int cmp_pstr_len(const void *p, const void *q) {
return strlen(*(char**)p) - strlen(*(char**)q);
}
// compares strings by numeric value via atoi function
int cmp_pstr_numeric(const void *p, const void *q) {
int p_int = atoi(*(char**)p);
int q_int = atoi(*(char**)q);
return p_int - q_int;
}
/*
* This function first reads input into a "max-sized" stack array
* using fgets, and then the result will be copied to dynamically
* allocated storage using strdup. If the '-u' flag is used to keep
* only unique values, binsert will be used; otherwise, one call to
* qsort will be made at the end to sort our array.
*
* Parameters uniq and reverse correspond to the flags passed in, and
* cmp is a generic comparison function that differs based on input type.
*/
void sort_lines(FILE *fp, cmp_fn_t cmp, bool uniq, bool reverse) {
char line[MAX_LINE_LEN];
int arr_size = MIN_NLINES;
char** input_lines = malloc(arr_size * sizeof(char*));
assert(input_lines != NULL); // input_lines must be freed
size_t num_lines = 0;
char* fgets_result = NULL;
while ((fgets_result = fgets(line, MAX_LINE_LEN, fp)) != NULL) {
if (num_lines == arr_size) {
input_lines = realloc(input_lines, 2 * arr_size * sizeof(char*));
assert(input_lines != NULL);
arr_size *= 2;
}
char* allocated_str = strdup(line); // every index of input_lines must be freed
assert(allocated_str != NULL);
if (uniq) {
binsert(&allocated_str, input_lines, &num_lines, sizeof(input_lines[0]), cmp);
} else {
input_lines[num_lines] = allocated_str;
num_lines++;
}
}
if (!uniq) {
qsort(input_lines, num_lines, sizeof(input_lines[0]), cmp);
}
if (reverse) {
for (int i = num_lines; i > 0; i--) {
printf("%s\n", input_lines[i - 1]);
free(input_lines[i - 1]);
}
} else {
for (int i = 0; i < num_lines; i++) {
printf("%s", input_lines[i]);
free(input_lines[i]);
}
}
free(input_lines);
}Editor is loading...