The LevAWC Project
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Pages
demo04.c
1 /*
2  * _____
3  * ANSI / ___/
4  * / /__
5  * \___/
6  *
7  * Filename: demo04.c
8  * Author : Dan Levin
9  * Date : Fri Feb 20 10:32:01 2015
10  * Version : 0.51
11  * ---
12  * Description: Usage demo of the chained hashtable ADT - in LevAWC.
13  *
14  * Revision history: (this is where you document the diffs between versions...)
15  * Date Revision
16  * 130201 Created this program the first time..
17  * 130324 Changed functions "insert_nodes(), remove_nodes()" - and made the loops in them terminated by user interaction.
18  * 150123 Converted demo4.c to be menu-driven.
19  * 150220 Moved some utility functions from here - to file ../utils.c
20  * 150220 Source ready for version 0.5!
21  * 150318 Source ready for version 0.51
22  *
23  *
24  */
25 
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <time.h>
29 #include "chashtbl.h"
30 #include "utils.h"
31 
32 #ifndef OK
33 #define OK 0
34 #endif
35 
36 #ifndef TRUE
37 #define TRUE 1
38 #endif
39 
40 #ifndef FALSE
41 #define FALSE 0
42 #endif
43 
44 /* Some string macros for the main menu... */
45 #define MAIN_MENU_ROW "--- CHAINED HASH TABLE DEMO ---\nMENU: 0=Exit 1=Add_Node 2=Rem_Node 3=Search 4=Print\nSelection "
46 
47 #define NR_OF_ITEMS 30
48 #define NR_OF_BUCKETS 11
49 
50 /* FUNCTION-DECLARATIONS */
51 /* Application-specific callbacks */
52 void my_destroy(void *data);
53 void print(const void *data);
54 int my_cmp(const void *key1, const void *key2);
55 int my_match(const void *k1, const void *k2);
56 int my_hash(const void *key);
57 
58 /* Functions handling menu selections */
59 void ins_nodes(CHtbl tbl);
60 void rem_nodes(CHtbl tbl);
61 void find_node(CHtbl tbl);
62 void print_table(CHtbl tbl);
63 void final_status(CHtbl tbl);
64 
65 /* Misc. application functions.. */
66 void create_nodes(CHtbl list, int nr_of_nodes);
67 /* END-OF-FUNCTION-DECLARATIONS */
68 
69 /* FUNCTION-DEFINITIONS - the rest of the program */
70 /* --- Function: void my_destroy(void *data) --- */
71 void my_destroy(void *data)
72 {
73  free(data);
74 }
75 
76 /* --- Function: void print(const void *data) --- */
77 void print(const void *data)
78 {
79  printf(" %02d", *(int *)data);
80 }
81 
82 /* --- Function: int my_cmp(const int *key1, const int *key2) --- */
83 int my_cmp(const void *key1, const void *key2)
84 {
85  return (*(int *)key1 - *(int *)key2);
86 }
87 
88 /* --- Function: int my_match(const void *k1, const void *k2) --- */
89 int my_match(const void *k1, const void *k2)
90 {
91  return *(int *)k1 == *(int *)k2;
92 }
93 
94 /* --- Function: int my_hash(const void *key) --- */
95 int my_hash(const void *key)
96 {
97  return *(int *)key%NR_OF_BUCKETS;
98 }
99 
100 /* --- Function: void create_nodes(CHtbl tbl, int nr_of_nodes) --- */
101 void create_nodes(CHtbl tbl, int nr_of_nodes)
102 {
103  int i=0, *pi, retval, dupctr=0;
104 
105  my_clearscrn();
106  printf("--- INITIALIZING A CHAINED HASHTABLE, %d NODES, RANDOM INTEGER DATA ---", NR_OF_ITEMS);
107 
108  do
109  {
110  pi = (int *)malloc(sizeof(int));
111  MALCHK(pi);
112 
113  *pi = rand_int(1,99);
114 
115  if ((retval = CHTBLinsert(tbl, pi)) != OK) /* Insertion failed... */
116  {
117  if (retval == 1) /* Duplicate key value.. */
118  {
119  dupctr++;
120  my_destroy(pi); /* Free node - since duplicate.. */
121  }
122  else
123  {
124  prompt_and_pause("\nFatal error - bailing out..!\n");
125  CHTBLdestroy(tbl);
126  exit(-1);
127  }
128  }
129  } while (++i < nr_of_nodes);
130 
131  printf("\n\nCreated hash table - %d/%d successful insertions -- %d duplicates rejected...", CHTBLsize(tbl), nr_of_nodes, dupctr);
132 
133  printf("\nCurrent table status(%d nodes): ", CHTBLsize(tbl));
134  CHTBLprint(tbl, print);
135  prompt_and_pause("\n\n");
136 }
137 
138 /* --- Function: void ins_nodes(CHtbl tbl) --- */
139 void ins_nodes(CHtbl tbl)
140 {
141  int tmp, *pi, retval;
142  char mess[BUFSIZ];
143 
144  do
145  {
146  my_clearscrn();
147  printf("--- ADD NODE TO HASH TABLE ---\n");
148  printf("\nCurrent table status(%d nodes): ", CHTBLsize(tbl));
149  CHTBLprint(tbl, print);
150 
151  tmp = read_int("\nEnter data for node to be inserted (-1=Quit): ", 0, 0);
152 
153  if (tmp == -1)
154  break;
155 
156  pi = (int *)malloc(sizeof(int));
157  MALCHK(pi);
158 
159  *pi = tmp;
160 
161  if ((retval = CHTBLinsert(tbl, pi)) != OK) /* Insertion failed... */
162  {
163  if (retval == 1) /* Duplicate key value.. */
164  {
165  sprintf(mess, "Error: Node %d already present (bucket %d)..!", *pi, (*pi)%NR_OF_BUCKETS);
166  prompt_and_pause(mess);
167  my_destroy(pi); /* Free node - since being duplicate.. */
168  }
169  else
170  {
171  prompt_and_pause("\nFatal error - bailing out..:!\n");
172  CHTBLdestroy(tbl);
173  exit(-1);
174  }
175  }
176  else
177  {
178  sprintf(mess, "Node will be %d inserted - in bucket %d..", *(int *)pi, (*pi)%NR_OF_BUCKETS);
179  prompt_and_pause(mess);
180  }
181  } while (TRUE);
182 }
183 
184 /* --- Function: void rem_nodes(CHtbl tbl) --- */
185 void rem_nodes(CHtbl tbl)
186 {
187  int tmp, *pi, retval;
188  char mess[BUFSIZ];
189 
190  do
191  {
192  my_clearscrn();
193  printf("--- REMOVE NODE FROM HASH TABLE ---\n");
194  printf("\nCurrent table status(%d nodes): ", CHTBLsize(tbl));
195  CHTBLprint(tbl, print);
196 
197  tmp = read_int("\nEnter data for node to be removed (-1=Quit): ", 0, 0);
198 
199  if (tmp == -1)
200  break;
201 
202  pi = &tmp;
203  if ((retval = CHTBLremove(tbl, (void **)&pi)) != OK) /* Node removal failed.. */
204  {
205  /* Removal didn't work - node NOT found... */
206  if (retval == 1)
207  {
208  sprintf(mess, "Error: Node %d not found..!", *(int *)pi);
209  prompt_and_pause(mess);
210  }
211  else /* Serious failure..(-1 or -2) */
212  {
213  printf("\nFatal failure - bailing out...");
214  CHTBLdestroy(tbl);
215  exit(retval);
216  }
217  }
218  else
219  {
220  /* Removal succesful - notify user.. */
221  sprintf(mess, "Node %d will be removed - from bucket %d..!", *(int *)pi, (*pi)%NR_OF_BUCKETS);
222  prompt_and_pause(mess);
223  /* Free node - after being removed from table.. */
224  my_destroy(pi);
225  }
226  } while (TRUE);
227 }
228 
229 /* --- Function: void find_node(CHtbl tbl) --- */
230 void find_node(CHtbl tbl)
231 {
232  int tmp, *pi, retval;
233  char mess[BUFSIZ];
234 
235  do
236  {
237  my_clearscrn();
238  printf("--- SEARCH NODE IN HASH TABLE ---\n");
239  printf("\nCurrent table status(%d nodes): ", CHTBLsize(tbl));
240  CHTBLprint(tbl, print);
241 
242  tmp = read_int("\nEnter data for node to be found (-1=Quit): ", 0, 0);
243 
244  if (tmp == -1)
245  break;
246 
247  pi = &tmp;
248 
249  if ((retval = CHTBLlookup(tbl, (void **)&pi)) != OK) /* Node not found failed... */
250  {
251  sprintf(mess, "\nNode %d NOT FOUND!", *(int *)pi);
252  prompt_and_pause(mess);
253  }
254  else
255  {
256  sprintf(mess, "\nNode %d FOUND - in bucket %d..", *(int *)pi, (*pi)%NR_OF_BUCKETS);
257  prompt_and_pause(mess);
258  }
259  } while (TRUE);
260 }
261 
262 /* --- Function: void print_table(CHtbl tbl) --- */
263 void print_table(CHtbl tbl)
264 {
265  /* Print table status... */
266  my_clearscrn();
267  printf("--- PRINT TABLE ---");
268  printf("\n\nCurrent table status(%d nodes): ", CHTBLsize(tbl));
269  CHTBLprint(tbl, print);
270  prompt_and_pause("\n\n");
271 }
272 
273 /* --- Function: void final_status(CHtbl tbl) --- */
274 void final_status(CHtbl tbl)
275 {
276  my_clearscrn();
277  printf("--- FINAL STATUS ---\n");
278  /* Final table status... */
279  printf("\nFinal table status(%d nodes): ", CHTBLsize(tbl));
280  CHTBLprint(tbl, print);
281 }
282 
283 int main(void)
284 {
285  /* Declare YOUR variables here ! */
286  CHtbl mytbl;
287  int menu_choice;
288 
289  srand((unsigned int)time(NULL));
290 
291  if ((mytbl = CHTBLinit(NR_OF_BUCKETS, my_hash, my_match, my_destroy)) == NULL)
292  {
293  printf("\nFatal error - bailing out...\n!");
294  CHTBLdestroy(mytbl);
295  exit(-1);
296  }
297 
298  /* Initialize - and add nodes to the table... */
299  create_nodes(mytbl, NR_OF_ITEMS);
300 
301  /* Enter menu loop */
302  do
303  {
304  menu_choice = menu(MAIN_MENU_ROW, 0, 4);
305 
306  switch (menu_choice)
307  {
308  case 1:
309  ins_nodes(mytbl);
310  break;
311  case 2:
312  rem_nodes(mytbl);
313  break;
314  case 3:
315  find_node(mytbl);
316  break;
317  case 4:
318  print_table(mytbl);
319  break;
320  default:
321  final_status(mytbl);
322  break;
323  }
324  }
325  while (menu_choice);
326 
327  prompt_and_pause("\n\nLet's tidy up and destroy the hashtable..- Bye!");
328  CHTBLdestroy(mytbl);
329 
330  return 0;
331 }