COMP2521: Assignment 1
Generic Iterator ADT
(Version-04: 07:50am Friday 20/Apr)
The specifications may change!
so please check the following change log frequently.
Change log:
- [07:50am Friday 20/Apr]: The deadline extended to 23 April (UNSW IT systems may be down over the weekend); last day to submit is 25 April.
- [4:50pm Thursday 19/Apr]:
- Due date extended by a day.
- Added instructions on how to Submit
- [5:30pm Tuesday 03/Apr]:
- Revised
'testIteratorG.c' offers six basic tests to test your generic ADT. However, make sure
that you do test all the required functions properly by adding more
tests in this or another file.
- The expected output for each test is in the file
'expected_output.txt'.
- The header file
'iteratorG.h' is now updated to reflect the following changes in the
signature/header of "find".
- The skeleton file for 'iteratorG.c' is also available,
'iteratorG-skeleton.c'.
You need to manually rename it to 'iteratorG.c', to
make sure that you do not overwrite it by mistake!
- The above files are available here.
- [6pm 27/March]: For the function "find", example function "gradeFL" is modified, as discussed in the lecture.
The signature/header of "find" is IteratorG find(IteratorG it, int (*fp) (void *vp) )
Objectives
- to give you experience in implementing generic ADTs in C
- to give you (more) experience with doubly-linked lists
- to give you further practice with C and data structures
Admin
- Marks: 10 marks (9 marks towards total course mark).
- Due date/time: 23:55pm on Monday of Week-08 (23 April).
- Late Penalty: 2 marks per day off the ceiling (e.g. if you are 2 days late, your maximum possible marks is 6/10). The last day to submit late is Wednesday of Week-08, after this date, you will receive zero mark for this assignment.
- Group?: This assignment is completed individually
Aim
In this assignment, your task is to implement a generic list Iterator ADT, in the file iteratorG.c.
You will have to write wrapper code to test your implementations, and make sure to test a variety of conditions.
Please note that, you need to submit only the C code implementing the required list Iterator ADT, in the file iteratorG.c.
Iterator
An iterator offers an easy way to traverse through a collection, add new elements, delete and modify existing elements.
Iterators are widely supported by langauges like C++ and Java. However, C does not offer iterators. In this assignment your task is to implement
a list iterator that allow the programmer to traverse the list in either direction and modify the list during iteration.
You will implement a list iterator defined below. The following interface specification is drawn from Java (7) ListIterator API and adapted for C implementations.
A List Iterator has no current element; its cursor position always lies between the element that would be
returned by a call to 'previous' and the element that would be returned by a call to 'next'.
An iterator for a list of length n has n+1 possible cursor positions, as illustrated by the carets (^) below:
Element(0) Element(1) Element(2) ... Element(n-1)
cursor positions: ^ ^ ^ ^ ^
Generic List iterator
You must use doubly linked list to implement the following iterator for this assignment, otherwise you will receive zero mark for this assignment!
You need to implement a generic list iterator that can store elements of any type, and offer the following interface to the programmer. You need to implement the following methods in
file iteratorG.c, and submit this file as described in the section named "Submission".
Note that you need to submit ONLY one file
iteratorG.c for this assignment. Please do not modify the header file iteratorG.h.
You can write your test code in testIteratorG.c. However, you will not submit your test code.
We will test your implementation using our test sets, so make sure you do NOT modify function
headers (signatures) in the header file iteratorG.h.
Interface
typedef struct IteratorGRep *IteratorG;
typedef int (*ElmCompareFp)(void const *e1, void const *e2);
typedef void *(*ElmNewFp)(void const *e1);
typedef void (*ElmFreeFp)(void *e1);
- IteratorG newIterator(ElmCompareFp cmp, ElmNewFp copy, ElmFreeFp free)
- Creates a new generic list iterator with given functions to handle elements.
- int add(IteratorG it, void *vp)
-
Inserts the specified element pointed by 'vp' into the list iterator 'it'.
The element is inserted immediately before the element that would be returned by next(), if any, and after the element that would be returned by 'previous', if any. If the list contains no elements, the new element becomes the sole element on the list. The new element is inserted after the implicit cursor, a subsequent call to 'previous' would be unaffected, and a subsequent call to 'next' would return the new element.
Returns 1 if successful, 0 otherwise.
For example:
Let's say 'it' is [ ^ ]
add(it, 12) will result in the following, and return 1
[ ^ 12 ]
add(it, 7) will result in the following, and return 1
[ ^ 7 12 ]
add(it, 15) will result in the following, and return 1
[ ^ 15 7 12 ]
- int hasNext(IteratorG it)
- Returns 1 if the given list iterator has more elements when traversing the list in the forward direction, returns 0 otherwise.
- int hasPrevious(IteratorG it)
- Returns 1 if the given list iterator has more elements when traversing the list in the reverse direction, returns 0 otherwise.
- void *next(IteratorG it)
- Returns the pointer to the next element in the given list iterator and advances the cursor position.
This method may be called repeatedly to iterate through the list, or intermixed with calls to 'previous'
to go back and forth. (Note that alternating calls to next and previous will return the same element repeatedly.)
The method returns NULL if it has no next value.
For example:
Let's say 'it' is [ 20 74 ^ 32 55 5 14 89 ]
// Alternative: 1 (compact)
int val = *((int *) next(it));
// Alternative: 2 (easy to understand!)
int *p1;
p1 = (int *) next(it);
int val = *p1;
val is now 32, and 'it' is [ 20 74 32 ^ 55 5 14 89 ]
- void *previous(IteratorG it)
- Returns the pointer to the previous element in the given list iterator and moves the cursor position backwards. This method may be
called repeatedly to iterate through the list backwards, or intermixed with calls to 'next' to go back and forth.
(Note that alternating calls to next and previous will return the same element repeatedly.)
The method returns NULL if it has no previous value.
For example:
Let's say 'it' is [ 20 74 ^ 32 55 5 14 89 ]
int val = *((int *) previous(it));
val is now 74, and 'it' is [ 20 ^ 74 32 55 5 14 89 ]
- int del(IteratorG it)
- Removes from the list iterator the previous element, if any.
A subsequent call to 'next' would be unaffected.
Returns 1 if successful, 0 otherwise (for example, no previous element to remove).
For example:
Let's say 'it' is [ 20 12 ^ 15 5 14 ]
del(it) will result in the following, and return 1
[ 20 ^ 15 5 14 ]
del(it) will result in the following, and return 1
[ ^ 15 5 14 ]
del(it) will result in the following, and return 0
[ ^ 15 5 14 ]
- int set(IteratorG it, void *vp)
- Replaces the 'previous' element with the specified element (*vp), if any.
Returns 1 if successful, 0 otherwise (for example, no previous element).
For example:
Let's say 'it' is [ 20 74 ^ 32 55 5 14 89 ]
int newVal = 50;
set(it, &newVal) will result in the following, and return 1
'it' is changed to [ 20 50 ^ 32 55 5 14 89 ]
- IteratorG advance(IteratorG it, int n)
- Advances 'it' by 'n' elements. Note that 'n' can be a positive or a negative
integer. The function returns a new iterator with 'n' elements, in the same
order as they were visited, see examples below.
If advancement by 'n' elements is not possible, the function returns 'null' and
the cursor position is not changed.
The new iterator uses the same functions as used by 'it' to handle elements.
For example:
Let's say 'it' is [ 20 ^ 12 15 5 14 10 5 9 3 ]
advance(it, 3) will result in the following, and return [ ^ 12 15 5 ]
[ 20 12 15 5 ^ 14 10 5 9 3 ]
advance(it, -2) will result in the following, and return [ ^ 5 15 ]
[ 20 12 ^ 15 5 14 10 5 9 3 ]
advance(it, 9) will result in the following (unchanged), and return 'null'
[ 20 12 ^ 15 5 14 10 5 9 3 ]
- void reverse(IteratorG it)
- Reverses the sequence in 'it'. The 'previous' element becomes the 'next' element (if any) and the 'next' element becomes the 'previous' element (if any). The rest of the elements are reorganised as shown below.
For example:
Let's say 'it' is [ 20 12 15 5 ^ 14 10 5 9 3 ]
reverse(it) will result in the following,
[ 3 9 5 10 14 ^ 5 15 12 20 ]
Let's say 'it' is [ ^ 7 1 8 9 4 ]
reverse(it) will result in the following,
[ 4 9 8 1 7 ^ ]
Let's say 'it' is [ 7 1 8 9 4 ^ ]
reverse(it) will result in the following,
[ ^ 4 9 8 1 7 ]
- IteratorG find(IteratorG it, int (*fp) (void *vp) )
-
The function finds elements, after the current cursor position in 'it',
for which the function 'fp' returns 1.
All such elements are inserted into a new iterator,
and this new iterator is returned.
The elements are considered in sequence, from the current cursor position to the end of the iterator.
The new iterator uses the
same functions as used by 'it' to handle elements.
The original iterator 'it' is unchnaged, and it's cursor position is unchanged.
For example:
int gradeFL(void *vp) {
int marks = *((int *) vp );
if(marks < 50)
return 1;
else
return 0;
}
....
....
Let's say 'it' is [ 20 74 ^ 32 55 5 14 89 ]
newIt = find(it, gradeFL);
'newIt' will be [ ^ 32 5 14 ]
'it' is unchanged [ 20 74 ^ 32 55 5 14 89 ]
- int distanceFromStart(IteratorG it)
- Calculates the number of elements before the cursor, and returns the value.
For example
Let's say 'it' is [ 15 5 ^ 14 10 5 9 3 ]
distanceFromStart(it) will return 2.
Let's say 'it' is [ ^ 7 1 8 9 4 ]
distanceFromStart(it) will return 0.
Let's say 'it' is [ 7 1 8 9 4 ^ ]
distanceFromStart(it) will return 5.
- int distanceToEnd(IteratorG it)
- Calculates the number of elements after the cursor, and returns the value.
For example
Let's say 'it' is [ 20 12 15 5 ^ 14 10 ]
distanceToEnd(it) will return 2.
Let's say 'it' is [ ^ 7 1 8 9 4 ]
distanceToEnd(it) will return 5.
Let's say 'it' is [ 7 1 8 9 4 ^ ]
distanceToEnd(it) will return 0.
- void reset(IteratorG it)
- Resets 'it' to the start of the list.
- void freeIt(IteratorG it)
- Removes all the nodes in 'it' and frees associated memory.
Testing
Please read the lecture notes on
"Software Development Process", in particular topics like "Testing" and "Debugging".
You need to test your functions thoroughly before submission. You can use the provided sample test program to get started.
However, please note that the tests provided in this file cover only basic scenarios (cases), you need to think about other possible cases, modify the file(s) accordingly and test your functions.
Assessment Criteria
Your program will be tested thoroughly and objectively. This assignment will be marked out of 10 where 8 marks are for correctness (based on auto marking) and 2 marks are for your solution's complexity, style and comments.
Submission
You need to submit only one file iteratorG.c.
To Submit this assignment, go to the Submission page and click the tab named "Make Submission".
Plagiarism
This is an individual assignment. Each student will have to develop their own solution
without help from other people. In particular, it is not permitted to exchange code or pseudocode.
You are not allowed to use code developed by persons other than yourself. If you have questions
about the assignment, ask your tutor Before submitting any work you should read and understand
the following very useful guide by the Learning Centre How Not To Plagiarise.
All work submitted for assessment must be entirely your own work.
We regard unacknowledged copying of material, in whole or part, as an extremely serious offence.
For further information, see the Course Information.
-- end --