Listing 1

  1: /*
  2:  * MDBEDIT.C
  3:  *
  4:  * Program:  Mini-Database
  5:  * Written by: Leor Zolman
  6:  * Module:   Edit the Current Database
  7:  */
  8:
  9: #include <stdio.h>
 10: #include <stdlib.h>
 11: #include <string.h>
 12: #include <ctype.h>
 13:
 14: #include "mdb.h"
 15:
 16: static void fix_db(void);
 17:
 18: #define LIST_RECS 1   /* Edit menu action codes */
 19: #define NEXT      2
 20: #define PREVIOUS  3
 21: #define MODIFY    4
 22: #define NEW       5
 23: #define DELETE    6
 24: #define UNDELETE  7
 25: #define QUIT      8
 26: #define SELECT    9
 27: #define FIX       10
 28:
 29: static struct menu_item edit_menu[] =
 30: {
 31:   {LIST_RECS, "List Records"},
 32:   {NEXT, "Go to Next Record"},
 33:   {PREVIOUS, "Go to Previous Record"},
 34:   {MODIFY, "Modify Current Record"},
 35:   {NEW, "Add New Record"},
 36:   {DELETE, "Delete Current Record"},
 37:   {UNDELETE, "Un-Delete Current Record"},
 38:   {SELECT, "Select Record (by Record Number)"},
 39:   {FIX, "Fix Up Database"},
 40:   {QUIT, "Return to main Menu"},
 41:   {NULL}
 42: };
 43:
 44: /*
 45:  * Function:    edit_db
 46:  * Purpose:     Perform operations on current Database
 47:  * Parameter:   Database Name
 48:  * Return Value:  None
 49:  */
 50:
 51: void edit_db(char *db_name)
 52: {
 53:   int cur_rec = 0; /* current record number */
 54:   struct record *rp; /* ptr to current record */
 55:   char buf[150];
 56:   int i;
 57:
 58:   while (1)
 59:   {
 60:     rp = RECS[cur_rec];
 61:     printf("\nDatabase: %s\n", db_name);
 62:     if (n_recs)
 63:     {
 64:       printf("Current Record is #%d", cur_rec);
 65:       if (!rp->active)
 66:         printf(" (Deleted)");
 67:       printf(":\n");
 68:
 69:       printf("Name:   %s %s\n", rp->first, rp->last);
 70:       printf("ID#:    %ld\n", rp->id);
 71:       printf("Age:    %d\n", rp->age);
 72:       printf("Gender: %c\n", rp->gender);
 73:       printf("Salary: $%.2f\n", rp->salary);
 74:    }
 75:
 76:    switch(do_menu(edit_menu, "Edit Menu"))
 77:    {
 78:      case LIST_RECS:
 79:        for (i = 0; i < n_recs; i++)
 80:          printf("%4d: %s%s\n", i, RECS[i]->last,
 81:            RECS[i]->active ? "" : " (Deleted)");
 82:        printf("Press RETURN to continue:");
 83:        gets(buf);
 84:        break;
 85:
 86:      case NEXT:      /* find next active record: */
 87:        for (i = cur_rec + 1; i < n_recs; i++)
 88:          if (RECS[i]->active) /* skip inactives */
 89:            break;
 90:        if (i == n_recs)       /* over the top? */
 91:        {
 92:          printf("\aAt end of file.\n");
 93:          break;
 94:        }
 95:        cur_rec = i;
 96:        break;
 97:
 98:      case PREVIOUS: /* find previous active record: */
 99:        for (i = cur_rec - 1; i >= 0; i--)
100:          if (RECS[i]->active) /* skip inactives */
101:            break;
102:        if (i < 0)       /* "under the bottom"? */
103:        {
104:          printf("\aAt beginning of file.\n");
105:          break;
106:        }
107:        cur_rec = i;
108:        break;
109:
110:      case NEW:
111:        if (n_recs+1 > max_recs)
112:        {
113:          printf("Maximum # of records ");
114:          printf("(%d) reached.\n", max_recs);
115:          break;
116:        }
117:
118:        if ((rp = alloc_rec()) == NULL)
119:        {
120:          printf("Out of memory. Try Fixing ");
121:          printf("Database first...\n");
122:          break;
123:        }
124:                   /* make new record current: */
125:        cur_rec = n_recs++;
126:        RECS[cur_rec] = rp;
127:        rp->active = TRUE;
128:
129:        strcpy(rp->last,""); /* initialize the record */
130:        strcpy(rp->first,"");
131:        rp->id = 0;
132:        rp->age = 0;
133:        rp->gender = ' ';
134:        rp->salary = 0.; /* fall through to MODIFY */
135:
136:      case MODIFY:
137:        printf("Last Name [%s]: ", rp->last);
138:        if (strlen(gets(buf)) > 0)
139:          strcpy(rp->last, buf);
140:
141:        printf("First Name [%s]: ", rp->first);
142:        if (strlen(gets(buf)) > 0)
143:          strcpy(rp->first, buf);
144:
145:        printf("ID# [%ld]: ", rp->id);
146:        if (strlen(gets(buf)) > 0)
147:          rp->id = atol(buf);
148:
149:        printf("Age [%d] ", rp->age);
150:        if (strlen(gets(buf)) > 0)
151:          rp->age = atoi(buf);
152:
153:        printf("Gender [%c]: ", rp->gender);
154:        if (strlen(gets(buf)) > 0)
155:          rp->gender = toupper(*buf);
156:
157:        printf("Salary [%.2f]: ", rp->salary);
158:        if (strlen(gets(buf)) > 0)
159:          rp->salary = (float) atof(buf);
160:        break;
161:
162:      case DELETE:
163:        if (!rp->active)
164:        {
165:          printf("Record is already deleted.\n");
166:          break;
167:        }
168:        printf("Press 'y' to delete record,\n");
169:        printf("anything else to abort: ");
170:        gets(buf);
171:        if (tolower(*buf) == 'y')
172:          rp->active = FALSE;
173:        break;
174:
175:      case UNDELETE:
176:        if (rp->active)
177:        {
178:          printf("Record is not deleted.\n");
179:          break;
180:        }
181:        rp->active = TRUE;
182:        printf("Record restored.\n");
183:        break;
184:
185:      case SELECT:
186:        printf("Enter new record number: ");
187:        i = atoi(gets(buf));
188:        if (i < 0 || i > n_recs)
189:        {
190:          printf("Record # out of range.\n");
191:          break;
192:        }
193:        cur_rec = i;
194:        break;
195:
196:      case FIX:
197:        fix_db();   /* clean up database */
198:        break;
199:
200:      case QUIT:
201:        return;
202:    }
203:   }
204: }
205:
206: /*
207:  * Function:     fix_db
208:  * Purpose:      Purge deleted records, sort Database
209:  * Parameters:   None
210:  * Return Value: None
211:  */
212:
213: static int compar( struct record **p1,
214:                   struct record **p2);
215:
216: static void fix_db()   /* File Fix module */
217: {
218:   int i, new_n_recs;
219:
220:   for (i = 0, new_n_recs = 0; i < n_recs; i++)
221:   {
222:     RECS[new_n_recs] = RECS[i];
223:     if (RECS[i]->active)
224:       new_n_recs++;
225:     else
226:       free(RECS[i]);
227:   }
228:
229:   n_recs = new_n_recs;
230:   qsort(RECS, new_n_recs,
231:          sizeof(struct record *), compar);
232: }
233:
234: /*
235:  * Function:   compar
236:  * Purpose:     Comparison function for qsort(),
237:  *             sorting simply on last name
238:  * Parameters:   Two pointers to record pointers
239:  * Return Value:   As per strcmp()
240:  */
241:
242: static int compar(struct record **p1,
243:                  struct record **p2)
244: {
245:   return strcmp((*p1)->last, (*p2)->last);
246: }