// A simple database to demonstrate all the parts you have learned // and maybe for some real world use for you depending on how you write it // database.c // K. J. Rock // November 11, 2018 // for Bacona Design LLC #include "database.h" #define COUNT 1051 // huge employment bump in November 2018 // working functions void addRecord(void); // add record manually int save(void); // needs work to use any filename instead of myList.dat int read(void); // reads myList.dat and no others int print(void); // prints all fields of all records int report(void); // initial attempt at filtering on a field value // functions needing work void deleteNode(struct node *here); // not yet deleting void swap(struct node *start, struct node *ep); // helper function for sort routine void sort(int); // not yet, need to add sorting field choice // random data generators void getName(void); // get name from women.txt or men.txt struct data *newData(void); // create random data for node void addNode(void); // add new node with randomly generated data //////////////////////////////////////////////////////////////////////// // need these functions to really feel like a database // one that can be useful for day to day stuff // input/output are randomly generated now // edit is related to input, don't create new but read and overwrite // Reports yes but they lead to read() and write() // Sort by your choice of field by tree or function // search within an indexed array // lists: arrays, linked lists, trees, queue? // delete a node of the linked list //////////////////////////////////////////////////////////////////////// int main(void) { int choice; char filename[128]; int loop = 1; // loop until this becomes a zero // need to instantiate a list here head = NULL; // empty list state tail = NULL; // these guard values are necessary. at least for head srand((unsigned) time(NULL)); // randomize seed from time getName(); // get lists of 100 men's and 100 women's first names while (loop) { // now a bit of old fashioned command line UI printf("\n"); printf("\tMenu\n"); printf("1) Add a new record\n"); // records?? in sub menu printf("2) Edit a record\n"); printf("3) Delete a record\n"); printf("4) Print all parts of all records\n"); printf("\n"); printf("5) Read file\n"); // ask for file name printf("6) Find a record\n"); printf("7) Print a report\n"); // ask for file name printf("8) Save records\n"); printf("9) Exit\n"); printf("10) \n"); printf("11) Sort on key\n"); printf("23) Display file statistics\n"); printf("\n"); printf("27) Ask for a filename\n"); printf("\n"); printf("Please make your choice => "); // need to change to sscanf() so I can trap for // non-numeric characters if (scanf(" %d", &choice)) printf("Your choice was #%d\n\n", choice); switch (choice) { case 1: addRecord(); break; case 2: printf("edit is not implemented yet\n"); break; case 3: printf("delete is not yet implemented\n"); // void deleteNode(struct node *here); break; case 4: print(); break; case 5: read(); break; case 6: printf("find is not yet implemented\n"); break; case 7: // needs work to choose report criteria(on) report(); break; case 8: save(); break; case 9: loop = 0; // flag to drop out of menu loop break; case 10: break; case 11: printf("\n"); printf("\tMenu\n"); printf("1) Use id as key\n"); // records?? in sub menu printf("2) Use age as key\n"); printf("3) Use salary as key\n"); printf("4) Use seniority as key\n"); printf("Please make your choice => "); if (scanf(" %d", &choice)) sort(choice); break; case 23: printf("display statistics is not implemented yet\n"); break; case 27: // ask for a file name printf("Please give me the name of your list => "); if (scanf(" %s", filename)) ; puts(filename); break; } } } // addNode(); was for adding random records //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Tool kit of parts from lessons 5 sortLink, 6 tree, 3 structure // parts of 7 search, 8 string, and 13 queue too /* ========================================================================== */ /* */ /* tree.c */ /* (c) April 7, 2017 K. J. Rock */ /* */ /* Build a binary tree from random data */ /* show inherent sorting of tree */ /* */ /* ========================================================================== */ /* #include #include #include struct data // create a structure to hold the data necessary to the problem { int age; // min 20 max 70 int salary; // min $30,000 max $95,000 int seniority; // years of service 0 - 45 }; struct node // create a node structure for the tree { struct data *data; // data pointer. struct node *left, *right; // tree structure pointers }; // allocate the space for the data and then fill each field // newNode() helper function. struct data * newData(void) { struct data *myData; myData = (struct data *) malloc(sizeof(struct data)); myData->age = rand() % 50 + 20; myData->salary = rand() % 65000 + 50000; myData->seniority = rand() % 45; return (myData); } struct node * newNode(void) { struct node *myNode; myNode = (struct node *) malloc(sizeof(struct node)); // create new node myNode->data = newData(); // add data to our new node myNode->left = NULL; myNode->right = NULL; return (myNode); } void printInorder(struct node *node) { if (node == NULL) // the tree is empty return; // First recurse on left child printInorder(node->left); // Then print the data of node printf("age %3d \t", node->data->age); printf("salary $%5d \t", node->data->salary); printf("seniority %3d \t", node->data->seniority); // the data lives at the following memory address //printf("data is here %p \n", node->data); printf("\n"); // Now recurse on right child printInorder(node->right); } // insert myNode into tree struct node * treeInsert(struct node *root, struct node *myNode) { if (root == NULL) // empty tree { printf("node\n"); // sanity check root = myNode; } else { int isLeft = 0; // direction flag struct node *ptr = root; struct node *prev = NULL; // walk the tree until there is space for a new node while (ptr != NULL) { prev = ptr; // change for different sort order if (myNode->data->age < ptr->data->age) //if (myNode->data->salary < ptr->data->salary) //if (myNode->data->seniority < ptr->data->seniority) { printf("left\n"); // sanity check isLeft = 1; // set left flag ptr = ptr->left; } else { printf("right\n"); // sanity check isLeft = 0; // set right flag ptr = ptr->right; } } // fill space at leaf with new node if (isLeft) prev->left = myNode; // set new node as left leaf else prev->right = myNode; // set new node as right leaf } return root; } int main(void) { static struct node *root; time_t t; // structure to hold computer's current time srand((unsigned) time(&t)); // randomize by seeding from time root = NULL; // start with an empty tree for (int i = 0; i < 43; i++) // fill the tree { root = treeInsert(root, newNode()); } printInorder(root); // walk tree, print in order } */ // Parker, on the prom at Harvard University: "If all the ladies were laid end to end, I wouldn't be surprised." struct data * newData(void) { struct data *myData; static int i = 43; // our founder holds id #42 to honor Douglas Adams myData = (struct data *) malloc(sizeof(struct data)); myData->id = i++; myData->age = rand() % 50 + 20; myData->salary = (float) (rand() % 95000 + 30000); myData->seniority = rand() % 45; return (myData); } void addNode(void) { struct node *myNode; myNode = (struct node *) malloc(sizeof(struct node)); // create new node myNode->data = newData(); // add data to our new node if (head == NULL) // empty list case { head = myNode; myNode->next = NULL; } else // non-empty list { tail->next = myNode; myNode->prev = tail; } tail = myNode; } void addRecord(void) { int id, age, seniority; float salary; struct node *myNode; struct data *myData; myNode = (struct node *) malloc(sizeof(struct node)); // create new node myData = (struct data *) malloc(sizeof(struct data)); myNode->data = myData; // add data to our new node myNode->next = NULL; // guard values myNode->prev = NULL; // this module needs some trapping // I entered 140,000 for the salary and blew it up! // did not like that comma one bit // I need to catch it before it bites me printf("\n\n"); // ask user for manual input printf("Add a new record to the list\n"); printf("\n"); printf("Please type the employee's id number => "); if (scanf(" %d", &id)) printf("id = %d\n", id); printf("Age => "); if (scanf(" %d", &age)) printf("age = %d\n", age); printf("Salary => "); if (scanf(" %f", &salary)) printf("salary = %10.2f\n", salary); printf("Seniority => "); if (scanf(" %d", &seniority)) printf("seniority = %d\n", seniority); printf("\n\n"); myData->id = id; myData->age = age; myData->salary = salary; myData->seniority = seniority; if (head == NULL) // empty list case { head = myNode; } else // non-empty list { tail->next = myNode; // add at end of list myNode->prev = tail; } tail = myNode; } void deleteNode(struct node *here) { if ((here->next == NULL) && (here->prev == NULL)) { // only one left in list case free(here->data); // free data memory space free(here); // free list node memory space printf("List is now empty.\n"); return; } if (here->prev != NULL) // you want to delete the first node here->prev->next = here->next; else { head = here->next; head->prev = NULL; } if (here->next != NULL) // you want to delete the last node here->next->prev = here->prev; else { tail = here->prev; // you're deleting node from the middle of the list tail->next = NULL; } free(here->data); // free data memory space free(here); // free list node memory space } // get name from women.txt or men.txt void getName(void) { //int c; FILE *fp = NULL; // guard value fp = fopen("men.txt", "r"); // open file for read if (fp != NULL) { for (int i = 0; i < 100; i++) { if (fscanf(fp, "%s", str)) ; if (fscanf(fp, "%d", &dummy)) ; // eats rank which is not used here s = (char *) malloc(strlen(str)); man[i] = s; s[0] = str[0]; // copy first letter unchanged for (int j = 1; j < (int) strlen(str); j++) s[j] = str[j] + 32; // change to lower case s[strlen(str)] = '\0'; } fclose(fp); } fp = fopen("women.txt", "r"); if (fp != NULL) { for (int i = 0; i < 100; i++) { if (fscanf(fp, "%s", str)) ; // read string into str[] array if (fscanf(fp, "%d", &dummy)) ; // eats rank which is unused s = (char *) malloc(strlen(str)); // allocate space for string woman[i] = s; // point woman array at new string space s[0] = str[0]; // set pointer s to first char of name string for (int j = 1; j < (int) strlen(str); j++) s[j] = str[j] + 32; // change to lower case s[strlen(str)] = '\0'; } fclose(fp); } } // sort helper function void swap(struct node *start, struct node *ep) { // notice how only the pointers to the data change struct data *temp; // while the data stays in the very same place it started temp = ep->data; ep->data = start->data; start->data = temp; } // change sort to take an input // this input determines which field is used as the key for sorting // so sort(1) would sort on the first field? // age, id, salary, seniority?? // a simple selection sort void sort(int choice) { struct node *start, *ptr; // working pointers start = head; // start at the head of the list while (start != NULL) { // find the smallest and move it into the first position ptr = start; while (ptr != NULL) { // change next line to reflect sort index of choice switch (choice) { case 1: // use id as the key if (ptr->data->id < start->data->id) swap(start, ptr); // swap the pointers, the data stays in place break; case 2: // use age as key if (ptr->data->age < start->data->age) swap(start, ptr); // swap the pointers, the data stays in place break; case 3: // use salary as key if (ptr->data->salary < start->data->salary) swap(start, ptr); break; case 4: // use seniority as key if (ptr->data->seniority < start->data->seniority) swap(start, ptr); break; } // if (ptr->data->salary >= start->data->salary) // if (ptr->data->seniority >= start->data->seniority) // if (ptr->data->age < start->data->age) // change < to >= for fun //if (ptr->data->age < start->data->age) /* { swap(start, ptr); // swap the pointers, the data stays in place } */ ptr = ptr->next; // step inner loop } start = start->next; // step outer loop, find next smallest list member } } int save(void) { FILE *fp; fp = fopen("myList.dat", "w"); // walk the list and print out the data it holds ep = head; while (ep != NULL) { fprintf(fp, "%3d", ep->data->id); fprintf(fp, " %3d", ep->data->age); fprintf(fp, " %10.2f", ep->data->salary); fprintf(fp, " %3d", ep->data->seniority); fprintf(fp, "\n"); ep = ep->next; } fclose(fp); return 0; } int read(void) // string pointer to the filename) { int id, age, seniority; float salary; struct node *myNode; struct data *myData; FILE *fp; // ask for a file name // printf("Please give me the name of your list => "); // if(scanf(" %s", filename); // puts(filename); head = NULL; tail = NULL; fp = fopen("myList.dat", "r"); //fp = fopen(str ptr my file, "r"); while (1) { if (fscanf(fp, "%d", &id) == EOF) break; if (fscanf(fp, "%d", &age) == EOF) break; if (fscanf(fp, "%f", &salary) == EOF) break; if (fscanf(fp, "%d", &seniority) == EOF) break; /* printf("id %3d\t\t", id); printf("age %3d\t\t", age); printf("salary $%8.2f\t", salary); printf("seniority %3d\n", seniority); */ myNode = (struct node *) malloc(sizeof(struct node)); // create new node myData = (struct data *) malloc(sizeof(struct data)); myNode->data = myData; // add data to our new node myData->id = id; myData->age = age; myData->salary = salary; myData->seniority = seniority; if (head == NULL) // empty list case { head = myNode; } else // non-empty list { tail->next = myNode; // add at end of list myNode->prev = tail; } tail = myNode; } fclose(fp); return 0; } // walk the list and print out the data it holds // need to expand this into a more thorough reporting tool // choice of fields to print // as well as choice of range of values in those fields // Maybe get to ANDing and ORing choices together. // That would require I write my own db language // I think not, I'll just mirror the SQL forms I need // remember: nothing fancy, light, fast int print(void) { ep = head; while (ep != NULL) { printf("id %3d\t\t", ep->data->id); printf("age %3d\t\t", ep->data->age); printf("salary $%10.2f\t", ep->data->salary); printf("seniority %3d\n", ep->data->seniority); ep = ep->next; } printf("\n"); return 0; } int report(void) { ep = head; while (ep) { //if ((ep->data->age < 55) && (ep->data->salary > 250000)) if (ep->data->salary > 250000) { printf("id %3d\t\t", ep->data->id); printf("age %3d\t\t", ep->data->age); printf("salary $%10.2f\t", ep->data->salary); printf("seniority %3d\n", ep->data->seniority); } ep = ep->next; } printf("\n"); return 0; } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // need these functions to really feel like a database // one that can be useful for day to day stuff // input/output are randomly generated now // edit is related to input, don't create new but read and overwrite // Reports yes but they lead to read() and write() // Sort by your choice of field by tree or function // search within an indexed array // delete a node of the linked list // lists: arrays, linked lists, trees, queue? // Remo Williams: Do you always talk like a Chinese fortune cookie? // [Outraged, Chiun strikes Remo in his solar plexus. // Remo stumbles to the window, // partially paralyzed, and in pain] // Chiun: Chinese! *Korean* is the most perfect creature ever // to sanctify the earth with the imprint of its foot. ////////////////////////////////////////////////////////////////////////