diff --git a/lab09/Makefile b/lab09/Makefile index 08c2234..4701f6a 100644 --- a/lab09/Makefile +++ b/lab09/Makefile @@ -3,9 +3,9 @@ CC = gcc CFLAGS = -Wall -std=c11 #Input file -INPUT = input1.txt +INPUT = input5.txt OUTPUT = output.txt -REF = ref1.txt +REF = ref5.txt # Source file SRCS = lab9.c # Output diff --git a/lab09/lab9.c b/lab09/lab9.c index 522c4e1..5229350 100644 --- a/lab09/lab9.c +++ b/lab09/lab9.c @@ -12,16 +12,22 @@ #define ERROR_CODE 1 #define OK_CODE 0 #define MAX_STRING_LEN 256 +#define SCAN_MAX_LEN 255 +#define SCAN_FORMAT_LEN 16 #define IS_EQUAL 0 #define INDEX_OFFSET 1 #define BASE_TEN 10 -#define DOUBLE 2 -#define SHORT 1 -#define INTEGER 2 -#define FLOAT 3 -#define CHAR 4 -#define STRING 5 +#define TYPE_SHORT 1 +#define TYPE_INTEGER 2 +#define TYPE_FLOAT 3 +#define TYPE_CHAR 4 +#define TYPE_STRING 5 + +#define NEWLINE '\n' +#define VALUE_SEPARATOR ',' +#define NULL_TERMINATOR '\0' +#define SENTINEL_STRING "E" char A_NUMBER[] = "A01385066"; @@ -36,10 +42,8 @@ void insertNode(NODE **head, void *data) NODE *node; node = malloc(sizeof(NODE)); - node->data = data; node->next = *head; - *head = node; } @@ -51,96 +55,25 @@ void freeList(NODE *head) { temp = head; head = head->next; - free(temp->data); free(temp); } } -NODE* readFile(char *filepath, int *type, int *count) -{ - FILE *file; - file = fopen(filepath, "r"); - - if (file == NULL) - { - return NULL; - } - - if (fscanf(file, "%d", type) != EXPECTED_INPUT) - { - fclose(file); - return NULL; - } - - int ch; // skip newlines characters and EOF - while ((ch = fgetc(file)) != '\n' && ch != EOF) {} - - char *format; - NODE *head; - size_t size; - - head = NULL; - *count = 0; - - format = *type == SHORT ? "%hd" : - *type == INTEGER ? "%d" : - *type == FLOAT ? "%f" : - " %c"; - - size = *type == SHORT ? sizeof(short) : - *type == INTEGER ? sizeof(int) : - *type == FLOAT ? sizeof(float) : - *type == CHAR ? sizeof(char) : - MAX_STRING_LEN; - - while (READING) - { - void *data; - - data = malloc(size); - - if (*type == STRING) - { - if (fscanf(file, "%255[^,\n]", (char *)data) != EXPECTED_INPUT || - strcmp((char *)data, "E") == IS_EQUAL) - { - free(data); - break; - } - } - else - { - if (fscanf(file, format, data) != EXPECTED_INPUT || - (*type == CHAR && - *(char *)data == 'E')) - { - free(data); - break; - } - } - - insertNode(&head, data); - (*count)++; - - ch = fgetc(file); - if (ch == EOF) - { - break; - } - if (ch == '\n') - { - continue; - } - } - - fclose(file); - return head; -} - int compare(void *a, void *b, int type) { - if (type == SHORT || type == INTEGER) + if (type == TYPE_SHORT) + { + short va; + short vb; + + va = *(short *)a; + vb = *(short *)b; + + return (va > vb) - (va < vb); + } + + if (type == TYPE_INTEGER) { int va; int vb; @@ -151,7 +84,7 @@ int compare(void *a, void *b, int type) return (va > vb) - (va < vb); } - if (type == FLOAT) + if (type == TYPE_FLOAT) { float va; float vb; @@ -162,7 +95,7 @@ int compare(void *a, void *b, int type) return (va > vb) - (va < vb); } - if (type == CHAR) + if (type == TYPE_CHAR) { char va; char vb; @@ -182,8 +115,8 @@ NODE* split(NODE *head) NODE *slow; NODE *second; - slow = head; fast = head; + slow = head; while (fast != NULL && fast->next != NULL) { @@ -206,6 +139,7 @@ NODE* merge(NODE *first, NODE *second, int type) { return second; } + if (second == NULL) { return first; @@ -216,60 +150,206 @@ NODE* merge(NODE *first, NODE *second, int type) first->next = merge(first->next, second, type); return first; } - else - { - second->next = merge(first, second->next, type); - return second; - } + + second->next = merge(first, second->next, type); + return second; } NODE* mergeSort(NODE *head, int type) { + NODE *second; + if (head == NULL || head->next == NULL) { return head; } - NODE *second; - second = split(head); - head = mergeSort(head, type); + head = mergeSort(head, type); second = mergeSort(second, type); return merge(head, second, type); } +NODE* readFile(char *filepath, int *type, int *count) +{ + FILE *file; + NODE *head; + int ch; + size_t size; + + file = fopen(filepath, "r"); + if (file == NULL) + { + return NULL; + } + + if (fscanf(file, "%d", type) != EXPECTED_INPUT) + { + fclose(file); + return NULL; + } + + ch = fgetc(file); + while (ch != NEWLINE && ch != EOF) + { + ch = fgetc(file); + } + + head = NULL; + *count = 0; + + size = MAX_STRING_LEN; + if (*type == TYPE_SHORT) + { + size = sizeof(short); + } + else if (*type == TYPE_INTEGER) + { + size = sizeof(int); + } + else if (*type == TYPE_FLOAT) + { + size = sizeof(float); + } + else if (*type == TYPE_CHAR) + { + size = sizeof(char); + } + + while (READING) + { + char buffer[MAX_STRING_LEN]; + char scanFormat[SCAN_FORMAT_LEN]; + void *data; + char *end; + long longValue; + float floatValue; + int scanResult; + + data = malloc(size); + if (data == NULL) + { + fclose(file); + freeList(head); + return NULL; + } + + scanResult = snprintf(scanFormat, SCAN_FORMAT_LEN, "%%%d[^,\n]", SCAN_MAX_LEN); + if (scanResult < 0) + { + free(data); + fclose(file); + freeList(head); + return NULL; + } + + if (fscanf(file, scanFormat, buffer) != EXPECTED_INPUT) + { + free(data); + break; + } + + if (strcmp(buffer, SENTINEL_STRING) == IS_EQUAL) + { + free(data); + break; + } + + if (*type == TYPE_SHORT) + { + longValue = strtol(buffer, &end, BASE_TEN); + if (*end != NULL_TERMINATOR || longValue < SHRT_MIN || longValue > SHRT_MAX) + { + free(data); + fclose(file); + freeList(head); + return NULL; + } + *(short *)data = (short)longValue; + } + else if (*type == TYPE_INTEGER) + { + longValue = strtol(buffer, &end, BASE_TEN); + if (*end != NULL_TERMINATOR || longValue < INT_MIN || longValue > INT_MAX) + { + free(data); + fclose(file); + freeList(head); + return NULL; + } + *(int *)data = (int)longValue; + } + else if (*type == TYPE_FLOAT) + { + floatValue = strtof(buffer, &end); + if (*end != NULL_TERMINATOR) + { + free(data); + fclose(file); + freeList(head); + return NULL; + } + *(float *)data = floatValue; + } + else if (*type == TYPE_CHAR) + { + if (strlen(buffer) != INDEX_OFFSET) + { + free(data); + fclose(file); + freeList(head); + return NULL; + } + *(char *)data = buffer[0]; + } + else + { + strncpy((char *)data, buffer, MAX_STRING_LEN); + ((char *)data)[MAX_STRING_LEN - INDEX_OFFSET] = NULL_TERMINATOR; + } + + insertNode(&head, data); + (*count)++; + + ch = fgetc(file); + if (ch == EOF) + { + break; + } + if (ch == NEWLINE) + { + continue; + } + } + + fclose(file); + return head; +} + void printValue(FILE *file, void *data, int type) { - if (type == SHORT) + if (type == TYPE_SHORT) { - short v; - v = *(short *)data; - fprintf(file, "%hd", v); + fprintf(file, "%hd", *(short *)data); return; } - if (type == INTEGER) + if (type == TYPE_INTEGER) { - int v; - v = *(int *)data; - fprintf(file, "%d", v); + fprintf(file, "%d", *(int *)data); return; } - if (type == FLOAT) + if (type == TYPE_FLOAT) { - float v; - v = *(float *)data; - fprintf(file, "%.1f", v); + fprintf(file, "%.1f", *(float *)data); return; } - if (type == CHAR) + if (type == TYPE_CHAR) { - char v; - v = *(char *)data; - fprintf(file, "%c", v); + fprintf(file, "%c", *(char *)data); return; } @@ -281,8 +361,12 @@ void writeOutput(char *filepath, NODE *head, int type, int isError) FILE *file; file = fopen(filepath, "w"); + if (file == NULL) + { + return; + } - if (isError == 1) + if (isError == ERROR_CODE) { fputs("Error\n", file); fclose(file); @@ -292,31 +376,29 @@ void writeOutput(char *filepath, NODE *head, int type, int isError) while (head != NULL) { printValue(file, head->data, type); - if (head->next != NULL) { - fputc(',', file); + fputc(VALUE_SEPARATOR, file); } - head = head->next; } - fputc('\n', file); + fputc(NEWLINE, file); fclose(file); } int main(int argc, char *argv[]) { + NODE *head; + int type; + int count; + if (argc < EXPECTED_ARGUMENTS) { printf("Usage: %s \n", argv[PROGRAM_FILE]); return 1; } - NODE *head; - int type; - int count; - head = readFile(argv[INPUT_FILE], &type, &count); if (head == NULL) @@ -326,9 +408,7 @@ int main(int argc, char *argv[]) } head = mergeSort(head, type); - writeOutput(argv[OUTPUT_FILE], head, type, OK_CODE); - freeList(head); return 0; diff --git a/lab09/output.txt b/lab09/output.txt index 776e6d6..a210e76 100644 --- a/lab09/output.txt +++ b/lab09/output.txt @@ -1 +1 @@ -101,158,205,219,317,347,412,501,516,604,629,732,739,813,826,945,32767 +apple,banana,blackberry,blueberry,cherry,grape,kiwi,lemon,mango,orange,peach,pear,pineapple,raspberry,strawberry,watermelon