Resources‎ > ‎Programming‎ > ‎C++‎ > ‎C++ Tutorial‎ > ‎Lesson 10‎ > ‎

Sample Solutions

Practice 1 - 3

#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
using namespace std;

int main() {
    int narray[] = {435, 225, 55, 983, 100, 391, 355, 6, 26};
    int size = sizeof narray / sizeof(int);

    vector<int> v1(size);
    v1.assign(narray, narray + size);

    cout << "v1:\n";
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    sort(v1.begin(), v1.end());
    cout << "v1 after sort():\n";
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    reverse(v1.begin(), v1.end());
    cout << "v1 after reverse():\n";
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));
    cout << endl;

    return 0;
}

Practice 4

#include <iostream>
#include <list>
#include <string>
#include <algorithm>
using namespace std;

class Cell {
  int x, y;
  string text;
public:
  Cell(int x, int y, const string &text) : x(x), y(y) {
	this->text = string(text);
  }
  int getX() {return x;}
  int getY() {return y;}
  string getText() {return text;}
  void setText(string text) {this->text = string(text);}
  Cell* clone() {return new Cell(x, y, text);}
};

class Sheet;
//this memento will store pointers for an old cell and a new cell
class CellMemento {
  Cell* pOldCell;
  Cell* pNewCell;
  // make Sheet class a frind of CellMemento so that only Sheet class can
  // access pOldCell/pNewCell
  friend class Sheet;
public:
  CellMemento(Cell* pOldCell, Cell* pNewCell) : pOldCell(pOldCell), pNewCell(pNewCell) {}
  ~CellMemento() {
	// pOldCell is a copy and only exists in a CellMemento...
	// so we need to delete it
	if (pOldCell != NULL) delete pOldCell;
  }
};

class Sheet {
  list<Cell*> cellList;	    // this is to store all cells to be displayed
  list<CellMemento*> stack; // this is to store all the history of the action
  int current;		    // the current action index
  
  list<Cell*>* getList() {return &cellList;}

  // add a new pair of old cell and new cell information in a history stack.
  void addStack(Cell* pOldCell, Cell* pNewCell) {
	while (isRedoable()) {
	  // if there are reduable tasks are in the stack, 
          // we need to delete them
	  list<CellMemento*>::iterator it = stack.begin();
	  advance(it, (stack.size()-1));
	  stack.erase(it);
	}
	// create a new memento object with a pair of old and new cell
	// and put that in the stack.
	stack.push_back(new CellMemento(pOldCell, pNewCell));
	current++;
  }

  // if the current action index is smaller than the total number of
  // actions in the stack, there are redoable tasks in the stack.
  bool isRedoable() {return current < (int)stack.size() - 1;}
  
public:
  Sheet() : current(-1) {}
  ~Sheet() {
	// first delete all memento objects (and copies of old cell in them)
	list<CellMemento*>::iterator it = stack.begin();
	while (it != stack.end()) {
	  delete *it;
	  it++;
	}
	// then delete all cells currently in the sheet.
	list<Cell *>::iterator itc = cellList.begin();
	while (itc != cellList.end()) {
	  delete *itc;
	  itc++;
	}
  }
  
  string getCellText(int x, int y) {
	Cell* pCell = getCell(x, y);
	return (pCell != NULL)? pCell->getText() : NULL;
  }
  
  Cell* getCell(int x, int y) {
	list<Cell*>::iterator it = getList()->begin();
	while (it != getList()->end()) {
	  Cell* pCell = *it;
	  if ((pCell->getX() == x) && (pCell->getY() == y)) return pCell;
	  it++;
	}
	return NULL;
  }

  // set a new "text" to the specified location (x,y)
  void setCellText(int x, int y, string text) {
	// first get a pointer of a cell at the specified location.
	Cell* pCell = getCell(x, y);
	Cell* pOldCell = pCell;
	Cell* pNewCell = pCell;
	
	if (pCell != NULL) {
	  // if pCell is not NULL, there already was a Cell at the specified location
	  // make a copy of the current cell and keep it as an old cell.
	  pOldCell = (Cell*)pCell->clone();
	  pCell->setText(text);
	} else {
	  // otherwise, create a new cell. and keep old cell as NULL.
	  pNewCell = new Cell(x, y, text);
	  getList()->push_back(pNewCell);
	}
	// add a pair of old and new cell to the history stack.
	addStack(pOldCell, pNewCell);
  }

  // it should be noted that "undo" operation itself does not remove a task
  // from a history stack.
  void undo() {
	if (current < 0) return; // nothing to undo...
	
	// first find the current location in the history stack.
	list<CellMemento*>::iterator it = stack.begin();
	for (int i = 0; it != stack.end(); it++, i++) 
	  if (current == i) break;
	
	CellMemento* memento = *it;
	// remove the current cell from the "cellList"
	cellList.remove(memento->pNewCell);
	// if oldcell is not NULL, put that old cell back in the "cellList"
	if (memento->pOldCell != NULL)
	  cellList.push_back(memento->pOldCell);
	if (current >= 0) current--;
  }

  
  void redo() {
	if (!isRedoable()) return;

	// first increment the index of the current task.
	current++;

	// then find the previous task corresponds to the updated current task index
	list<CellMemento*>::iterator it = stack.begin();
	for (int i = 0; it != stack.end(); it++, i++) 
	  if (current == i) break;
	
	CellMemento* pMemento = *it;

	// then re-apply the task.
	if (pMemento->pOldCell != NULL)
	  cellList.remove(pMemento->pOldCell);
	cellList.push_back(pMemento->pNewCell);
  }
  
  void display() {
	list<Cell*>::iterator it = getList()->begin();
	while (it != getList()->end()) {
	  cout << "x: " << (*it)->getX() << " ";
	  cout << "y: " << (*it)->getY() << " ";
	  cout << "Text: " << (*it)->getText() << endl;
	  it++;
	}
  }
};

int main(){
  Sheet sheet;
  sheet.setCellText(1,1,"t1");
  sheet.setCellText(3,4,"t2");
  sheet.setCellText(3,4,"t3");
  sheet.setCellText(5,5,"t4");
  sheet.display();
  sheet.undo();
  sheet.undo();
  sheet.display();
  sheet.redo();
  sheet.display();
}

Comments