/********************************** * dlui.c * * * * The user interface for doubly * * linked lists. * * Any arguments on the command * * line are made into a list. * **********************************/ #include #include "dllist.h" #define QUIT 0 union keystroke { char c[2]; int i; }; /*Returns the data of the current element, or "[Null Element]" if it is null.*/ /* Purpose: Protection against null list elements Preconditions: none. Postconditions: l is not changed Problems: None. Parameters: l - the list element. May be null. Produces: The data value of the element, or "[Null Element]" if it is null. */ char * dataValue(dllist l) { if(l==NULL) { return "[Null Element]"; } else { return l->data; } } /**/ /* Purpose: Prints the previous, current and next elements along with the length of the list. Preconditions: None. Postconditions: The purpose has been accomplished. Problems: None. Parameters: l - the list to show. Produces: nothing. */ void printTop(dllist l) { char * next; char * prev; char * curr; int len = countElements(l); if(l==NULL) { l = newDLListNode("[Empty List]"); } curr = l->data; if(l->next == NULL) { next = "[End]"; } else { next = l->next->data; } if(l->prev == NULL) { prev = "[Beginning]"; } else { prev = l->prev->data; } printf("Previous: \"%s\" Current: \"%s\" Next: \"%s\"\n",prev,curr,next); printf("Length of list: %d\n",len); } /*Prints the menu for the program.*/ /* Purpose: To show the program menu. Preconditions: None. Postconditions: The menu has been printed. Problems: None. Parameters: None. Produces: None. */ void printMenu() { /*Create a "sense of event", as they say in the theater department*/ printf("\n\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\n"); printf("\\\\//\\\\//\\\\// \\\\//\\\\//\\\\//\n"); printf("\\\\//\\\\//\\\\// P R O G R A M M E N U \\\\//\\\\//\\\\//\n"); printf("\\\\//\\\\//\\\\// \\\\//\\\\//\\\\//\n"); printf("\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\\\\//\n\n"); printf(" F) All the Way Forward (end of list)\n"); printf(" f) Move Forward\n"); printf(" p) Print List\n"); printf(" b) Move Backward\n"); printf(" B) All the Way Backward (beginning of list)\n\n"); printf(" e) Edit Current Element\n"); printf(" i) Insert New Element\n"); printf(" d) Delete Current Element\n\n"); printf(" z) Zoom (Quick) Sort\n\n"); printf(" l) Load list from file\n"); printf(" s) Save list to file\n\n"); printf(" m) Show Menu (this)\n"); printf(" q) Quit\n\n"); } /*Changes the data in the current node. The user is prompted for a string.*/ /* Purpose: Change the data in the current node. Preconditions: list is not null Postconditions: list->data has changed to whatever the user entered. Problems: No way to cancel out of this. Parameters: list - the element to change. Cannot be null. Produces: Nothing. */ void editElement(dllist list) { printf("\nEdit the current element.\n Current value: \"%s\"\n",dataValue(list)); printf(" Enter new value > "); gets(list->data); } /*Inserts an element into the list. The user is prompted for the data string and, if the list is not null, whether it should go in front of or behind the current element.*/ /* Purpose: Insert an element into the list. Preconditions: None. Postconditions: If list is null, a new list is created. Else a new element is inserted before or after list, as the user chooses. Problems: None. Parameters: list - a pointer to a list element. May be null. Produces: Nothing */ void insertElement(dllist * list) { char buf[256]; union keystroke c; dllist new; printf("\nInsert an element.\n"); if(*list==NULL) { printf(" Enter new value > "); gets(buf); *list = newDLListNode(buf); } else { printf(" Insert: \n b)efore current element\n a)fter current element\n c)ancel\n"); printf(" > "); c.i=0; c.c[0] = getchar(); c.c[1] = getchar(); if((c.c[0]=='c') || ((c.c[0]!='a') && (c.c[0]!='b'))){ printf("Cancelled.\n"); return; } printf(" Enter new value > "); gets(buf); new = newDLListNode(buf); if(c.c[0]=='b') { insertBefore(*list,new); } else if(c.c[0]=='a') { insertAfter(*list,new); } else { } } /*else if null*/ } /*insertElement*/ /**/ /* Purpose: Removes the current element from the list, and deallocates the memory. Preconditions: list is not null Postconditions: the list is in one piece minus the current element Problems: No null protection Parameters: list - the element to remove. Cannot be null. Produces: Another element of the same list. If there are no other elements of the list, null is returned. */ dllist rmv(dllist list) { dllist ans; ans = takeOut(list); if(ans->next!=NULL) { ans = ans->next; } else { ans = ans->prev; } delete(list); return ans; } /*Loads a list. The user is prompted for a filename. The new list replaces the existing list.*/ /* Purpose: Loads a list from a file. Prompts the user for a file name Preconditions: None. Postconditions: The current list is replaced by the list created from the file. Problems: None. Parameters: list - the current list, may be null and will be replaced. Produces: The list that was created. */ dllist loadFile(dllist list) { FILE * fp = NULL; char buf[256]; dllist ans; while(fp==NULL) { printf("\nLoad a list from a file\n"); printf(" File name > "); gets(buf); if(strlen(buf)<1) { /*cancel*/ break; } fp = fopen(buf,"r"); if(fp==NULL) { printf("File not found.\n"); } } /*While fp==null*/ if(fp!=NULL) { ans = readFromFile(fp); close(fp); return ans; } else { printf("Canceled.\n"); return list; } } /*loadFile*/ /*Saves the current list to a file. The user is prompted for a filename. If a file of that name already exists, it is overwritten.*/ /* Purpose: Saves a list to a file. The user is prompted for the file name, any file with that name gets overwritten. Preconditions: None. Postconditions: The list is written to a file. Problems: None. Parameters: list - the list to write to a file. May be null. Produces: None. */ void saveFile(dllist list) { FILE * fp = NULL; char buf[256]; printf("\nSave a list to a file\n"); printf(" File name > "); gets(buf); if(strlen(buf)<1) { /*cancel*/ printf("Canceled.\n"); return; } fp = fopen(buf,"w"); writeToFile(findEnd(list,1),fp); close(fp); } /*saveFile*/ /*The main program. */ /* Purpose: The main program; the input loop. If any arguments are supplied they are used form the current list, otherwise it starts out empty. Preconditions: None. Postconditions: The program exits. Problems: None. Parameters: argc - the number of arguments argv - the arguments. These become the initial list. Produces: 0 */ int main(int argc, char * argv[]) { int i; union keystroke ks; dllist list; /*-----------------process any args in command line----------------*/ if(argc > 1) { list = newDLListNode(argv[1]); for(i = 2; i < argc ; i++) { insertAfter(list, newDLListNode(argv[i])); list = list->next; } list = findEnd(list,1); printList(list); } printMenu(list); while(ks.c[0] != 'q') { /*------------------------ get input ------------------------*/ printf("\n"); printTop(list); printf("\n\'m\' for Menu> "); ks.c[0] = getchar(); ks.c[1] = getchar(); /*------------------------process input------------------------*/ switch(ks.c[0]) { case 'm': printMenu(); break; case 'p': printList(list); break; case 'f': if((list!=NULL) && (list->next!=NULL)){list = list->next;} break; case 'b': if((list!=NULL ) && (list->prev!=NULL)){list = list->prev;} break; case 'e': if(list!=NULL){editElement(list);} else {insertElement(&list);} break; case 'i': insertElement(&list); break; case 'd': if(list!=NULL){list=rmv(list);} break; case 'l': list=loadFile(list); break; case 's': saveFile(list); break; case 'q': break; /*let while loop handle it*/ case 'F': if(list!=NULL){list=findEnd(list,0);} break; case 'B': if(list!=NULL){list=findEnd(list,1);} break; case 'z': if(list!=NULL){list=sort(findEnd(list,1));} break; default: printf("Unknown option. Please choose again.\n"); break; } /*------------------------print results------------------------*/ /* printf("Keystroke: 0x%x\n",ks.i); */ } printf("Done.\n"); return 0; }