#include #include #include #include struct cell { // individual cell in spreadsheet int col_index; // column index float data; // contents of cell cell() {} cell(int c, float d) : col_index(c), data(d) {} }; class spreadsheet { typedef list< cell > row_type; // rows are lists of non-empty cells vector< row_type > rows; // all the rows, initially empty lists public: float empty_cell; // dummy float type to be returned by get_data // when the cell is empty spreadsheet(int size) : rows(size), // number of rows in spreadsheet empty_cell(0.0) {} float& put_data(int i, int j, float x); // places value x in cell at i-th row and j-th column // returns a reference to the data in the cell float& get_data(int i, int j); // returns a reference to the data in the cell in i-th row // and j-th column, or a reference to the member empty_cell friend ostream& operator<<(ostream&, spreadsheet&); }; class col_index_is_equal { // function object that compares the column index of a cell // to the test_index in this object which is set by the constructor // used in STL find generic algorithm int test_index; // is initialized by constructor public: col_index_is_equal(int j) : test_index(j) {} bool operator() (const cell& c) {return c.col_index == test_index;} }; float& spreadsheet::put_data(int i, int j, float x) {// place value x in cell at i-th row and j-th column if(i > rows.size()) {cerr << "row index too large in put_data"; return empty_cell;} row_type& ith_row = rows[i]; // reference to requested row // check if there is a cell in column j in this row row_type::iterator p = find_if(ith_row.begin(), ith_row.end(), col_index_is_equal(j)); if(p == ith_row.end()) {// no previous cell in column j in this row, add a new cell ith_row.push_back( cell(j, x) ); p = ith_row.end(); p--; // p refers to the new cell } else // previous cell in column j in this row // replace the data field in that cell (*p).data = x; return (*p).data; } float& spreadsheet::get_data(int i, int j) {// retrieve contents of cell in i-th row and j-th column if(i > rows.size()) {cerr << "row index too large in get_data"; return empty_cell;} row_type& ith_row = rows[i]; // reference to requested row // locate cell in j-th column in this row row_type::iterator p = find_if(ith_row.begin(), ith_row.end(), col_index_is_equal(j)); if(p != ith_row.end()) // a cell has been put there, so return its value return (*p).data; else // the cell is empty, i.e., no previous put_data for the // pair i and j was performed return empty_cell; } ostream& operator<<(ostream& os, spreadsheet& sh) {int m, n; int max_row_index=-1, max_col_index=-1; list::iterator p; for(m=0; m < sh.rows.size(); m++) for(p = sh.rows[m].begin(); p!=sh.rows[m].end(); p++) {max_row_index = m; if((*p).col_index > max_col_index) max_col_index = (*p).col_index; } for(m=0; m<=max_row_index; m++) {for(n=0; n<=max_col_index; n++) {float& x = sh.get_data(m, n); if(&x == &sh.empty_cell) cout << " empty "; else cout << x << " "; } cout << endl; } cout << endl;} int main(void) {spreadsheet sh(6); // make a spreadsheet with 6 rows sh.put_data(1,2,3.14); // place 3.14 in row 1, col 2 sh.put_data(1,0,-1.0); // place 3.14 in row 1, col 2 sh.put_data(3,1,2.78); // place 2.78 in row 3, col 1 // test if cell in row 0 and column 3 is empty // by comparing the address of the returned float with empty_cell if(&sh.get_data(0, 3) == &sh.empty_cell) cout << "empty" << endl; cout << sh; // print the entire spreadsheet }