Exported from Notepad++
1 /******************************************************************************************
2 *Filename: main.c
3 *Version: 1
4 *Author: Mostapha Abdelaziz
5 *Course: C Language
6 *Assignment Number: Assignment 2
7 *Assignment Name: Employee Database Implementation
8 *Purpose: Implement an employee database using linkedlist of structures
9 ******************************************************************************************/
10
11 #include "header.h"
12
13 /******************************************************************************************
14 *Function name: main
15 *Purpose: Main function for the employee database program calls other functions and loops through menu
16 *Function In parameters: None
17 *Function Out parameters: An integer for function success
18 *Version: 1
19 *Author: Mostapha Abdelaziz
20 ******************************************************************************************/
21 int main()
22 {
23 struct Employee *head;
24 struct Employee *employee;
25 int menuChoice = -1;
26 int empCount = 0;
27
28 /* print welcome */
29 printf("\nWelcome to the Employee Database\n--------------------------------\n");
30
31 /* allocate memory */
32 head = (struct Employee *)malloc(sizeof(struct Employee));
33 if (head == NULL)
34 {
35 printf("Error - could not allocate memory for an employee structure\n");
36 return EXIT_FAILURE;
37 }
38 head->next = NULL;
39
40 employee = (struct Employee *)malloc(sizeof(struct Employee));
41 if (employee == NULL)
42 {
43 printf("Error - could not allocate memory for an employee structure\n");
44 return EXIT_FAILURE;
45 }
46
47 /* loop through menu */
48 while (menuChoice != 5)
49 {
50 menuChoice = printMenu();
51 switch (menuChoice)
52 {
53 case 1:
54 /* add an employee if we do not have 150 */
55 if (empCount < 150)
56 {
57 employee->next = NULL;
58
59 /* ask for details */
60 printf("\nEnter information for employee %d\n\n", empCount + 1);
61 validateEmployeeDetails(employee);
62
63 /* first check if the name & age exist already */
64 if (empCount > 0 && findEmployee(head, employee->name, employee->age) == 0)
65 {
66 /* if they were found, print error */
67 printf("\nEmployee with name \"%s\" and age \"%d\" already exists. Employee was not added.\n", employee->name, employee->age);
68 }
69 else
70 {
71 /* otherwise place them in sorted */
72 addSortEmployee(head, employee, empCount);
73 empCount++;
74 }
75 }
76 else
77 {
78 printf("Database is full.\n");
79 }
80 break;
81 case 2:
82 /* delete an employee */
83 if (empCount > 0)
84 {
85 if (accessEmployee(head, employee, empCount, 1) == 1)
86 {
87 empCount--;
88 }
89 }
90 else
91 {
92 printf("There are no employees, use menu option 1 to add.\n");
93 }
94 break;
95 case 3:
96 /* edit an employee */
97 if (empCount > 0)
98 {
99 accessEmployee(head, employee, empCount, 2);
100 }
101 else
102 {
103 printf("There are no employees, use menu option 1 to add.\n");
104 }
105 break;
106 case 4:
107 /* print all employees */
108 if (empCount > 0)
109 {
110 printEmployees(head);
111 }
112 else
113 {
114 printf("There are no employees, use menu option 1 to add.\n");
115 }
116 break;
117 case 5:
118 /* exit program */
119 printf("\nGood Bye.\n");
120 break;
121 default:
122 return EXIT_FAILURE;
123 }
124 }
125
126 free(employee->next);
127 free(employee);
128 /* free every node */
129 while (head != NULL)
130 {
131 /* start from the head, free then move on */
132 employee = head;
133 head = head->next;
134 free(employee);
135 }
136
137 return EXIT_SUCCESS;
138 }
139
140 /******************************************************************************************
141 *Function name: menu
142 *Purpose: Prints the menu for the database functions and validates input
143 *Function In parameters: None
144 *Function Out parameters: The validated input for the menu
145 *Version: 1
146 *Authors: Mostapha Abdelaziz
147 ******************************************************************************************/
148 int printMenu()
149 {
150 char input[3];
151 int menuChoice = -1;
152
153 while (menuChoice == -1)
154 {
155 printf("\nPlease choose one of the following actions:\n1- Add an employee\n2- Delete an employee\n3- Edit an employee\n4- Print all employees\n5- Quit\nPlease your menu choice: ");
156
157 /* read input */
158 fgets(input, 5, stdin);
159 input[strcspn(input, "\n")] = 0;
160
161 /* check if it is an int, then range */
162 menuChoice = atoi(input);
163 if (menuChoice == 0)
164 {
165 if (menuChoice == 0 && input[0] == '0' && input[1] == '\0')
166 {
167 /* input was 0 */
168 printf("Option %d is not a valid choice. Options range from 1 to 5. Try again.\n", menuChoice);
169 menuChoice = -1;
170 }
171 else
172 {
173 /* input wasnt an int */
174 printf("Enter a valid whole number from 1 to 5. Try again.\n");
175 menuChoice = -1;
176 }
177 }
178 else if (menuChoice < 0 || menuChoice > 5)
179 {
180 /* if out of range */
181 printf("Option %d is not a valid choice. Options range from 1 to 5. Try again.\n", menuChoice);
182 menuChoice = -1;
183 }
184 }
185 return menuChoice;
186 }
187
188 /******************************************************************************************
189 *Function name: validateEmployeeDetails
190 *Purpose: Reads input and adds the information to a struct of an Employee
191 *Function In parameters: The employee to add information to
192 *Function Out parameters: None
193 *Version: 1
194 *Authors: Mostapha Abdelaziz
195 ******************************************************************************************/
196 void validateEmployeeDetails(struct Employee *employee)
197 {
198 char input[MAX_NAME_LENGTH];
199 int age = -1;
200 char tempChar;
201
202 input[0] = '\0';
203
204 /* ask for details and verify */
205 while (input[0] == '\0')
206 {
207 printf("Enter Employee Name: ");
208 /* store in temp variable, remove newline */
209 fgets(input, MAX_NAME_LENGTH, stdin);
210 input[strcspn(input, "\n")] = 0;
211 /* validate */
212 verifyString(input);
213 }
214 /* set first letter to capital if its a lower case letter */
215 tempChar = input[0];
216 if ((tempChar >= 97 && tempChar <= 122))
217 {
218 tempChar = tempChar - 32;
219 input[0] = tempChar;
220 }
221 /* copy into struct */
222 strcpy(employee->name, input);
223
224 input[0] = '\0';
225 /* ask for details and verify */
226 while (input[0] == '\0')
227 {
228 printf("Enter Employee Gender: ");
229 /* store and remove new line */
230 fgets(input, 20, stdin);
231 input[strcspn(input, "\n")] = 0;
232 /* validate */
233 verifyString(input);
234 }
235 /* set first letter to capital if its a lower case letter */
236 tempChar = input[0];
237 if ((tempChar >= 97 && tempChar <= 122))
238 {
239 tempChar = (tempChar - 32);
240 input[0] = tempChar;
241 }
242 /* copy into struct */
243 strcpy(employee->gender, input);
244
245 /* validate and save age */
246 while (age == -1)
247 {
248 printf("Enter Employee Age: ");
249 /* read input */
250 fgets(input, 20, stdin);
251 input[strcspn(input, "\n")] = 0;
252 age = validateInt(input);
253 }
254 employee->age = age;
255
256 input[0] = '\0';
257 /* ask for details and verify */
258 while (input[0] == '\0')
259 {
260 /* store and remove new line */
261 printf("Enter Employee Description: ");
262 fgets(input, MAX_JOB_LENGTH, stdin);
263 input[strcspn(input, "\n")] = 0;
264 /* validate */
265 verifyString(input);
266 }
267 /* set first letter to capital if its a lower case letter */
268 tempChar = input[0];
269 if ((tempChar >= 97 && tempChar <= 122))
270 {
271 tempChar = tempChar - 32;
272 input[0] = tempChar;
273 }
274 /* copy into struct */
275 strcpy(employee->description, input);
276 }
277
278 /******************************************************************************************
279 *Function name: validateInt
280 *Purpose: Reads input and validates an integer to ensure it is 0 or greater
281 *Function In parameters: The string input to validate if it was a integer
282 *Function Out parameters: The validated integer value
283 *Version: 1
284 *Authors: Mostapha Abdelaziz
285 ******************************************************************************************/
286 int validateInt(char *input)
287 {
288 int number;
289
290 /* check if it is an int, then range */
291 number = atoi(input);
292 if (number == 0)
293 {
294 if (number == 0 && input[0] == '0' && input[1] == '\0')
295 {
296 /* input was 0 */
297 printf("Cannot be 0. Try again.\n");
298 number = -1;
299 }
300 else
301 {
302 /* input wasnt an int */
303 printf("Input whole numbers only. try again.\n");
304 number = -1;
305 }
306 }
307 else if (number < 0)
308 {
309 /* if it is negative */
310 printf("Must be a positive number. Try again.\n");
311 number = -1;
312 }
313 else if (number > 150)
314 {
315 /* if it is too large */
316 printf("Input is too large. Try again.\n");
317 number = -1;
318 }
319
320 return number;
321 }
322
323 /******************************************************************************************
324 *Function name: verifyString
325 *Purpose: Takes a string and verifies it has no disallowed characters
326 *Function In parameters: The string to compare
327 *Function Out parameters: None
328 *Version: 1
329 *Authors: Mostapha Abdelaziz
330 ******************************************************************************************/
331 void verifyString(char *string)
332 {
333 char tempChar = string[0];
334 int i = 0;
335
336 /* confirm it does not begin with dash, apostrophe or space */
337 if (tempChar == 96 || tempChar == 45 || tempChar == 39 || tempChar == 32)
338 {
339 printf("Can not begin with \"%c\", try again.\n", tempChar);
340 i = strlen(string);
341 string[0] = '\0';
342 }
343 /* verify there are no invalid characters in the whole string */
344 while (i < strlen(string))
345 {
346 if (tempChar != 32 && tempChar != 39 && tempChar != 45 && tempChar != 96 && !(tempChar >= 65 && tempChar <= 90) && !(tempChar >= 97 && tempChar <= 122))
347 {
348 printf("Invalid character \"%c\" entered, try again.\n", tempChar);
349 string[0] = '\0';
350 i = strlen(string);
351 }
352 i++;
353 tempChar = string[i];
354 /* capitalise a letter if its preceeded by a space */
355 if (string[i - 1] == 32 && (tempChar >= 97 && tempChar <= 122))
356 {
357 tempChar = tempChar - 32;
358 string[i] = tempChar;
359 }
360 }
361 }
362
363 /******************************************************************************************
364 *Function name: addSortEmployee
365 *Purpose: Finds where to place the employee based on alphabetic order and places them
366 *Function In parameters: Head/first employee, employee being added and how many employees there are
367 *Function Out parameters: None
368 *Version: 1
369 *Authors: Mostapha Abdelaziz
370 ******************************************************************************************/
371 void addSortEmployee(struct Employee *head, struct Employee *employee, int empCount)
372 {
373
374 int i;
375
376 /* if it's the first one, add it to head otherwise make it current */
377 if (empCount == 0)
378 {
379 /* set as head */
380 *head = *employee;
381 }
382 else if (employee->name[0] < head->name[0])
383 {
384 /* if should be ordered before head, set head as the next data, and the employee as head */
385 if (employee->next == NULL)
386 {
387 employee->next = (struct Employee *)malloc(sizeof(struct Employee));
388 }
389 *employee->next = *head;
390 *head = *employee;
391 }
392 else
393 {
394 /* loop to check where it should enter */
395 for (i = 0; i < empCount; i++)
396 {
397 /* set head next if we are adding to the end */
398 if (head->next == NULL)
399 {
400 head->next = (struct Employee *)malloc(sizeof(struct Employee));
401 /* add to the end of list */
402 employee->next = NULL;
403 *head->next = *employee;
404 }
405 /* if its between two employees add in the middle */
406 else if (employee->name[0] < head->next->name[0])
407 {
408 /* add in sorted position */
409 if (employee->next == NULL)
410 {
411 employee->next = (struct Employee *)malloc(sizeof(struct Employee));
412 }
413 *employee->next = *head->next;
414 *head->next = *employee;
415
416 i = empCount;
417 }
418 head = head->next;
419 }
420 }
421 }
422
423 /******************************************************************************************
424 *Function name: findEmployee
425 *Purpose: Finds a provided employee based on name and age in provided list
426 *Function In parameters: The first employee in linked list, the employee name, the employee age
427 *Function Out parameters: Whether they were found or not
428 *Version: 1
429 *Authors: Mostapha Abdelaziz
430 ******************************************************************************************/
431 int findEmployee(struct Employee *head, char *name, int age)
432 {
433 int i = 1;
434
435 /* first check if it is the head */
436 if (strcmp(name, head->name) == 0 && head->age == age)
437 {
438 /* if it is return true for found */
439 return 0;
440 }
441 else
442 {
443 /* otherwise loop through until they're found */
444 while (head->next != NULL)
445 {
446 /* if its a match return success */
447 if (strcmp(name, head->next->name) == 0 && head->next->age == age)
448 {
449 return 0;
450 }
451 i++;
452 head = head->next;
453 }
454 }
455
456 /* if they were not found return false */
457 return 1;
458 }
459
460 /******************************************************************************************
461 *Function name: printEmployees
462 *Purpose: Prints all employees and their information
463 *Function In parameters: The first employee in linked list to print
464 *Function Out parameters: None
465 *Version: 1
466 *Authors: Mostapha Abdelaziz
467 ******************************************************************************************/
468 void printEmployees(struct Employee *employee)
469 {
470 int count = 1;
471
472 printf("\n-------------------------\n--- Employee Database ---\n-------------------------\n\n");
473 /* loop through until the struct is null */
474 while (employee != NULL)
475 {
476 /* print information */
477 printf("Employee %d\n------------\nName: %s \nGender: %s \nAge: %d \nJob Description: %s\n\n", count, employee->name, employee->gender, employee->age, employee->description);
478 /* increment count, set struct to next one */
479 count++;
480 employee = employee->next;
481 }
482 }
483
484 /******************************************************************************************
485 *Function name: accessEmployee
486 *Purpose: Accesses an selected employee to edit or delete them
487 *Function In parameters: The head of the linked list, a temporary employee, the number of employees and option for deleting or editing
488 *Function Out parameters: Integer how many were deleted
489 *Version: 1
490 *Authors: Mostapha Abdelaziz
491 ******************************************************************************************/
492 int accessEmployee(struct Employee *head, struct Employee *employee, int empCount, int option)
493 {
494 int success;
495 int i = 1;
496 char input[5];
497 int number = -1;
498 char *message;
499 int found = 0;
500 char name[MAX_NAME_LENGTH];
501 int age;
502 struct Employee *temp;
503
504 /* set a variable for deleting or editing */
505 if (option == 1)
506 {
507 message = "Delete";
508 }
509 else
510 {
511 message = "Edit";
512 }
513
514 printEmployees(head);
515
516 /* ask which one to delete */
517 while (number == -1)
518 {
519 printf("Enter employee number to select: ");
520 /* read input */
521 fgets(input, 20, stdin);
522 input[strcspn(input, "\n")] = 0;
523 number = validateInt(input);
524
525 if (number > empCount)
526 {
527 printf("Employee %d is the last employee, %d is too large. Try again.\n", empCount, number);
528 number = -1;
529 }
530 }
531
532 /* Loop until employee */
533 if (number > 2)
534 {
535 for (i = 1; i < number - 1; i++)
536 {
537 head = head->next;
538 }
539 }
540
541 /* confirm */
542 input[0] = '\0';
543 while (input[0] == '\0')
544 {
545 if (number == 1)
546 {
547 printf("%s employee %d: %s, age: %d ? (\"y\" for yes, \"n\" for no): ", message, number, head->name, head->age);
548 }
549 else
550 {
551 printf("%s employee %d: %s, age: %d ? (\"y\" for yes, \"n\" for no): ", message, number, head->next->name, head->next->age);
552 }
553 fgets(input, 20, stdin);
554 input[strcspn(input, "\n")] = 0;
555 /* lower case the letter */
556 if (input[0] >= 65 && input[0] <= 90)
557 {
558 input[0] = input[0] + 32;
559 }
560 /* check if valid */
561 if (input[1] != '\0' || (input[0] != 'y' && input[0] != 'n'))
562 {
563 printf("Invalid input \"%s\", try again.\n", input);
564 input[0] = '\0';
565 }
566 }
567
568 /* if they cancel set success as 0, else success is employee position */
569 if (input[0] != 'n')
570 {
571 success = number;
572 }
573 else
574 {
575 success = 0;
576 }
577
578 /* if employee found, delete and edit - function prints by default */
579 if (success != 0)
580 {
581 /* if we are deleting or editing the head */
582 if (success == 1)
583 {
584 /* copy if editing and delete the head */
585 if (option == 2)
586 {
587 *employee = *head;
588 employee->next = NULL;
589 }
590 if (head->next != NULL)
591 {
592 temp = head->next;
593 *head = *head->next;
594 free(temp);
595 }
596 else
597 {
598 head = NULL;
599 }
600 /* if we are deleting, print so otherwise enter new employee details */
601 if (option == 1)
602 {
603 printf("Employee was deleted.\n");
604 return 1;
605 }
606 else
607 {
608 /* edit the copied employee then re sort */
609 /* copy original name and age in case of duplicate */
610 strcpy(name, employee->name);
611 age = employee->age;
612
613 /* edit the employee */
614 editEmployee(employee);
615
616 /* first check if the name & age exist already */
617 found = findEmployee(head, employee->name, employee->age);
618 if (found == 0)
619 {
620 /* if they were found, print error */
621 printf("\nEmployee with name \"%s\" and age \"%d\" already exists. Changes were not made.\n", employee->name, employee->age);
622
623 /* copy original values back */
624 employee->age = age;
625 strcpy(employee->name, name);
626 }
627
628 /* insert employee */
629 addSortEmployee(head, employee, empCount - 1);
630 }
631 }
632 /* if we are editing or deleting other than the head */
633 else
634 {
635 /* copy if editing then remove the one after head */
636 if (option == 2)
637 {
638 *employee = *head->next;
639 employee->next = NULL;
640 }
641 temp = head->next;
642 head->next = head->next->next;
643 free(temp);
644 /* if we are deleting, print so otherwise enter new employee details */
645 if (option == 1)
646 {
647 printf("Employee was deleted.\n");
648 return 1;
649 }
650 else
651 {
652 /* edit the copied employee then re sort */
653 /* copy original name and age in case of duplicate */
654 strcpy(name, employee->name);
655 age = employee->age;
656
657 /* edit the employee */
658 editEmployee(employee);
659
660 /* first check if the name & age exist already */
661 found = findEmployee(head, employee->name, employee->age);
662 if (found == 0)
663 {
664 /* if they were found, print error */
665 printf("\nEmployee with name \"%s\" and age \"%d\" already exists. Changes were not made.\n", employee->name, employee->age);
666
667 /* copy original values back */
668 employee->age = age;
669 strcpy(employee->name, name);
670 }
671
672 /* insert employee */
673 addSortEmployee(head, employee, empCount - 1);
674 }
675 }
676 }
677 return 0;
678 }
679
680 /******************************************************************************************
681 *Function name: editEmployee
682 *Purpose: Asks what to edit of a provided employee
683 *Function In parameters: The employee to edit
684 *Function Out parameters: None
685 *Version: 1
686 *Authors: Mostapha Abdelaziz
687 ******************************************************************************************/
688 void editEmployee(struct Employee *employee)
689 {
690 char menuOption[10];
691 char string[MAX_NAME_LENGTH];
692 int age = -1;
693 int success;
694
695 /* loop for validation */
696 success = 1;
697 while (success == 1)
698 {
699 /* ask for what to change */
700 printf("Enter the corresponding option\n 1. Name\n 2. Gender\n 3. Age\n 4. Description\n > ");
701 fgets(menuOption, 10, stdin);
702 menuOption[strcspn(menuOption, "\n")] = 0;
703
704 /* if invalid print so */
705 if (menuOption[1] != '\0' || (menuOption[0] != '1' && menuOption[0] != '2' && menuOption[0] != '3' && menuOption[0] != '4'))
706 {
707 printf("Invalid menu choice \"%s\", try again.\n", menuOption);
708 success = 1;
709 }
710 else
711 {
712 /* otherwise implement choice */
713 success = 0;
714 string[0] = '\0';
715 switch (menuOption[0])
716 {
717 case '1':
718 /* ask for name */
719 while (string[0] == '\0')
720 {
721 printf("Enter new Employee Name: ");
722 /* store in temp variable, remove newline */
723 fgets(string, MAX_NAME_LENGTH, stdin);
724 string[strcspn(string, "\n")] = 0;
725 /* validate */
726 verifyString(string);
727 }
728 /* set first letter to capital if its a lower case letter */
729 if ((string[0] >= 97 && string[0] <= 122))
730 {
731 string[0] = string[0] - 32;
732 }
733
734 /* change employee name */
735 strcpy(employee->name, string);
736 break;
737 case '2':
738 /* ask for gender */
739 while (string[0] == '\0')
740 {
741 printf("Enter new Employee gender: ");
742 /* store in temp variable, remove newline */
743 fgets(string, MAX_NAME_LENGTH, stdin);
744 string[strcspn(string, "\n")] = 0;
745 /* validate */
746 verifyString(string);
747 }
748 /* set first letter to capital if its a lower case letter */
749 if ((string[0] >= 97 && string[0] <= 122))
750 {
751 string[0] = string[0] - 32;
752 }
753
754 /* change employee gender */
755 strcpy(employee->gender, string);
756 break;
757 case '3':
758 /* ask for employee age */
759 while (age == -1)
760 {
761 printf("Enter Employee Age: ");
762 /* read input */
763 fgets(string, 5, stdin);
764 string[strcspn(string, "\n")] = 0;
765 age = validateInt(string);
766 }
767 /* change employee age */
768 employee->age = age;
769 break;
770 case '4':
771 /* ask for description */
772 while (string[0] == '\0')
773 {
774 printf("Enter new Employee description: ");
775 /* store in temp variable, remove newline */
776 fgets(string, MAX_NAME_LENGTH, stdin);
777 string[strcspn(string, "\n")] = 0;
778 /* validate */
779 verifyString(string);
780 }
781 /* set first letter to capital if its a lower case letter */
782 if ((string[0] >= 97 && string[0] <= 122))
783 {
784 string[0] = string[0] - 32;
785 }
786
787 /* change employee description */
788 strcpy(employee->description, string);
789 break;
790 default:
791 printf("No changes were made.\n");
792 break;
793 }
794 }
795 }
796 }
797