Untitled

 avatar
unknown
plain_text
2 years ago
3.1 kB
7
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...