// Source: "Software Design ...", John A Robinson, Newnes, 2004, Chapter 17. #include #include using namespace std; class tcell { // Structure of each cell in the table: basic unit of the collection bool cellused; int rowindex; int colindex; string content; public: tcell() { cellused = 0; rowindex = colindex = -1; }; ~tcell() { }; void setindices(const int r, const int c) { rowindex = r; colindex = c; }; void setval(const string& cont) { cellused = 1; content = cont; }; void delval() { cellused = 0; content = ""; }; const string getval() { return content; }; const int row() { return rowindex; }; const int col() { return colindex; }; const bool used() { return cellused; }; }; class stable { // The 2D table of tcells plus row and column labels int max_rows; // Set on instantiation int max_cols; // Set on instantiation int lowest_available_row; // Row numbers equal to or higher than // this are not yet used. int lowest_available_col; // No rows have entries is this or any // higher numbered column tcell *rlabel; // Row labels are outsize the table itself // in a 1D array tcell *clabel; // Column labels are outsize the table itself // in a 1D array tcell **cell; // The array of pointers to arrays (rows) of cells public: stable(const int r, const int c) { max_rows = r; max_cols = c; lowest_available_row = 0; lowest_available_col = 0; rlabel = new tcell[max_rows]; // Row labels clabel = new tcell[max_cols]; // Column labels cell = new tcell *[max_rows]; // All the cells for (int i = 0; i < max_rows; i++) cell[i] = new tcell[max_cols]; }; ~stable() { for (int i = 0; i < max_rows; i++) delete [] cell[i]; delete [] cell; delete [] clabel; delete [] rlabel; }; int set(const int row, const int col, const string& val) { if ((row < 0)||(col < 0)||(row >= max_rows)||(col >= max_cols)) return -1; if (row >= lowest_available_row) lowest_available_row = row+1; if (col >= lowest_available_col) lowest_available_col = col+1; cell[row][col].setval(val); return 0; }; // May later need versions of set that have int in one of row // and col and string in the other. But for now, just do both same. int set(const string& row, const string& col, const string& val) { int r; // Integer value of row for (r = 0; r < lowest_available_row; r++) { if (rlabel[r].getval() == row) break; } if (r == lowest_available_row){ // Not already in array. (Note inefficiency: usually will // call set(...) when labels not yet used, but every time do // futile linear search through all all labels) if (lowest_available_row == max_rows) return -1; // Otherwise, using r = lowest_available_row and // move lowest_available_row up rlabel[lowest_available_row].setval(row); lowest_available_row++; } for (int c = 0; c < lowest_available_col; c++) { if (clabel[c].getval() == col) { cell[r][c].setval(val); return 0; } } // Not already in array. (Note inefficiency: as for rows) if (lowest_available_col == max_cols) return -1; clabel[lowest_available_col].setval(col); cell[r][lowest_available_col].setval(val); lowest_available_col++; return 0; }; int get(const int row, const int col, string& val) { if ((row < 0)||(col < 0)||(row >= max_rows)||(col >= max_cols)){ val = ""; return -1; } if (!cell[row][col].used()) { // Works for row, col greater than lowest_available too val = ""; return 0; } val = cell[row][col].getval(); return 1; }; int get(const string& row, const string& col, string& val) { int r; // Integer value of row for (r = 0; r < lowest_available_row; r++) { if (rlabel[r].getval() == row) break; } if (r == lowest_available_row) { val = ""; return 0; } for (int c = 0; c < lowest_available_col; c++) { if (clabel[c].getval() == col) { val = cell[r][c].getval(); return 1; } } return 0; }; void print() { cout << "\t"; // Top left corner: No label int i; for (i = 0; i < lowest_available_col; i++) cout << clabel[i].getval() << "\t"; cout << endl; for (i = 0; i < lowest_available_row; i++) { cout << rlabel[i].getval() << "\t"; for (int j = 0; j < lowest_available_col; j++) cout << cell[i][j].getval() << "\t"; cout << endl; } }; }; // Test program int main() { stable mytab(5,3); mytab.set("w","y","wy"); mytab.set("w","z","wz"); mytab.set("x","y","xy"); mytab.set("x","z","xz"); mytab.set(2,0,"Num"); mytab.print(); string retval; mytab.get(1,1,retval); cout << "Value at 1,1 is " << retval << endl; mytab.get("w","w",retval); cout << "Value at w,w is " << retval << endl; mytab.get("x","y",retval); cout << "Value at x,y is " << retval << endl; }