Uploaded most of my stuff
This commit is contained in:
parent
ff7991c82b
commit
0641107f4b
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,243 @@
|
|||
/* matrilineal
|
||||
*
|
||||
* Build a simple, non-sorted tree of mother-daughter relationships
|
||||
*
|
||||
* Created by Nunthatinn Veerapaiboon, 30 Jan 2025
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
/* Adds person with a given name at the root.
|
||||
*/
|
||||
#define MAX_CHILDREN 10
|
||||
#define MAX_NAME_LENGTH 25
|
||||
|
||||
typedef struct NODE_T
|
||||
{
|
||||
char name[MAX_NAME_LENGTH];
|
||||
int numChildren;
|
||||
struct NODE_T * parent;
|
||||
struct NODE_T *children[MAX_CHILDREN];
|
||||
|
||||
} NODE_T;
|
||||
|
||||
NODE_T* root = NULL;
|
||||
|
||||
NODE_T* createNode(char* name) {
|
||||
NODE_T* newNode = (NODE_T*)malloc(sizeof(NODE_T));
|
||||
if (newNode == NULL) {
|
||||
printf("Memory allocation failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
strncpy(newNode->name, name, MAX_NAME_LENGTH - 1);
|
||||
newNode->name[MAX_NAME_LENGTH - 1] = '\0';
|
||||
newNode->numChildren = 0;
|
||||
newNode->parent = NULL;
|
||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
newNode->children[i] = NULL;
|
||||
}
|
||||
printf("Added\n");
|
||||
return newNode;
|
||||
}
|
||||
|
||||
// create Root
|
||||
NODE_T* addRoot(char* name)
|
||||
{
|
||||
if (root != NULL)
|
||||
{
|
||||
printf("Root already exists.\n");
|
||||
return root;
|
||||
}
|
||||
root = createNode(name);
|
||||
return root;
|
||||
}
|
||||
|
||||
// Helper function to find a node by name (DFS)
|
||||
NODE_T* findNode(NODE_T* currentNode, char* name)
|
||||
{
|
||||
if (currentNode == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
// Found at current node
|
||||
if (strcmp(currentNode->name, name) == 0)
|
||||
{
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
for (int i = 0; i < currentNode->numChildren; i++)
|
||||
{
|
||||
// recursively find in Children node
|
||||
NODE_T* found = findNode(currentNode->children[i], name);
|
||||
// Return node if it was found
|
||||
if (found != NULL)
|
||||
{
|
||||
return found;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Adds person with a given name and mother's name to the tree.
|
||||
*/
|
||||
NODE_T* addNonRoot(char* name, char* motherName)
|
||||
{
|
||||
if (root == NULL)
|
||||
{
|
||||
printf("Error: Root does not exist. Please add a root first.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Find mother node
|
||||
NODE_T* motherNode = findNode(root, motherName);
|
||||
if (motherNode == NULL)
|
||||
{
|
||||
printf("Not Found\n");
|
||||
return NULL;
|
||||
}
|
||||
if (motherNode->numChildren == MAX_CHILDREN)
|
||||
{
|
||||
printf("Unsuccessful\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create new node
|
||||
NODE_T* newNode = createNode(name);
|
||||
newNode->parent = motherNode;
|
||||
motherNode->children[motherNode->numChildren] = newNode;
|
||||
motherNode->numChildren++;
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/* Prints the person's mother.
|
||||
*/
|
||||
void queryMother(char* name)
|
||||
{
|
||||
if (root == NULL)
|
||||
{
|
||||
printf("The tree is empty.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
NODE_T* node = findNode(root, name);
|
||||
if (node == NULL)
|
||||
{
|
||||
printf("Not Found\n");
|
||||
}
|
||||
else if (node->parent == NULL)
|
||||
{
|
||||
printf("Not Found\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s", node->parent->name);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prints the person's daughters.
|
||||
*/
|
||||
void queryDaughters(char* name)
|
||||
{
|
||||
if (root == NULL)
|
||||
{
|
||||
printf("The tree is empty.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
NODE_T* node = findNode(root, name);
|
||||
if (node == NULL)
|
||||
{
|
||||
printf("Not Found\n");
|
||||
}
|
||||
else if (node->numChildren == 0)
|
||||
{
|
||||
printf("Not Found\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < node->numChildren; i++)
|
||||
{
|
||||
printf("%s ", node->children[i]->name);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
/* Prints the person's sisters.
|
||||
*/
|
||||
void querySisters(char* name)
|
||||
{
|
||||
if (root == NULL)
|
||||
{
|
||||
printf("The tree is empty.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
NODE_T* node = findNode(root, name);
|
||||
if (node == NULL)
|
||||
{
|
||||
printf("Not Found\n");
|
||||
}
|
||||
else if (node->parent == NULL)
|
||||
{
|
||||
printf("Not Found\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
NODE_T* motherNode = node->parent;
|
||||
if (motherNode->numChildren <= 1)
|
||||
{
|
||||
printf("Not Found\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < motherNode->numChildren; i++)
|
||||
{
|
||||
// Don't print self name
|
||||
if (strcmp(motherNode->children[i]->name, name) != 0)
|
||||
{
|
||||
printf("%s ", motherNode->children[i]->name);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char input[64]; // Input operation name
|
||||
char name[MAX_NAME_LENGTH]; // The name of the woman
|
||||
char motherName[MAX_NAME_LENGTH]; // The number of woman's mother
|
||||
int numOperations; // The number of operations.
|
||||
|
||||
scanf("%d", &numOperations);
|
||||
scanf("\n%s", name);
|
||||
NODE_T* root = addRoot(name);
|
||||
|
||||
for (int i = 1 ; i < numOperations ; i ++)
|
||||
{
|
||||
scanf("\n%s ", input);
|
||||
if (strcmp(input, "Add") == 0)
|
||||
{
|
||||
scanf("%s %s", name, motherName);
|
||||
addNonRoot(name, motherName);
|
||||
}
|
||||
else if (strcmp(input, "Mother") == 0)
|
||||
{
|
||||
scanf("%s", name);
|
||||
queryMother(name);
|
||||
}
|
||||
else if (strcmp(input, "Daughters") == 0)
|
||||
{
|
||||
scanf("%s", name);
|
||||
queryDaughters(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
scanf("%s", name);
|
||||
querySisters(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,226 @@
|
|||
/* matrilineal.c
|
||||
*
|
||||
* A non-sorted tree of mother-daughter relationships
|
||||
*
|
||||
* Created by Pasin Manurangsi, 2025-01-08
|
||||
* Modified by Thanawin Pattanaphol, 2025-05-02
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Adds person with a given name at the root
|
||||
*/
|
||||
#define MAX_CHILDREN 10
|
||||
#define MAX_NAME_LENGTH 25
|
||||
#define MAX_PATH_LENGTH 100
|
||||
|
||||
typedef struct NODE_T
|
||||
{
|
||||
char name[MAX_NAME_LENGTH];
|
||||
int numChildren;
|
||||
struct NODE_T* parent;
|
||||
struct NODE_T* children[MAX_CHILDREN];
|
||||
} NODE_T;
|
||||
|
||||
NODE_T* root = NULL;
|
||||
|
||||
NODE_T* createNode(char* name)
|
||||
{
|
||||
NODE_T* newNode = (NODE_T*)malloc(sizeof(NODE_T));
|
||||
|
||||
if (newNode == NULL)
|
||||
{
|
||||
printf("Memory allocation failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
strncpy(newNode->name, name, MAX_NAME_LENGTH - 1);
|
||||
newNode->name[MAX_NAME_LENGTH - 1] = '\0';
|
||||
newNode->numChildren = 0;
|
||||
newNode->parent = NULL;
|
||||
|
||||
for (int i = 0; i < MAX_CHILDREN; i++)
|
||||
{
|
||||
newNode->children[i] = NULL;
|
||||
}
|
||||
|
||||
printf("Added\n");
|
||||
return newNode;
|
||||
}
|
||||
|
||||
// Create the root
|
||||
NODE_T* addRoot(char* name)
|
||||
{
|
||||
if (root != NULL)
|
||||
{
|
||||
printf("Root already exists.\n");
|
||||
return root;
|
||||
}
|
||||
|
||||
root = createNode(name);
|
||||
return root;
|
||||
}
|
||||
|
||||
// Function that helps finding a node by name
|
||||
NODE_T* findNode(NODE_T* currentNode, char* name)
|
||||
{
|
||||
if (currentNode == NULL) return NULL;
|
||||
if (strcmp(currentNode->name, name) == 0) return currentNode;
|
||||
|
||||
for (int i = 0; i < currentNode->numChildren; i++)
|
||||
{
|
||||
NODE_T* found = findNode(currentNode->children[i], name);
|
||||
if (found != NULL) return found;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Adds person with a given name and mother's name to the tree.
|
||||
*/
|
||||
NODE_T* addNonRoot(char* name, char* motherName)
|
||||
{
|
||||
if (root == NULL)
|
||||
{
|
||||
printf("Error: Root does not exist. Please add a root first.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NODE_T* motherNode = findNode(root, motherName);
|
||||
if (motherNode == NULL)
|
||||
{
|
||||
printf("Unsuccessful\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (motherNode->numChildren == MAX_CHILDREN)
|
||||
{
|
||||
printf("Unsuccessful\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NODE_T* newNode = createNode(name);
|
||||
newNode->parent = motherNode;
|
||||
motherNode->children[motherNode->numChildren++] = newNode;
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/* DFS function
|
||||
*/
|
||||
void dfsPrintDescendants(NODE_T* node)
|
||||
{
|
||||
for (int i = 0; i < node->numChildren; i++)
|
||||
{
|
||||
printf("%s ", node->children[i]->name);
|
||||
dfsPrintDescendants(node->children[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prints the descendants of a given node.
|
||||
*/
|
||||
void printDescendants(char* name)
|
||||
{
|
||||
NODE_T* node = findNode(root, name);
|
||||
if (node == NULL || node->numChildren == 0)
|
||||
{
|
||||
printf("Not Found\n");
|
||||
return;
|
||||
}
|
||||
dfsPrintDescendants(node);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
/* DFS function to find the maximum chain
|
||||
*/
|
||||
void dfsFindMaxChain(
|
||||
NODE_T* node,
|
||||
NODE_T* path[],
|
||||
int depth,
|
||||
NODE_T* maxPath[],
|
||||
int* maxDepth
|
||||
)
|
||||
{
|
||||
path[depth] = node;
|
||||
|
||||
if (node->numChildren == 0)
|
||||
{
|
||||
if (depth + 1 > *maxDepth)
|
||||
{
|
||||
*maxDepth = depth + 1;
|
||||
for (int i = 0; i <= depth; i++)
|
||||
{
|
||||
maxPath[i] = path[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < node->numChildren; i++)
|
||||
{
|
||||
dfsFindMaxChain(
|
||||
node->children[i],
|
||||
path,
|
||||
depth + 1,
|
||||
maxPath,
|
||||
maxDepth
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to print the longest chain
|
||||
void printLongestChain()
|
||||
{
|
||||
if (root == NULL)
|
||||
{
|
||||
printf("Tree is empty\n");
|
||||
return;
|
||||
}
|
||||
NODE_T* path[MAX_PATH_LENGTH];
|
||||
NODE_T* maxPath[MAX_PATH_LENGTH];
|
||||
int maxDepth = 0;
|
||||
|
||||
dfsFindMaxChain(root, path, 0, maxPath, &maxDepth);
|
||||
|
||||
for (int i = 0; i < maxDepth; i++)
|
||||
{
|
||||
printf("%s ", maxPath[i]->name);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
char input[64];
|
||||
char name[MAX_NAME_LENGTH];
|
||||
char motherName[MAX_NAME_LENGTH];
|
||||
int numOperations;
|
||||
|
||||
scanf("%d", &numOperations);
|
||||
scanf("%s", name);
|
||||
addRoot(name);
|
||||
|
||||
for (int i = 1; i < numOperations; i++)
|
||||
{
|
||||
scanf("%s", input);
|
||||
if (strcmp(input, "Add") == 0)
|
||||
{
|
||||
scanf("%s %s", name, motherName);
|
||||
addNonRoot(name, motherName);
|
||||
}
|
||||
else if (strcmp(input, "Descendant") == 0)
|
||||
{
|
||||
scanf("%s", name);
|
||||
printDescendants(name);
|
||||
}
|
||||
else if (strcmp(input, "Max") == 0)
|
||||
{
|
||||
printLongestChain();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,177 @@
|
|||
/* AICE Tree
|
||||
*
|
||||
* Build a sorted binary tree for competency information
|
||||
*
|
||||
* Template for Fundamental Data Structures Lab 3
|
||||
* Created by Nunthatinn Veerapaiboon, 2025-02-15
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_COMPETENCY_CODE 8
|
||||
#define MAX_COMPETENCY_TITLE 64
|
||||
|
||||
// Define the structs here
|
||||
// Node Binary tree structure
|
||||
typedef struct NODE_BT {
|
||||
char competency_code[8];
|
||||
char competency_title[64];
|
||||
int credit;
|
||||
int year;
|
||||
int semester;
|
||||
struct NODE_BT *leftChildren;
|
||||
struct NODE_BT *rightChildren;
|
||||
} NODE_BT;
|
||||
|
||||
// Declare a global variable for the root of the binary tree
|
||||
NODE_BT* root = NULL;
|
||||
|
||||
/* Creates the node containing compentency's information
|
||||
**** You may change the type of the function to make it matches the function
|
||||
output ****
|
||||
*/
|
||||
NODE_BT * create_node(char competency_code[MAX_COMPETENCY_CODE], char competency_title[MAX_COMPETENCY_TITLE], int credit, int year, int semester)
|
||||
{
|
||||
NODE_BT* newNode = (NODE_BT*)malloc(sizeof(NODE_BT));
|
||||
if (newNode == NULL) {
|
||||
printf("Memory allocation failed.\n");
|
||||
exit(1);
|
||||
}
|
||||
strncpy(newNode->competency_code, competency_code, MAX_COMPETENCY_CODE - 1);
|
||||
newNode->competency_code[MAX_COMPETENCY_CODE - 1] = '\0';
|
||||
strncpy(newNode->competency_title, competency_title, MAX_COMPETENCY_TITLE - 1);
|
||||
newNode->competency_title[MAX_COMPETENCY_TITLE - 1] = '\0';
|
||||
newNode->credit = credit;
|
||||
newNode->year = year;
|
||||
newNode->semester = semester;
|
||||
newNode->leftChildren = NULL;
|
||||
newNode->rightChildren = NULL;
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/* Inserts the node into the sorted binary tree
|
||||
**** You may add the function's parameter ****
|
||||
*/
|
||||
void insert(NODE_BT* newNode, NODE_BT* currentNode)
|
||||
{
|
||||
if (root == NULL) {
|
||||
root = newNode;
|
||||
return;
|
||||
}
|
||||
|
||||
// compare year
|
||||
if (currentNode->year < newNode->year) {
|
||||
if (currentNode->rightChildren == NULL)
|
||||
currentNode->rightChildren = newNode;
|
||||
else
|
||||
insert(newNode, currentNode->rightChildren);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentNode->year > newNode->year) {
|
||||
if (currentNode->leftChildren == NULL)
|
||||
currentNode->leftChildren = newNode;
|
||||
else
|
||||
insert(newNode, currentNode->leftChildren);
|
||||
return;
|
||||
}
|
||||
|
||||
// If years are equal, compare semester
|
||||
if (currentNode->semester < newNode->semester) {
|
||||
if (currentNode->rightChildren == NULL)
|
||||
currentNode->rightChildren = newNode;
|
||||
else
|
||||
insert(newNode, currentNode->rightChildren);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentNode->semester > newNode->semester) {
|
||||
if (currentNode->leftChildren == NULL)
|
||||
currentNode->leftChildren = newNode;
|
||||
else
|
||||
insert(newNode, currentNode->leftChildren);
|
||||
return;
|
||||
}
|
||||
|
||||
// If both year and semester are equal, compare competency codes
|
||||
for (int i = 0; i < MAX_COMPETENCY_CODE; i++) {
|
||||
if (currentNode->competency_code[i] < newNode->competency_code[i]) {
|
||||
if (currentNode->rightChildren == NULL)
|
||||
currentNode->rightChildren = newNode;
|
||||
else
|
||||
insert(newNode, currentNode->rightChildren);
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentNode->competency_code[i] > newNode->competency_code[i]) {
|
||||
if (currentNode->leftChildren == NULL)
|
||||
currentNode->leftChildren = newNode;
|
||||
else
|
||||
insert(newNode, currentNode->leftChildren);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Prints competencies in-order
|
||||
*/
|
||||
void print_subtree(NODE_BT* currentNode)
|
||||
{
|
||||
if(currentNode->leftChildren != NULL)
|
||||
{
|
||||
print_subtree(currentNode->leftChildren);
|
||||
}
|
||||
printf("%d %d %s %s\n", currentNode->year, currentNode->semester, currentNode->competency_code, currentNode->competency_title);
|
||||
if(currentNode->rightChildren != NULL)
|
||||
{
|
||||
print_subtree(currentNode->rightChildren);
|
||||
}
|
||||
}
|
||||
|
||||
void print_competencies()
|
||||
{
|
||||
print_subtree(root);
|
||||
}
|
||||
|
||||
/* Free the contents
|
||||
*/
|
||||
void freeBT(NODE_BT* node) {
|
||||
if (node == NULL) return; // Base case: empty node
|
||||
|
||||
freeBT(node->leftChildren); // Free left subtree
|
||||
freeBT(node->rightChildren); // Free right subtree
|
||||
|
||||
free(node); // Free the current node
|
||||
}
|
||||
|
||||
// Wrapper function to free the entire tree
|
||||
void free_all() {
|
||||
freeBT(root); // Free all nodes starting from the root
|
||||
root = NULL; // Set root to NULL to prevent dangling reference
|
||||
}
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
char competency_code[8];
|
||||
char competency_title[64];
|
||||
int credit;
|
||||
int year;
|
||||
int semester; // Spring = 0, Fall = 1
|
||||
int num_operations; // The number of operations.
|
||||
|
||||
scanf("%d", &num_operations);
|
||||
|
||||
for (int i = 0; i < num_operations; i++)
|
||||
{
|
||||
scanf("%7s %63s %d %d %d", competency_code, competency_title, &credit,
|
||||
&year, &semester);
|
||||
NODE_BT * new_node = create_node(competency_code, competency_title, credit, year, semester); // You may change the datatype
|
||||
insert(new_node, root); // You may add the function's argument
|
||||
}
|
||||
print_competencies();
|
||||
free_all();
|
||||
}
|
||||
|
|
@ -0,0 +1,337 @@
|
|||
/* orgChart
|
||||
*
|
||||
* Build a corporate hierarchy structure and sorted binary tree
|
||||
*
|
||||
* Created by Chavakorn Arunkunarax and Phasit Thanitkul, 2025-01-12
|
||||
* Modified by Thanawin Pattanaphol, 2025-05-02
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
|
||||
// Structure for an employee in the organization chart (general tree node)
|
||||
typedef struct EmployeeNode
|
||||
{
|
||||
char name[32];
|
||||
char employeeId[8];
|
||||
char jobTitle[32];
|
||||
struct EmployeeNode *supervisor;
|
||||
struct EmployeeNode *firstChild;
|
||||
struct EmployeeNode *nextSibling;
|
||||
} EmployeeNode;
|
||||
|
||||
// Structure for a node in the sorted binary tree (index)
|
||||
typedef struct IndexNode
|
||||
{
|
||||
char key[40]; // Concatenation of Name and EmployeeId
|
||||
EmployeeNode *employeePtr;
|
||||
struct IndexNode *left;
|
||||
struct IndexNode *right;
|
||||
} IndexNode;
|
||||
|
||||
EmployeeNode *root = NULL; // Root of the organization chart
|
||||
IndexNode *indexRoot = NULL; // Root of the sorted binary tree
|
||||
|
||||
// Function to create a new employee node
|
||||
EmployeeNode *createEmployeeNode(char *name, char *employeeId, char *jobTitle)
|
||||
{
|
||||
EmployeeNode *newNode = (EmployeeNode *)malloc(sizeof(EmployeeNode));
|
||||
|
||||
if (newNode == NULL)
|
||||
{
|
||||
perror("Failed to allocate memory for employee node");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
strcpy(newNode->name, name);
|
||||
strcpy(newNode->employeeId, employeeId);
|
||||
strcpy(newNode->jobTitle, jobTitle);
|
||||
newNode->supervisor = NULL;
|
||||
newNode->firstChild = NULL;
|
||||
newNode->nextSibling = NULL;
|
||||
return newNode;
|
||||
}
|
||||
|
||||
// Function to create a new index node
|
||||
IndexNode *createIndexNode(char *key, EmployeeNode *employeePtr)
|
||||
{
|
||||
IndexNode *newNode = (IndexNode *)malloc(sizeof(IndexNode));
|
||||
|
||||
if (newNode == NULL)
|
||||
{
|
||||
perror("Failed to allocate memory for index node");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
strcpy(newNode->key, key);
|
||||
newNode->employeePtr = employeePtr;
|
||||
newNode->left = NULL;
|
||||
newNode->right = NULL;
|
||||
return newNode;
|
||||
}
|
||||
|
||||
// Function to insert into the sorted binary tree
|
||||
IndexNode *insertIndexNode(IndexNode *root, char *key, EmployeeNode *employeePtr)
|
||||
{
|
||||
if (root == NULL)
|
||||
{
|
||||
return createIndexNode(key, employeePtr);
|
||||
}
|
||||
|
||||
int cmp = strcmp(key, root->key);
|
||||
if (cmp < 0)
|
||||
{
|
||||
root->left = insertIndexNode(root->left, key, employeePtr);
|
||||
}
|
||||
else if (cmp > 0)
|
||||
{
|
||||
root->right = insertIndexNode(root->right, key, employeePtr);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
/* Adds employee to the corporate hierarchy structure and sorted binary tree
|
||||
*/
|
||||
void addEmployee(char *name, char *employeeId, char *jobTitle, char *supervisorName, char *supervisorId)
|
||||
{
|
||||
EmployeeNode *newEmployee = createEmployeeNode(name, employeeId, jobTitle);
|
||||
char indexKey[40];
|
||||
sprintf(indexKey, "%s%s", name, employeeId);
|
||||
indexRoot = insertIndexNode(indexRoot, indexKey, newEmployee);
|
||||
|
||||
if (strcmp(supervisorName, "--") == 0)
|
||||
{
|
||||
if (root == NULL)
|
||||
{
|
||||
root = newEmployee;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error: Multiple root employees found.\n");
|
||||
// Handle this error as needed, maybe free the newEmployee
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
EmployeeNode *supervisorNode = NULL;
|
||||
// Search for the supervisor in the existing organization chart
|
||||
// A simple linear search here. For larger organizations, a hash map would be more efficient.
|
||||
// However, for this exercise, we'll keep it straightforward.
|
||||
EmployeeNode *queue[100]; // Assuming a reasonable maximum number of employees for the queue
|
||||
int head = 0, tail = 0;
|
||||
|
||||
if (root != NULL)
|
||||
{
|
||||
queue[tail++] = root;
|
||||
}
|
||||
|
||||
while (head < tail)
|
||||
{
|
||||
EmployeeNode *current = queue[head++];
|
||||
|
||||
if (strcmp(current->name, supervisorName) == 0 && strcmp(current->employeeId, supervisorId) == 0)
|
||||
{
|
||||
supervisorNode = current;
|
||||
break;
|
||||
}
|
||||
|
||||
EmployeeNode *child = current->firstChild;
|
||||
while (child != NULL)
|
||||
{
|
||||
queue[tail++] = child;
|
||||
child = child->nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
if (supervisorNode != NULL)
|
||||
{
|
||||
newEmployee->supervisor = supervisorNode;
|
||||
if (supervisorNode->firstChild == NULL)
|
||||
{
|
||||
supervisorNode->firstChild = newEmployee;
|
||||
}
|
||||
else
|
||||
{
|
||||
EmployeeNode *sibling = supervisorNode->firstChild;
|
||||
while (sibling->nextSibling != NULL)
|
||||
{
|
||||
sibling = sibling->nextSibling;
|
||||
}
|
||||
sibling->nextSibling = newEmployee;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "cannot_add %s %s\n", name, employeeId);
|
||||
// Free the allocated memory for the employee node since it couldn't be added
|
||||
free(newEmployee);
|
||||
}
|
||||
}
|
||||
|
||||
/* Prints the corporate hierarchy structure, pre-order
|
||||
*/
|
||||
void printCorporateHierarchyHelper(EmployeeNode *node, int level)
|
||||
{
|
||||
if (node == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < level; i++)
|
||||
{
|
||||
printf("...");
|
||||
}
|
||||
|
||||
printf("%s %s %s\n", node->name, node->employeeId, node->jobTitle);
|
||||
EmployeeNode *child = node->firstChild;
|
||||
while (child != NULL)
|
||||
{
|
||||
printCorporateHierarchyHelper(child, level + 1);
|
||||
child = child->nextSibling;
|
||||
}
|
||||
}
|
||||
|
||||
void printCorporateHierarchy()
|
||||
{
|
||||
printCorporateHierarchyHelper(root, 0);
|
||||
}
|
||||
|
||||
// Helper function for in-order traversal of the index tree to print sorted list
|
||||
void printSortedListHelper(IndexNode *root)
|
||||
{
|
||||
if (root == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
printSortedListHelper(root->left);
|
||||
printf("%s %s %s\n", root->employeePtr->name, root->employeePtr->employeeId, root->employeePtr->jobTitle);
|
||||
printSortedListHelper(root->right);
|
||||
}
|
||||
|
||||
/* Prints the sorted list of employees
|
||||
*/
|
||||
void printSortedList()
|
||||
{
|
||||
printSortedListHelper(indexRoot);
|
||||
}
|
||||
|
||||
/* Searches for an employee in the corporate hierarchy structure using the index tree
|
||||
*/
|
||||
void searchEmployee(char *name, char *employeeId)
|
||||
{
|
||||
char searchKey[40];
|
||||
sprintf(searchKey, "%s%s", name, employeeId);
|
||||
|
||||
IndexNode *current = indexRoot;
|
||||
while (current != NULL)
|
||||
{
|
||||
int cmp = strcmp(searchKey, current->key);
|
||||
if (cmp < 0)
|
||||
{
|
||||
current = current->left;
|
||||
}
|
||||
else if (cmp > 0)
|
||||
{
|
||||
current = current->right;
|
||||
}
|
||||
else
|
||||
{
|
||||
EmployeeNode *employee = current->employeePtr;
|
||||
printf("%s %s %s\n", employee->jobTitle, employee->supervisor ? employee->supervisor->name : "Top", employee->employeeId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("not_found\n");
|
||||
}
|
||||
|
||||
// Helper function to free the organization chart tree
|
||||
void freeOrganizationChart(EmployeeNode *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EmployeeNode *child = node->firstChild;
|
||||
|
||||
while (child != NULL)
|
||||
{
|
||||
EmployeeNode *next = child->nextSibling;
|
||||
freeOrganizationChart(child);
|
||||
child = next;
|
||||
}
|
||||
free(node);
|
||||
}
|
||||
|
||||
// Helper function to free the index tree
|
||||
void freeIndexTree(IndexNode *node)
|
||||
{
|
||||
if (node == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
freeIndexTree(node->left);
|
||||
freeIndexTree(node->right);
|
||||
free(node);
|
||||
}
|
||||
|
||||
/* Free the contents of the datastructures used */
|
||||
void freeAll()
|
||||
{
|
||||
freeOrganizationChart(root);
|
||||
freeIndexTree(indexRoot);
|
||||
root = NULL;
|
||||
indexRoot = NULL;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
char input[128];
|
||||
char name[32];
|
||||
char employeeId[8];
|
||||
char jobTitle[32];
|
||||
char supervisorName[32];
|
||||
char supervisorId[8];
|
||||
int numEmployees;
|
||||
int numQuestions;
|
||||
|
||||
if (scanf("%d", &numEmployees) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading number of employees.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (scanf("%d", &numQuestions) != 1)
|
||||
{
|
||||
fprintf(stderr, "Error reading number of queries.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numEmployees; i++) {
|
||||
if (scanf("%s %s %s %s %s", name, employeeId, jobTitle, supervisorName, supervisorId) != 5)
|
||||
{
|
||||
fprintf(stderr, "Error reading employee data.\n");
|
||||
return 1;
|
||||
}
|
||||
addEmployee(name, employeeId, jobTitle, supervisorName, supervisorId);
|
||||
}
|
||||
|
||||
printCorporateHierarchy();
|
||||
|
||||
for (int i = 0; i < numQuestions; i++)
|
||||
{
|
||||
if (scanf("%s %s", name, employeeId) != 2)
|
||||
{
|
||||
fprintf(stderr, "Error reading query.\n");
|
||||
return 1;
|
||||
}
|
||||
searchEmployee(name, employeeId);
|
||||
}
|
||||
|
||||
printSortedList();
|
||||
freeAll();
|
||||
return 0;
|
||||
}
|
||||
Binary file not shown.
|
|
@ -0,0 +1,446 @@
|
|||
/* cmkl_book
|
||||
*
|
||||
* Build a social network with basic functionalities
|
||||
*
|
||||
* Template for Fundamental Data Structures Lab 2
|
||||
* Modified by Thanawin Pattanaphol, 2025-05-02
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define MAX_ACCOUNTS 1000 // Arbitrary limit for simplicity
|
||||
#define MAX_FRIENDS 100 // Arbitrary limit for simplicity
|
||||
|
||||
// Structure for an account
|
||||
typedef struct Account
|
||||
{
|
||||
char emailAddress[55];
|
||||
char firstName[25];
|
||||
char lastName[25];
|
||||
bool isActive;
|
||||
int numFriends;
|
||||
struct Account *friends[MAX_FRIENDS];
|
||||
} Account;
|
||||
|
||||
// Hash table structure
|
||||
#define HASH_TABLE_SIZE 101 // A prime number for better distribution
|
||||
|
||||
typedef struct HashNode
|
||||
{
|
||||
char emailAddress[55];
|
||||
Account *account;
|
||||
struct HashNode *next;
|
||||
} HashNode;
|
||||
|
||||
HashNode *accountHashTable[HASH_TABLE_SIZE];
|
||||
int numAccounts = 0;
|
||||
Account accounts[MAX_ACCOUNTS];
|
||||
|
||||
// Hash function
|
||||
unsigned long hash(const char *str)
|
||||
{
|
||||
unsigned long hash = 5381;
|
||||
int c;
|
||||
while ((c = *str++))
|
||||
hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
|
||||
return hash % HASH_TABLE_SIZE;
|
||||
}
|
||||
|
||||
// Find an account by email in the hash table
|
||||
Account *findAccount(const char *emailAddress)
|
||||
{
|
||||
unsigned long index = hash(emailAddress);
|
||||
HashNode *current = accountHashTable[index];
|
||||
while (current != NULL)
|
||||
{
|
||||
if (strcmp(current->emailAddress, emailAddress) == 0 && current->account->isActive)
|
||||
{
|
||||
return current->account;
|
||||
}
|
||||
current = current->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Insert an account into the hash table
|
||||
void insertAccount(Account *account)
|
||||
{
|
||||
unsigned long index = hash(account->emailAddress);
|
||||
HashNode *newNode = (HashNode *)malloc(sizeof(HashNode));
|
||||
|
||||
if (newNode == NULL)
|
||||
{
|
||||
perror("Failed to allocate memory for hash node");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
strcpy(newNode->emailAddress, account->emailAddress);
|
||||
newNode->account = account;
|
||||
newNode->next = accountHashTable[index];
|
||||
accountHashTable[index] = newNode;
|
||||
}
|
||||
|
||||
// Delete an account from the hash table (mark as inactive)
|
||||
Account *deleteAccountFromTable(const char *emailAddress)
|
||||
{
|
||||
unsigned long index = hash(emailAddress);
|
||||
HashNode *current = accountHashTable[index];
|
||||
HashNode *prev = NULL;
|
||||
while (current != NULL)
|
||||
{
|
||||
if (strcmp(current->emailAddress, emailAddress) == 0 && current->account->isActive)
|
||||
{
|
||||
current->account->isActive = false;
|
||||
return current->account;
|
||||
}
|
||||
prev = current;
|
||||
current = current->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Add a new account
|
||||
void newAccount(char *emailAddress, char *firstName, char *lastName)
|
||||
{
|
||||
if (numAccounts >= MAX_ACCOUNTS)
|
||||
{
|
||||
fprintf(stderr, "Error: Maximum number of accounts reached.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (findAccount(emailAddress) != NULL) {
|
||||
printf("Error: Duplicate\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Account *newAccountPtr = &accounts[numAccounts++];
|
||||
|
||||
strcpy(newAccountPtr->emailAddress, emailAddress);
|
||||
strcpy(newAccountPtr->firstName, firstName);
|
||||
strcpy(newAccountPtr->lastName, lastName);
|
||||
|
||||
newAccountPtr->isActive = true;
|
||||
newAccountPtr->numFriends = 0;
|
||||
|
||||
insertAccount(newAccountPtr);
|
||||
printf("Success\n");
|
||||
}
|
||||
|
||||
// Delete an account
|
||||
void deleteAccount(char *emailAddress)
|
||||
{
|
||||
Account *accountToDelete = deleteAccountFromTable(emailAddress);
|
||||
if (accountToDelete == NULL)
|
||||
{
|
||||
printf("Error: Not Found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove this account from the friend lists of others
|
||||
for (int i = 0; i < numAccounts; i++)
|
||||
{
|
||||
if (accounts[i].isActive)
|
||||
{
|
||||
Account *friendAccount = &accounts[i];
|
||||
for (int j = 0; j < friendAccount->numFriends; j++)
|
||||
{
|
||||
if (friendAccount->friends[j] == accountToDelete)
|
||||
{
|
||||
// Shift remaining friends to the left
|
||||
for (int k = j; k < friendAccount->numFriends - 1; k++)
|
||||
{
|
||||
friendAccount->friends[k] = friendAccount->friends[k + 1];
|
||||
}
|
||||
|
||||
friendAccount->numFriends--;
|
||||
break; // Only one instance of the deleted friend
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("Success %s %s\n", accountToDelete->firstName, accountToDelete->lastName);
|
||||
}
|
||||
|
||||
// Make two accounts friends
|
||||
void addFriend(char *firstEmailAddress, char *secondEmailAddress)
|
||||
{
|
||||
Account *account1 = findAccount(firstEmailAddress);
|
||||
Account *account2 = findAccount(secondEmailAddress);
|
||||
|
||||
if (account1 == NULL || account2 == NULL)
|
||||
{
|
||||
printf("Error: Account Not Found\n");
|
||||
return;
|
||||
}
|
||||
if (strcmp(firstEmailAddress, secondEmailAddress) == 0)
|
||||
{
|
||||
printf("Error: Can’t add friend to self\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bool areFriends = false;
|
||||
for (int i = 0; i < account1->numFriends; i++)
|
||||
{
|
||||
if (account1->friends[i] == account2)
|
||||
{
|
||||
areFriends = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (areFriends)
|
||||
{
|
||||
printf("Error: Accounts are already friends\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (account1->numFriends < MAX_FRIENDS && account2->numFriends < MAX_FRIENDS)
|
||||
{
|
||||
account1->friends[account1->numFriends++] = account2;
|
||||
account2->friends[account2->numFriends++] = account1;
|
||||
printf("Success\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Error: Maximum number of friends reached for one of the accounts.\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Unfriend two accounts
|
||||
void unfriend(char *firstEmailAddress, char *secondEmailAddress)
|
||||
{
|
||||
Account *account1 = findAccount(firstEmailAddress);
|
||||
Account *account2 = findAccount(secondEmailAddress);
|
||||
|
||||
if (account1 == NULL || account2 == NULL)
|
||||
{
|
||||
printf("Error: Account Not Found\n");
|
||||
return;
|
||||
}
|
||||
if (strcmp(firstEmailAddress, secondEmailAddress) == 0)
|
||||
{
|
||||
printf("Error: Can’t unfriend self\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int index1 = -1, index2 = -1;
|
||||
for (int i = 0; i < account1->numFriends; i++)
|
||||
{
|
||||
if (account1->friends[i] == account2)
|
||||
{
|
||||
index1 = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < account2->numFriends; i++)
|
||||
{
|
||||
if (account2->friends[i] == account1)
|
||||
{
|
||||
index2 = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (index1 == -1 || index2 == -1)
|
||||
{
|
||||
printf("Error: Can’t unfriend accounts that are not friends\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove from account1's friend list
|
||||
for (int i = index1; i < account1->numFriends - 1; i++)
|
||||
{
|
||||
account1->friends[i] = account1->friends[i + 1];
|
||||
}
|
||||
account1->numFriends--;
|
||||
|
||||
// Remove from account2's friend list
|
||||
for (int i = index2; i < account2->numFriends - 1; i++)
|
||||
{
|
||||
account2->friends[i] = account2->friends[i + 1];
|
||||
}
|
||||
account2->numFriends--;
|
||||
|
||||
printf("Success\n");
|
||||
}
|
||||
|
||||
// List all friends of an account
|
||||
void listFriends(char *emailAddress)
|
||||
{
|
||||
Account *account = findAccount(emailAddress);
|
||||
if (account == NULL)
|
||||
{
|
||||
printf("Error: Account Not Found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (account->numFriends == 0)
|
||||
{
|
||||
printf("No Friend\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < account->numFriends; i++)
|
||||
{
|
||||
printf("%s %s", account->friends[i]->firstName, account->friends[i]->lastName);
|
||||
|
||||
if (i < account->numFriends - 1)
|
||||
{
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// List friend suggestions for an account
|
||||
void listSuggestions(char *emailAddress)
|
||||
{
|
||||
Account *account = findAccount(emailAddress);
|
||||
if (account == NULL)
|
||||
{
|
||||
printf("Error: Account Not Found\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (account->numFriends == 0)
|
||||
{
|
||||
printf("No Friend Suggestion\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Account *suggestions[MAX_ACCOUNTS];
|
||||
int numSuggestions = 0;
|
||||
bool isSuggested;
|
||||
|
||||
for (int i = 0; i < account->numFriends; i++)
|
||||
{
|
||||
Account *friend = account->friends[i];
|
||||
|
||||
for (int j = 0; j < friend->numFriends; j++)
|
||||
{
|
||||
Account *potentialFriend = friend->friends[j];
|
||||
|
||||
// Don't suggest self or existing friends
|
||||
if (potentialFriend == account) continue;
|
||||
bool isAlreadyFriend = false;
|
||||
for (int k = 0; k < account->numFriends; k++)
|
||||
{
|
||||
if (account->friends[k] == potentialFriend)
|
||||
{
|
||||
isAlreadyFriend = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAlreadyFriend) continue;
|
||||
|
||||
// Check if already suggested
|
||||
isSuggested = false;
|
||||
for (int k = 0; k < numSuggestions; k++)
|
||||
{
|
||||
if (suggestions[k] == potentialFriend)
|
||||
{
|
||||
isSuggested = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isSuggested && potentialFriend->isActive)
|
||||
{
|
||||
suggestions[numSuggestions++] = potentialFriend;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numSuggestions == 0)
|
||||
{
|
||||
printf("No Friend Suggestion\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < numSuggestions; i++)
|
||||
{
|
||||
printf("%s %s", suggestions[i]->firstName, suggestions[i]->lastName);
|
||||
if (i < numSuggestions - 1)
|
||||
{
|
||||
printf(", ");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
// Free the contents of the datastructures used
|
||||
void freeAll()
|
||||
{
|
||||
// Accounts array is statically allocated, no need to free individually
|
||||
// Free hash table nodes
|
||||
for (int i = 0; i < HASH_TABLE_SIZE; i++)
|
||||
{
|
||||
HashNode *current = accountHashTable[i];
|
||||
while (current != NULL)
|
||||
{
|
||||
HashNode *temp = current;
|
||||
current = current->next;
|
||||
free(temp);
|
||||
}
|
||||
accountHashTable[i] = NULL;
|
||||
}
|
||||
numAccounts = 0;
|
||||
}
|
||||
|
||||
int main() {
|
||||
char input[64]; // Input operation name
|
||||
char emailAddress[55]; // Email address of a person
|
||||
char secondEmailAddress[55]; // Email address of another person
|
||||
char firstName[25]; // First name of the person
|
||||
char lastName[25]; // First name of the person
|
||||
int numOperations; // The number of operations.
|
||||
|
||||
// Initialize hash table
|
||||
for (int i = 0; i < HASH_TABLE_SIZE; i++)
|
||||
{
|
||||
accountHashTable[i] = NULL;
|
||||
}
|
||||
|
||||
scanf("%d", &numOperations);
|
||||
for (int i = 0; i < numOperations; i++)
|
||||
{
|
||||
scanf("\n%s", input);
|
||||
if (strcmp(input, "New") == 0)
|
||||
{
|
||||
scanf(" %s %s %s", emailAddress, firstName, lastName);
|
||||
newAccount(emailAddress, firstName, lastName);
|
||||
}
|
||||
else if (strcmp(input, "Delete") == 0)
|
||||
{
|
||||
scanf(" %s", emailAddress);
|
||||
deleteAccount(emailAddress);
|
||||
}
|
||||
else if (strcmp(input, "Add") == 0)
|
||||
{
|
||||
scanf(" %s %s", emailAddress, secondEmailAddress);
|
||||
addFriend(emailAddress, secondEmailAddress);
|
||||
}
|
||||
else if (strcmp(input, "Unfriend") == 0)
|
||||
{
|
||||
scanf(" %s %s", emailAddress, secondEmailAddress);
|
||||
unfriend(emailAddress, secondEmailAddress);
|
||||
}
|
||||
else if (strcmp(input, "Friend") == 0)
|
||||
{
|
||||
scanf(" %s", emailAddress);
|
||||
listFriends(emailAddress);
|
||||
}
|
||||
else if (strcmp(input, "Suggestion") == 0)
|
||||
{
|
||||
scanf(" %s", emailAddress);
|
||||
listSuggestions(emailAddress);
|
||||
}
|
||||
}
|
||||
freeAll();
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in New Issue