-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
530 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
// DLList.c - Implementation of doubly-linked list ADT | ||
// Written by John Shepherd, March 2013 | ||
// Modified by John Shepherd, August 2014, August 2015 | ||
|
||
#include <stdlib.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <assert.h> | ||
#include "DLList.h" | ||
|
||
// data structures representing DLList | ||
|
||
typedef struct DLListNode { | ||
char *value; // value of this list item (string) | ||
struct DLListNode *prev; | ||
// pointer previous node in list | ||
struct DLListNode *next; | ||
// pointer to next node in list | ||
} DLListNode; | ||
|
||
typedef struct DLListRep { | ||
int nitems; // count of items in list | ||
DLListNode *first; // first node in list | ||
DLListNode *curr; // current node in list | ||
DLListNode *last; // last node in list | ||
} DLListRep; | ||
|
||
// create a new DLListNode (private function) | ||
static DLListNode *newDLListNode(char *it) | ||
{ | ||
DLListNode *new; | ||
new = malloc(sizeof(DLListNode)); | ||
assert(new != NULL); | ||
new->value = strdup(it); | ||
new->prev = new->next = NULL; | ||
return new; | ||
} | ||
|
||
// create a new empty DLList | ||
DLList newDLList() | ||
{ | ||
struct DLListRep *L; | ||
|
||
L = malloc(sizeof (struct DLListRep)); | ||
assert (L != NULL); | ||
L->nitems = 0; | ||
L->first = NULL; | ||
L->last = NULL; | ||
L->curr = NULL; | ||
return L; | ||
} | ||
|
||
// free up all space associated with list | ||
void freeDLList(DLList L) | ||
{ | ||
assert(L != NULL); | ||
DLListNode *curr, *prev; | ||
curr = L->first; | ||
while (curr != NULL) { | ||
prev = curr; | ||
curr = curr->next; | ||
free(prev->value); | ||
free(prev); | ||
} | ||
free(L); | ||
} | ||
|
||
// trim off \n from strings (private function) | ||
// this is needed for getDLList() because of fgets() | ||
// alternatively, we could use the evil gets() function | ||
static char *trim(char *s) | ||
{ | ||
int end = strlen(s)-1; | ||
if (s[end] == '\n') s[end] = '\0'; | ||
return s; | ||
} | ||
|
||
// create an DLList by reading items from a file | ||
// assume that the file is open for reading | ||
// assume one item per line, line < 999 chars | ||
DLList getDLList(FILE *in) | ||
{ | ||
DLList L; | ||
DLListNode *new; | ||
char line[1000]; | ||
|
||
L = newDLList(); | ||
while (fgets(line,1000,in) != NULL) { | ||
char *value = strdup(trim(line)); | ||
new = newDLListNode(value); | ||
if (L->last == NULL) { | ||
L->first = L->last = new; | ||
} | ||
else { | ||
L->last->next = new; | ||
new->prev = L->last; | ||
L->last = new; | ||
} | ||
L->nitems++; | ||
} | ||
L->curr = L->first; | ||
return L; | ||
} | ||
|
||
// display list to file, one item per line | ||
// assumes that the file is open for writing | ||
void putDLList(FILE *out, DLList L) | ||
{ | ||
assert(out != NULL); assert(L != NULL); | ||
DLListNode *curr; | ||
for (curr = L->first; curr != NULL; curr = curr->next) | ||
fprintf(out,"%s\n",curr->value); | ||
} | ||
|
||
// check sanity of a DLList (for testing) | ||
int validDLList(DLList L) | ||
{ | ||
if (L == NULL) { | ||
fprintf(stderr,"DLList is null\n"); | ||
return 0; | ||
} | ||
if (L->first == NULL) { | ||
// list is empty; curr and last should be null | ||
if (L->last != NULL || L->curr != NULL) { | ||
fprintf(stderr,"Non-null pointers in empty list\n"); | ||
return 0; | ||
} | ||
} | ||
else { | ||
// list is not empty; curr and last should be non-null | ||
if (L->last == NULL || L->curr == NULL) { | ||
fprintf(stderr,"Null pointers in non-empty list\n"); | ||
return 0; | ||
} | ||
} | ||
int count; | ||
DLListNode *curr; | ||
// check scanning forward through list | ||
count = 0; | ||
for (curr = L->first; curr != NULL; curr = curr->next) { | ||
if (curr->prev != NULL && curr->prev->next != curr) { | ||
fprintf(stderr, "Invalid forward link into node (%s)\n",curr->value); | ||
return 0; | ||
} | ||
if (curr->next != NULL && curr->next->prev != curr) { | ||
fprintf(stderr, "Invalid backward link into node (%s)\n",curr->value); | ||
return 0; | ||
} | ||
count++; | ||
} | ||
if (count != L->nitems) { | ||
fprintf(stderr, "Forward count mismatch; counted=%d, nitems=%d\n", | ||
count, L->nitems); | ||
return 0; | ||
} | ||
// check scanning backward through list | ||
count = 0; | ||
for (curr = L->last; curr != NULL; curr = curr->prev) { | ||
count++; | ||
} | ||
if (count != L->nitems) { | ||
fprintf(stderr, "Backward count mismatch; counted=%d, nitems=%d\n", | ||
count, L->nitems); | ||
return 0; | ||
} | ||
// nothing went wrong => must be ok | ||
return 1; | ||
} | ||
|
||
// return item at current position | ||
char *DLListCurrent(DLList L) | ||
{ | ||
assert(L != NULL); assert(L->curr != NULL); | ||
return L->curr->value; | ||
} | ||
|
||
// move current position (+ve forward, -ve backward) | ||
// return 1 if reach end of list during move | ||
// if current is currently null, return 1 | ||
int DLListMove(DLList L, int n) | ||
{ | ||
assert(L != NULL); | ||
if (L->curr == NULL) | ||
return 1; | ||
else if (n > 0) { | ||
while (n > 0 && L->curr->next != NULL) { | ||
L->curr = L->curr->next; | ||
n--; | ||
} | ||
} | ||
else if (n < 0) { | ||
while (n < 0 && L->curr->prev != NULL) { | ||
L->curr = L->curr->prev; | ||
n++; | ||
} | ||
} | ||
return (L->curr == L->first || L->curr == L->last) ? 1 : 0; | ||
} | ||
|
||
// move to specified position in list | ||
// i'th node, assuming first node has i==1 | ||
int DLListMoveTo(DLList L, int i) | ||
{ | ||
assert(L != NULL); assert(i > 0); | ||
L->curr = L->first; | ||
return DLListMove(L, i-1); | ||
} | ||
|
||
// insert an item before current item | ||
// new item becomes current item | ||
void DLListBefore(DLList L, char *it) | ||
{ | ||
assert(L != NULL); | ||
// COMPLETE THIS FUNCTION | ||
} | ||
|
||
// insert an item after current item | ||
// new item becomes current item | ||
void DLListAfter(DLList L, char *it) | ||
{ | ||
assert(L != NULL); | ||
// COMPLETE THIS FUNCTION | ||
} | ||
|
||
// delete current item | ||
// new item becomes item following current | ||
// if current was last, current becomes new last | ||
// if current was only item, current becomes null | ||
void DLListDelete(DLList L) | ||
{ | ||
assert (L != NULL); | ||
// COMPLETE THIS FUNCTION | ||
} | ||
|
||
// return number of elements in a list | ||
int DLListLength(DLList L) | ||
{ | ||
return (L->nitems); | ||
} | ||
|
||
// is the list empty? | ||
int DLListIsEmpty(DLList L) | ||
{ | ||
return (L->nitems == 0); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// DLList.h - Interface to doubly-linked list ADT | ||
// Written by John Shepherd, March 2013 | ||
// Last modified, August 2014 | ||
|
||
#ifndef DLLIST_H | ||
#define DLLIST_H | ||
|
||
#include <stdio.h> | ||
#include "DLList.h" | ||
|
||
// External view of DLList | ||
// Implementation given in DLList.c | ||
// Implements a DLList of strings (i.e. items are strings) | ||
|
||
typedef struct DLListRep *DLList; | ||
|
||
// create a new empty DLList | ||
DLList newDLList(); | ||
|
||
// free up all space associated with list | ||
void freeDLList(DLList); | ||
|
||
// create an DLList by reading items from a file | ||
// assume that the file is open for reading | ||
DLList getDLList(FILE *); | ||
|
||
// display list to file, one item per line | ||
// assumes that the file is open for writing | ||
void putDLList(FILE *, DLList); | ||
|
||
// check sanity of a DLList (for testing) | ||
int validDLList(DLList); | ||
|
||
// return item at current position | ||
char *DLListCurrent(DLList); | ||
|
||
// move current position (+ve forward, -ve backward) | ||
// return 1 if reach end of list during move | ||
int DLListMove(DLList, int); | ||
|
||
// move to specified position in list | ||
// i'th node, assuming first node has i==1 | ||
int DLListMoveTo(DLList, int); | ||
|
||
// insert an item before current item | ||
// new item becomes current item | ||
void DLListBefore(DLList, char *); | ||
|
||
// insert an item after current item | ||
// new item becomes current item | ||
void DLListAfter(DLList, char *); | ||
|
||
// delete current item | ||
// new item becomes item following current | ||
// if current was last, current becomes new last | ||
// if current was only item, current becomes null | ||
void DLListDelete(DLList); | ||
|
||
// return number of elements in a list | ||
int DLListLength(DLList); | ||
|
||
// is the list empty? | ||
int DLListIsEmpty(DLList); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
# COMP1927 16s2 Week 04 Lab | ||
|
||
CC=gcc | ||
CFLAGS=-Wall -Werror | ||
BINS=testL myed | ||
|
||
all: $(BINS) | ||
|
||
testL : testList.o DLList.o | ||
$(CC) -o testL testList.o DLList.o | ||
|
||
myed : myed.o DLList.o | ||
$(CC) -o myed myed.o DLList.o | ||
|
||
DLList.o : DLList.c DLList.h | ||
|
||
myed.o : myed.c DLList.h | ||
|
||
testList.o : testList.c DLList.h | ||
|
||
clean: | ||
rm -f $(BINS) *.o core |
Binary file not shown.
Oops, something went wrong.