cs240/hw/hw12/backup/miniDB.bak.c

440 lines
11 KiB
C
Raw Permalink Normal View History

2018-10-15 17:20:57 -04:00
#include "miniDB.h"
Movie* head = NULL;
int size = 0;
int main(int argc, char** argv) {
if (argc < 4) {
printf("Usage: miniDB <database> <commands> <output>\n");
} else {
if (load(argv[1]) != 0) {
printf("Error while loading database from '%s'.\n", argv[1]);
return 2;
}
if (read(argv[2], argv[3]) != 0) {
printf("Error while reading commands from '%s'.\n", argv[2]);
return 3;
}
if (save(argv[1]) != 0) {
printf("Error while saving database to '%s'.\n", argv[1]);
return 4;
}
}
return 0;
}
int read(char* filename, char* fileOut) {
if (filename == NULL) {
return 1;
}
FILE* file = fopen(filename, "r");
if (file == NULL)
return 2;
FILE* output = fopen(fileOut, "w"); // If appending, switch to "a".
if (output == NULL)
return 3;
int length = 512*3;
char buffer[length];
while (fgets(buffer, length, file) != NULL && strcmp(buffer, "") != 0) {
printf("Command read: %s\n", buffer);
char* token = strtok(buffer, ", ");
if (token == NULL) {
token = strtok(buffer, ",");
if (token == NULL)
return 4;
}
if (strcmp(token, "ADD") == 0) {
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
char* title = strdup(token);
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
char* date = strdup(token);
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
char* director = strdup(token);
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
int id = atoi(token);
if (add(title, date, director, id) != 0)
return 6;
free(title);
free(date);
free(director);
title = NULL;
date = NULL;
director = NULL;
} else if (strcmp(token, "LOOKUP") == 0) {
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
char* feature = strdup(token);
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
char* data = strdup(token);
if (lookup(feature, data, output) != 0)
return 6;
free(feature);
free(data);
feature = NULL;
data = NULL;
} else if (strcmp(token, "DISPLAY") == 0) {
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
char* feature = strdup(token);
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
int order = atoi(token);
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
int max = atoi(token);
if (display(feature, order, max, output) != 0)
return 6;
free(feature);
feature = NULL;
} else if (strcmp(token, "EDIT") == 0) {
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
int id = atoi(token);
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
char* feature = strdup(token);
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
char* data = strdup(token);
if (edit(id, feature, data) != 0)
return 6;
free(feature);
free(data);
feature = NULL;
data = NULL;
} else if (strcmp(token, "REMOVE") == 0) {
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
int id = atoi(token);
if (removeId(id) != 0)
return 6;
}
}
printf("End of commands.\n");
if (fclose(file) != 0)
return 7;
if (fclose(output) != 0)
return 8;
return 0;
}
int load(char* filename) {
if (filename == NULL) {
return 1;
}
FILE* file = fopen(filename, "r");
if (file == NULL)
return 2;
int length = 512*3; // HOLD ALL THE CHARS!
char buffer[length];
while (fgets(buffer, length, file) != NULL && strcmp(buffer, "") != 0) {
printf("Line read: %s\n", buffer);
char* token = strtok(buffer, ", ");
if (token == NULL) {
token = strtok(buffer, ",");
if (token == NULL)
return 3;
} // Now that it's kicked off with the correct delimeter...
char* title = strdup(token);
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
char* date = strdup(token);
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
char* director = strdup(token);
token = strtok(buffer, NULL);
if (token == NULL)
return 5;
int id = atoi(token);
if (add(title, date, director, id) != 0)
return 6;
free(title);
free(date);
free(director);
title = NULL;
date = NULL;
director = NULL;
}
printf("End of file.\n");
if (fclose(file) != 0) {
return 4;
}
return 0;
}
Movie* get(int id) {
if (head == NULL) {
return NULL;
}
Movie* target = head;
while (target->id != id) {
if (target->next != NULL) {
target = target->next;
} else
return NULL;
}
return target;
}
int add(char* title, char* date, char* director, int id) {
if (title == NULL || date == NULL || director == NULL)
return 1;
Movie* mov = (Movie *) malloc(sizeof(Movie));
if (mov == NULL)
return 2;
if (head == NULL) {
head = mov;
} else {
Movie* target = head;
while (target->next != NULL) {
target = target->next;
}
target->next = mov;
mov->next = NULL;
}
size++;
mov->title = strdup(title);
mov->date = strdup(date);
mov->director = strdup(director);
mov->id = id;
return 0;
}
int edit(int id, char* feature, char* data) {
if (feature == NULL || data == NULL)
return 1;
Movie* mov = get(id);
if (mov == NULL)
return 2;
if (strcmp(feature, "ID") == 0) {
mov->id = atoi(data);
} else if (strcmp(feature, "TITLE") == 0) {
free(mov->title);
mov->title = strdup(data);
} else if (strcmp(feature, "DATE") == 0) {
free(mov->date);
mov->date = strdup(data);
} else if (strcmp(feature, "DIRECTOR") == 0) {
free(mov->director);
mov->director = strdup(data);
} else {
return 3;
}
return 0;
}
int removeId(int id) {
if (head == NULL) {
return 1;
}
Movie* prev = NULL;
Movie* target = head;
while (target->id != id) {
if (target->next != NULL) {
prev = target;
target = target->next;
} else
return 2;
}
if (prev == NULL && target != NULL) {
head = target->next; // If next is NULL, that's okay.
} else {
prev->next = target->next; // Again, a NULL next is okay.
}
size--;
free(target->title);
free(target->date);
free(target->director);
target->title = NULL;
target->date = NULL;
target->director = NULL;
free(target);
target = NULL;
return 0;
}
int lookup(char* feature, char* data, FILE* out) {
if (feature == NULL || data == NULL || head == NULL) {
return 1;
}
printf("LOOKUP, %s, %s\n", feature, data);
fprintf(out, "LOOKUP, %s, %s\n", feature, data);
Movie* target = head;
while (target != NULL) {
char success = 0;
if (strcmp(feature, "ID") == 0) {
if (get(atoi(data)) == NULL)
success++;
} else if (strcmp(feature, "TITLE") == 0) {
success += fnmatch(data, target->title, "FNM_NOCASE");
} else if (strcmp(feature, "DATE") == 0) {
success += fnmatch(data, target->date, "FNM_NOCASE");
} else if (strcmp(feature, "DIRECTOR") == 0) {
success += fnmatch(data, target->director, "FNM_NOCASE");
}
if (success == 0) {
printf("%s, %s, %s, %d\n", target->title, target->date, target->director, target->id);
fprintf(out, "%s, %s, %s, %d\n", target->title, target->date, target->director, target->id);
}
target = target->next;
}
return 0;
}
int display(char* feature, int order, int max, FILE* out) {
if (feature == NULL)
return 1;
printf("DISPLAY, %s, %d, %d\n", feature, order, max);
fprintf(out, "DISPLAY, %s, %d, %d\n", feature, order, max);
if (max <= 0) {
return 0;
} else if (max > size) {
max = size;
}
Movie* target = head;
int count = 0; // Number of Movies displayed.
int* countedIds = calloc(max, sizeof(int)); // Set 'em all to 0.
Movie* best = target;
while (count < max) {
while (target != NULL) {
if (idIncluded(target->id, countedIds, max) == 0) { // ID not counted yet. (Ignore counted ones)
if (order == 0) { // Ascending: smallest first.
if ( (strcmp(feature, "TITLE") == 0 && strcmp(target->title, best->title) < 0)
|| (strcmp(feature, "DATE") == 0 && strcmp(target->date, best->date) < 0)
|| (strcmp(feature, "DIRECTOR") == 0 && strcmp(target->director, best->director) < 0)
|| (strcmp(feature, "ID") == 0 && target->id < best->id) ) {
best = target;
}
} else { // Descending: largest first.
if ( (strcmp(feature, "TITLE") == 0 && strcmp(target->title, best->title) > 0)
|| (strcmp(feature, "DATE") == 0 && strcmp(target->date, best->date) > 0)
|| (strcmp(feature, "DIRECTOR") == 0 && strcmp(target->director, best->director) > 0)
|| (strcmp(feature, "ID") == 0 && target->id > best->id) ) {
best = target;
}
}
}
target = target->next; // Okay if target is NULL.
}
countedIds[count] = best->id;
printf("%s, %s, %s, %d\n", best->title, best->date, best->director, best->id);
fprintf(out, "%s, %s, %s, %d\n", best->title, best->date, best->director, best->id);
count++;
// Set best to an uncounted ID.
Movie* nextBest = head;
while (nextBest != NULL) {
if (idIncluded(nextBest->id, countedIds, max) == 0) {
best = nextBest;
break;
} else
nextBest = nextBest->next;
}
}
return 0;
}
int idIncluded(int id, int* idList, size_t len) {
for (int i = 0; i < len; i++) {
if (id == idList[i])
return 1;
}
return 0;
}