// 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 #include #include #include #include "database.h" struct data // create an employee record { int id; int age; // min 20 max 70 float salary; // min $30,000 max $95,000 int seniority; // years of service 0 - 45 // hire date??? // a date type?? }; struct node // create a node structure for the linked list { struct data *data; // these two data's are not the same. struct node *next, *prev; // for doubly linked list struct node *left, *right; // for tree in the future }; struct node *head, *tail, *ep; // head, tail, & employee pointers // allocate the space for the data and then fill each field // addNode() helper function. 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); } // add a new node to the linked list // it calls the above function for the problem data. // This abstraction aids writing code. // It separates the data from the linked list structure. // This makes sorting easy because the data is pointed to not part of the list 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; } 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 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 = %f\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; myNode->prev = tail; } tail = myNode; } // deleteNode is for completeness. It will be used in the future. // Notice how you need to free the data node memory // prior to freeing the node memory. // If you don't do this in the correct order you'll have a "memory leak". // That means the memory you allocated is now floating around // without a pointer to it. So you can't find it and the OS // can't put it back into the free memory pool. // Over time this really screws things up and can crash the system. 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 } // sort helper function void swap(struct node *start, struct node *ep) { // notice how only the pointers to the data change struct data *temp; temp = ep->data; ep->data = start->data; start->data = temp; } // a simple selection sort, pretty much brute force // scan the list with two pointers. // if the second is less than the first then swap them. void sort(void) { 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 // if (ptr->data->id < start->data->id) // 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 { 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 } } // 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?? 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, " %8.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; 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; myNode->prev = tail; } tail = myNode; } fclose(fp); return 0; } // walk the list and print out the data it holds 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 $%8.2f\t", ep->data->salary); printf("seniority %3d\n", ep->data->seniority); ep = ep->next; } printf("\n\n"); return 0; } #define COUNT 1051 // huge employment bump in November 2018 int main(void) { // int choice; // int j, count = 20; // number of employees // int j; // randomize by seeding from time srand((unsigned) time(NULL)); /* j=0; while (j++ < COUNT) { addNode(); // add more employees randomly } */ read(); // print(); sort(); print(); // save(); /* j=0; count=2; while (j++ < count) { addRecord(); // add more employees manually } // walk the list and print out the data it holds ep = head; while (ep != NULL) { printf("age %3d\t\t", ep->data->age); printf("salary $%6.2f\t", ep->data->salary); printf("seniority %3d\t", ep->data->seniority); printf("data is here %p \n", ep->data); ep = ep->next; } sort(); // sort by age, salary, or seniority printf("\n\n\n"); // much needed whitespace j=0; count=2; while (j++ < count) { addRecord(); // add more employees manually } // walk the sorted list and show the results ep = head; while (ep != NULL) { printf("age %3d\t\t", ep->data->age); printf("salary $%6.2f\t", ep->data->salary); printf("seniority %3d\t", ep->data->seniority); printf("data is here %p \n", ep->data); ep = ep->next; } for (j=0; j<5; j++) // add five more nodes with data { addNode(); } j=0; count=2; while (j++ < count) { addRecord(); // add more employees manually } printf("\n\n\n"); // much needed whitespace ep = head; // show they are added at the end unsorted while (ep != NULL) { printf("age %3d\t\t", ep->data->age); printf("salary $%6.2f\t", ep->data->salary); printf("seniority %3d\t", ep->data->seniority); printf("data is here %p \n", ep->data); ep = ep->next; } */ /* // now a bit of old fashioned command line UI // printf("\n\n"); printf("Menu\n"); printf("1) Add a new record\n"); printf("2) Delete a record\n"); printf("3) Print a report\n"); printf("4) Print all parts of all records\n"); printf("9) Exit\n"); printf("\n"); printf("Please make your choice => "); if (scanf(" %d",&choice)) printf("Your choice was #%d\n\n", choice); */ } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// /* int main(void) { // 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 } */ //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Tool kit of parts from lessons 5 sortLink, 6 tree, 3 structure // parts of 7, 8, and 13 too // search, string, queue /* ========================================================================== */ /* */ /* 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 } //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// void delTree(struct node *root) { if (root != NULL) { delTree(root->left); delTree(root->right); free(root->data); free(root); } } ///////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////// */ /* Little test of steganography int RGBx(int r, int g, int b, int x) { r &= 0xFF; printf("%d ", r); g &= 0xFF; printf("%d ", g); b &= 0xFF; printf("%d ", b); x &= 0xFF; printf("%d \n", x); return ((x << 24) | (b << 16) | (g << 8) | r); } //color = RGBx(128, 0, 0, 'c'); // embed an ASCII character in a pixel color = RGBx(200, 128, 52, 'f'); printf("RGBx => %x => %d\n", color, color); int c; unsigned int color; FILE *fp; //fp = fopen("feynman.jpg", "r"); fp = fopen("eye.bmp", "r"); while ((c = fgetc(fp)) != EOF) printf("%x ", c); for (int i=0; i<500; i++) { printf("%x ", fgetc(fp)); } fclose(fp); */ // from queue S1L13 char *man[100]; char *woman[100]; // pointer to 100 men's & 100 women's names char str[80]; // allocated from stack and uses 80 chars int dummy; // throw away excess digit in each record of the file char *s; // allocated from heap and can be quite large // 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); } }