CS 70

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() and end() need to do.
    • What the ++, *, and != operators of the iterator need to do.
  • Capture evidence of your planning as a .jpg file (either a photo of your nodes, whiteboard session, or a screenshot of your digital drawing), adding it to the Planning folder in your repository as Phase_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.

  • Duck speaking

    What about in the iterator functions? Should we call check_invariants() there?

  • LHS Cow speaking

    Actually, you can't. The iterator functions only have access to the Node* current_ pointer, not to the IntList object itself, so they can't call check_invariants().

  • Sheep speaking

    Oh, wow, so they're, like, oblivious to the list itself?

  • LHS Cow speaking

    That's right! Although the iterator functions are tightly coupled to the IntList class, they don't actually know anything about it.

  • Alien speaking

    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.

  • Sheep speaking

    Remind me… why did we want an iterator again?

  • Pig speaking

    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.

  • Dog speaking

    Awesome! Red xs! Woo-hoo!

  • Horse speaking

    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?

  • LHS Cow speaking

    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 IntList class doesn't currently support.

  • Pig speaking

    MORE functionality in our IntList class!!!

  • Goat speaking

    Meh. I thought it was fine as is. I was totally ready to bail.

  • Cat speaking

    So are we going to have to add that functionality now?

  • LHS Cow speaking

    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

  • Sheep speaking

    Harsh… I got a segfault! What was the deal with those again…?

  • RHS Cow speaking

    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.

To Complete This Part of the Assignment…

You'll know you're done with this part of the assignment when you've done all of the following:

(When logged in, completion status appears here.)