Implementing IntList, Phase 2: The Iteratorizing
In principle, you now know how the iterator is supposed to work, so now it's time to implement it. Once again, we'll break this work into two parts: planning and implementation.
Your Task, Part 1: Planning the Implementation
You will need to do the following:
- Think about how how all the pieces work, and how they fit together, including
- What
begin()andend()need to do. - What the
++,*, and!=operators of the iterator need to do.
- What
- Capture evidence of your planning as a
.jpgfile (either a photo of your nodes, whiteboard session, or a screenshot of your digital drawing), adding it to thePlanningfolder in your repository asPhase_2.jpg.
Your Task, Part 2: Implementing and Testing
Implementing the Missing Functions
In intlist.cpp, add the following code:
IntList::const_iterator IntList::begin() const {
// TODO: use the iterator constructor to create an iterator refering
// to the first node
}
IntList::const_iterator IntList::end() const {
// TODO: use the iterator constructor to create an iterator with the
// correct value to represent "just gone off the end"
}
IntList::Iter::Iter(Node* current) /* TODO: member initializer list */ {
// TODO: any other code you need or perhaps nothing else needed
}
IntList::Iter& IntList::Iter::operator++() {
// TODO: advance the iterator to the next node
// return ourselves to allow chained increments
return *this;
}
const int& IntList::Iter::operator*() const {
// TODO: return the value in the current node
}
bool IntList::Iter::operator==(const Iter& rhs) const {
// TODO: compare this iterator with another for equality
}
bool IntList::Iter::operator!=(const Iter& rhs) const {
return !(*this == rhs); // use the == operator we just wrote
}
None of these functions change the structure of the list, so you don't need to call check_invariants() in any of them, but you can do so in begin() and end() if you want to.
What about in the iterator functions? Should we call
check_invariants()there?
Actually, you can't. The iterator functions only have access to the
Node* current_pointer, not to theIntListobject itself, so they can't callcheck_invariants().
Oh, wow, so they're, like, oblivious to the list itself?
That's right! Although the iterator functions are tightly coupled to the
IntListclass, they don't actually know anything about it.
Reminds me of humans. They don't even know the real reason Earth is where it is.
Testing the Iterator
Now you can try your newly written iterator with your newly written test cases in intlist-test.cpp.
cs70-make -H intlist-test
./intlist-test
If all the tests pass, great! But if not, running with valgrind will give you a backtrace that will help you find the problem:
valgrind --leak-check=full ./intlist-test
All the usual debugging advice applies here. If you get stuck, you can post on Piazza, or ask in grutoring hours or during lab.
Remind me… why did we want an iterator again?
To add MORE awesomeness to the Snake game!
Your Task, Part 3: Revising the Snake Game to Use the Iterator
Now that we have a working IntList class, let's switch the Snake game to use it instead of IntVector. Open config.hpp and replace the code in the marked section with this new code:
#define COORDLIST_USES_INTLIST 1
#define COORDLIST_PROVIDES_ITERATOR 1
Then run
cs70-make -H snake
./snake
Hopefully the game will still work (and show the desired effect when the game ends). If it doesn't work, it may indicate that you have a bug in your IntList class not captured by your test cases. You may be able to get some insight by running the game under valgrind, but do not spend significant time trying to understand the internal logic of the Snake game. If you can't find anything obvious wrong with your IntList class, ask for help on Piazza, during grutoring hours, or during lab, but you can move on to the next part of the assignment without getting this part working.
Awesome! Red
xs! Woo-hoo!
Hay! I hate to bring this up, but isn't it supposed to be the case that for mutagenic food, the five added segments are added somewhere near the end of the tail? In our game they're always added right at the very end of the tail. Is that right?
Yes, that's correct. To add segments “somewhere near the end of the tail”, we would need to be able to insert elements in the middle of the list, which our
IntListclass doesn't currently support.
MORE functionality in our
IntListclass!!!
Meh. I thought it was fine as is. I was totally ready to bail.
So are we going to have to add that functionality now?
That's right. But at least there's nothing new on the encoding front—we just need to add one new function to the interface and then plan and implement it.
Helpful Hints
Harsh… I got a segfault! What was the deal with those again…?
Okay, here's the advice we gave pack in Part 4.
If you use valgrind to run your test cases, it will give you a backtrace that shows you where the segfault happened, which often gives you a clue about what went wrong.
If you're still stuck, we now have a whole page of debugging tips that you can use to help you track down the problem.
(When logged in, completion status appears here.)