The LevAWC Project
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Pages
demo02.c
1 /*
2  * _____
3  * ANSI / ___/
4  * / /__
5  * \___/
6  *
7  * Filename: demo02.c
8  * Author : Dan Levin
9  * Date : Fri Feb 20 10:11:42 2015
10  * Version : 0.51
11  * ---
12  * Description: A short C demo program testing the function interface of library LevAWC, doubly-linked list.
13  *
14  * Revision history: (this is where you document the diffs between versions...)
15  * Date Revision
16  * 121212 Created this program the first time..
17  * 121218 After some editing I consider this hack ready for going public :-)
18  * 130205 Used the new function 'int DLISTfind_remove()'...
19  * 130205 Further editing - more extensive error handling than before..
20  * 130411 Extended user interaction when inserting/removing nodes. User determines the number of operations..
21  * 150121 Converted demo2.c to be menu-driven.
22  * 150220 Moved some utility functions from here - to file ../utils.c
23  * 150220 Source ready for version 0.5!
24  * 150317 Source ready for version 0.51
25  *
26  */
27 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <time.h>
31 #include "dlist.h"
32 #include "utils.h"
33 
34 #ifndef OK
35 #define OK 0
36 #endif
37 
38 #ifndef TRUE
39 #define TRUE 1
40 #endif
41 
42 #ifndef FALSE
43 #define FALSE 0
44 #endif
45 
46 /* Some string macros for the main menu... */
47 #define MAIN_MENU_ROW "--- DOUBLY-LINKED LIST DEMO ---\nMENU: 0=Exit 1=Add_Node 2=Rem_Node 3=Search 4=Sort 5=Print\nSelection "
48 
49 #define NR_OF_ITEMS 10
50 #define MINLEN 5
51 
52 /* FUNCTION-DECLARATIONS */
53 /* Application-specific callbacks.. */
54 void my_destroy(void *data);
55 void print(const void *data);
56 int my_cmp(const void *key1, const void *key2);
57 int my_match(const void *k1, const void *k2);
58 
59 /* Functions handling menu selections */
60 void rem_nodes(Dlist list);
61 void ins_nodes(Dlist list);
62 void search_node(Dlist lst);
63 void sort_list(Dlist list);
64 void print_list(Dlist lst);
65 void final_status(Dlist list);
66 
67 /* Misc. application functions.. */
68 void create_random_nodes(Dlist list, int nr_of_nodes);
69 /* END-OF-FUNCTION-DECLARATIONS */
70 
71 /* FUNCTION DEFINITIONS - the rest of the program */
72 /* --- Function: void my_destroy(void *data) --- */
73 void my_destroy(void *data)
74 {
75  free(data);
76 }
77 
78 /* --- Function: void print(const void *data) --- */
79 void print(const void *data)
80 {
81  printf(" %02d", *(int *)data);
82 }
83 
84 /* --- Function: int my_cmp(const int *key1, const int *key2) --- */
85 int my_cmp(const void *key1, const void *key2)
86 {
87  return (*(int *)key1 - *(int *)key2);
88 }
89 
90 /* --- Function: int my_match(const void *k1, const void *k2) --- */
91 int my_match(const void *k1, const void *k2)
92 {
93  return *(int *)k1 == *(int *)k2;
94 }
95 
96 /* --- Function: void create_random_nodes(Dlist list, int nr_of_nodes) --- */
97 void create_random_nodes(Dlist list, int nr_of_nodes)
98 {
99  int i=0, *pi, retval;
100 
101  my_clearscrn();
102 
103  /* Initialize the list.. */
104  printf("--- CREATED A DOUBLY-LINKED LIST(%d NODES) - RANDOM INTEGER DATA ---", NR_OF_ITEMS);
105 
106  do
107  {
108  pi = (int *)malloc(sizeof(int));
109  MALCHK(pi);
110 
111  *pi = rand_int(1,50);
112 
113  /* Defensive programming... */
114  if (!DLISTsize(list))
115  retval=DLISTinsprev(list, NULL, pi);
116  else
117  retval=DLISTinsprev(list, DLISThead(list), pi);
118 
119  assert(retval == OK);
120 
121  } while (++i < nr_of_nodes);
122 
123  /* Display the list... */
124  printf("\n\nCurrent list status(%d nodes): ", DLISTsize(list));
125  printf("\nAscending : ");
126  DLISTtraverse(list, print, DLIST_FWD);
127  printf("\nDescending: ");
128  DLISTtraverse(list, print, DLIST_BWD);
129  prompt_and_pause("\n\n");
130 }
131 
132 /* --- Function: void ins_nodes(Dlist list) --- */
133 void ins_nodes(Dlist list)
134 {
135  int tmp, *pi;
136  DlistNode node;
137  char mess[BUFSIZ];
138 
139  do
140  {
141  my_clearscrn();
142  printf("--- ADD NODE WITH DATA=99 - AFTER USER-SPECIFIED NODE ---\n");
143  printf("\nCurrent list status(%d nodes): ", DLISTsize(list));
144  printf("\nAscending : ");
145  DLISTtraverse(list, print, DLIST_FWD);
146 
147  tmp = read_int("\nEnter (key)data, after which new node(key=99) will be inserted (-1=Quit): ", 0, 0);
148 
149  if (tmp == -1)
150  break;
151 
152  if ((node = DLISTfindnode(list, &tmp)) != NULL) /* Node found */
153  {
154  /* Insert node after first occurance of user-specified node */
155  pi = (int *)malloc(sizeof(int));
156  MALCHK(pi);
157 
158  *pi = 99;
159 
160  if ((DLISTinsnext(list, node, pi)) != OK)
161  {
162  printf("\nFatal error - exiting...");
163  DLISTdestroy(list);
164  exit(-1);
165  }
166  else
167  {
168  sprintf(mess, "Node 99 will be inserted after node %d", *(int *)DLISTdata(node));
169  prompt_and_pause(mess);
170  }
171  }
172  else
173  {
174  sprintf(mess, "Error: Node %d not found...!", tmp);
175  prompt_and_pause(mess);
176  }
177  } while (TRUE);
178 }
179 
180 /* --- Function: void rem_nodes(Dlist list) --- */
181 void rem_nodes(Dlist list)
182 {
183  int tmp, *pi, retval;
184  char mess[BUFSIZ];
185 
186  do
187  {
188  my_clearscrn();
189  printf("--- REMOVE NODE FROM LIST ---\n");
190  printf("\nCurrent list status(%d nodes): ", DLISTsize(list));
191  printf("\nAscending : ");
192  DLISTtraverse(list, print, DLIST_FWD);
193  printf("\nDescending: ");
194  DLISTtraverse(list, print, DLIST_BWD);
195 
196  tmp = read_int("\nEnter keydata for node to be removed (-1=Quit): ", 0, 0);
197 
198  if (tmp == -1)
199  break;
200 
201  /* Remove node - and free memory */
202  pi = &tmp;
203 
204  if ((retval = DLISTfind_remove(list, (void **)&pi)) != OK)
205  {
206  if (retval == 1)
207  {
208  sprintf(mess, "Error: Node %d not found..!", tmp);
209  prompt_and_pause(mess);
210  }
211  else
212  {
213  if (retval == -2)
214  printf("\nError: Match-callback is missing... - bailing out!");
215  else
216  printf("\nFatal error... - bailing out!");
217  DLISTdestroy(list);
218  exit(retval);
219  }
220  }
221  else
222  {
223  /* Removal succesful - notify user.. */
224  sprintf(mess, "Node %d will be removed..!", *(int *)pi);
225  prompt_and_pause(mess);
226  /* Free node - after being removed from list.. */
227  my_destroy(pi);
228  }
229  } while (TRUE);
230 }
231 /* --- Function: void search_node(Dlist lst) --- */
232 void search_node(Dlist lst)
233 {
234  int tmp;
235  char mess[BUFSIZ];
236 
237  do
238  {
239  my_clearscrn();
240  printf("--- SEARCH NODE ---\n");
241  printf("\nCurrent list status(%d nodes): ", DLISTsize(lst));
242  DLISTtraverse(lst, print, DLIST_FWD);
243 
244  tmp = read_int("\nEnter keydata for node to be found (-1=Quit): ", 0, 0);
245 
246  if (tmp == -1)
247  break;
248 
249  if (DLISTfindnode(lst, &tmp) == NULL) /* Node not found.. */
250  {
251  sprintf(mess, "Node %d NOT found..!", tmp);
252  prompt_and_pause(mess);
253  }
254  else
255  {
256  /* Search succesful - notify user.. */
257  sprintf(mess, "Node %d FOUND!", tmp);
258  prompt_and_pause(mess);
259  }
260  } while (TRUE);
261 }
262 
263 /* --- Function: void sort_list(Dlist list) --- */
264 void sort_list(Dlist list)
265 {
266  my_clearscrn();
267  printf("--- SORT LIST ---\n");
268  DLISTsort(list, my_cmp);
269  printf("\nCurrent list status(%d nodes): ", DLISTsize(list));
270  printf("\nAscending : ");
271  DLISTtraverse(list, print, DLIST_FWD);
272  printf("\nDescending: ");
273  DLISTtraverse(list, print, DLIST_BWD);
274  prompt_and_pause("\n\n");
275 }
276 
277 /* --- Function: void print_list(Dlist lst) --- */
278 void print_list(Dlist lst)
279 {
280  my_clearscrn();
281  printf("--- PRINT LIST ---\n");
282  /* Print list status... */
283  printf("\nCurrent list contents(%d nodes): ", DLISTsize(lst));
284  printf("\nAscending : ");
285  DLISTtraverse(lst, print, DLIST_FWD);
286  printf("\nDescending: ");
287  DLISTtraverse(lst, print, DLIST_BWD);
288  prompt_and_pause("\n\n");
289 }
290 
291 /* --- Function: void final_status(Dlist list) --- */
292 void final_status(Dlist list)
293 {
294  my_clearscrn();
295  printf("--- FINAL STATUS ---\n");
296  /* Final list status... */
297  printf("\nFinal list contents(%d nodes): ", DLISTsize(list));
298  printf("\nAscending : ");
299  DLISTtraverse(list, print, DLIST_FWD);
300  printf("\nDescending: ");
301  DLISTtraverse(list, print, DLIST_BWD);
302 }
303 
304 int main(void)
305 {
306  /* Declare YOUR variables here ! */
307  Dlist mylist;
308  int menu_choice;
309 
310  /* Seed to random generator and clear the screen.. */
311  srand((unsigned int)time(NULL));
312 
313  if ((mylist = DLISTinit(my_destroy)) == NULL)
314  {
315  printf("\nFatal error... - bailing out!");
316  DLISTdestroy(mylist);
317  exit(-1);
318  }
319 
320  /* Set match-callback into list structure.. */
321  DLISTsetmatch(mylist, my_match);
322 
323  /* Populate the (empty) list.. */
324  create_random_nodes(mylist, NR_OF_ITEMS);
325 
326  do
327  {
328  menu_choice = menu(MAIN_MENU_ROW, 0, 5);
329 
330  switch (menu_choice)
331  {
332  case 1:
333  ins_nodes(mylist);
334  break;
335  case 2:
336  rem_nodes(mylist);
337  break;
338  case 3:
339  search_node(mylist);
340  break;
341  case 4:
342  sort_list(mylist);
343  break;
344  case 5:
345  print_list(mylist);
346  break;
347  default:
348  final_status(mylist);
349  break;
350  }
351  }
352  while (menu_choice);
353 
354  /* ..and finally destroy the list. */
355  prompt_and_pause("\n\nLet's tidy up and destroy the list..- Bye!");
356  DLISTdestroy(mylist);
357 
358  return 0;
359 }