#include // Standard I/O definitions. #include // Definition of 'int atol(...)'. #include // string class and operations. #include // list class and operations. using namespace std; class Pair { int key; // Key for the record pair. int value; // Associated integer value. public: Pair( int k, int v ) { key = k; value = v; } Pair() {}; int getKey() { return key; } // Return the subscript. int& getValue() { return value; } // Return the value associated with key. }; class FlexVec { private: list vlist; // List to contain information. int numEntries; // Number of non-zero entries in the list. int maxIndex; // Maximal subscript so far for non-zero entry. int minIndex; // Minimal subscript so far for non-zero entry. list::iterator lastChangedLoc; // Location of last changed node in the list. void CheckStatus(); // Verify if need to update status information. public: FlexVec(); ~FlexVec(); void Status( int &numEntries, int &minIndex, int &maxIndex ); int& operator[ ]( int subscript ); // Overloaded subscripting operator. }; // FlexVec::FlexVec is used to initialize the vector. FlexVec::FlexVec() { numEntries = 0; lastChangedLoc = NULL; maxIndex = 0; minIndex = 0; } // FlexVec::~FlexVec is used to free up any information left in the list. FlexVec::~FlexVec() { if ( ! vlist.empty() ) vlist.clear(); } // FlexVeck::CheckStatus sees if lastChanged != NULL. If that is the case, the status information // is updated as appropriate if the value stored is non-zero. void FlexVec::CheckStatus() { if ( lastChangedLoc != (list::iterator) NULL) { // Has a node been referenced recently? if ( lastChangedLoc->getValue() != 0 ) { // If value is not 0, update status information. // Check for special case of first item in list. if ( numEntries == 0 ) { minIndex = lastChangedLoc->getKey(); maxIndex = minIndex; } numEntries += 1; if ( lastChangedLoc->getKey() < minIndex) { minIndex = lastChangedLoc->getKey(); } if ( lastChangedLoc->getKey() > maxIndex) { maxIndex = lastChangedLoc->getKey(); } } else { if ( lastChangedLoc == vlist.end() ) { vlist.pop_back(); } else { vlist.erase( lastChangedLoc ); } } lastChangedLoc = NULL; } } // FlexVec::operator[ ] returns the integer value associated with the given subscript. If no // such value exists in the list, a new pair is inserted whose integer value is 0. int& FlexVec::operator[ ](int subscript) { Pair newpair(subscript, 0); // Item which may be inserted into list. bool retval = false; // Found a match? list::iterator i; // Pointer into the list. CheckStatus(); // See if status information has to be updated. // If list was empty, i == 0 and loop terminates immediately. for( i = vlist.begin(); i != vlist.end(); ++i ) { if ( i->getKey() == subscript ) { // Check if have found right element. retval = true; break; } } // If FALSE, didn't find element to match, so insert empty one. if ( ! retval ) { vlist.push_back( newpair ); i = --(vlist.end()); lastChangedLoc = i; // Make sure we know where the new element is. } return i->getValue(); } // FlexVec::operator[ ] // FlexVec::Status returns the status of the vector so far. void FlexVec::Status( int &ne, int &minI, int &maxI ) { CheckStatus(); // See if status information has to be updated. ne = numEntries; minI = minIndex; maxI = maxIndex; } // FlexVec::Status void ObtainArgument( string &buffer, string &arg ) { arg = ""; int commandstart = buffer.find_first_not_of( " \t", 0 ); if ( commandstart == -1 ) commandstart = buffer.length(); int commandend = buffer.find( " ", 1 ); if ( commandend == -1 ) commandend = buffer.find( "\t", 1 ); if ( commandend == -1 ) commandend = buffer.length(); if ( commandend > commandstart ) { arg = buffer.substr( commandstart, commandend-commandstart ); buffer = buffer.substr( commandend, buffer.length()-commandend ); } else { buffer = ""; } // if } // ObtainArgument bool IsInt(string value) { bool retvalue = true; for ( int i = 0; i < value.length() && retvalue; i += 1 ) { if ( i == 0 && (value[i] == '-' || value[i] == '+') ) { } else if ( ! isdigit(value[i]) ) { retvalue = false; } // if } // for return retvalue; } // IsInt // Main driver for the program. Reads in the commands and calls the appropriate routines. int main() { int subscript; // Subscript for the vector. int value; // Value to be assigned. int numSplit; // # of values from string split. char *tempValue; // Buffer for converting string to int. FlexVec *myList[3]; // Simulated vectors of integers. int vecIndex; // Which vector is to be modified. int numEntries; // Number of non-zero entries in the list. int maxIndex; // Maximal subscript so far for non-zero entry. int minIndex; // Minimal subscript so far for non-zero entry. int i, j; // Loop indices for ( i = 0; i < 3; i += 1 ) { myList[i] = new FlexVec(); } // for for ( ;; ) { string command = ""; // Command read in by the driver. string args[4] = { "", "", "", "" }; // Arguments for the command, if applicable. string buffer = ""; // Throw-away buffer for rest of line. getline(cin, buffer); if (cin.fail()) break; string line = buffer; // Make a copy of buffer before pull it apart. ObtainArgument( buffer, command ); if ( command.length() > 0 && command[0] != '*' ) { if ( buffer.length() > 0 ) ObtainArgument(buffer, args[0]); if ( buffer.length() > 0 ) ObtainArgument(buffer, args[1]); if ( buffer.length() > 0 ) ObtainArgument(buffer, args[2]); if ( buffer.length() > 0 ) ObtainArgument(buffer, args[3]); } // if // Ignore comments or empty lines. if ( command[0] == '*' || command.length() == 0 ) { } else if ( command.length() != 1 && command != "?" && command != "=" && command != "s" ) { cerr << "ERROR: unknown command '" << command << "' entered." << endl; } else if ( args[0].length() == 0 || buffer.length() > 0 || args[3].length() != 0 ) { cerr << "ERROR: invalid number of parameters for '" << line << "'." << endl; } else { vecIndex = (int) atol((const char *) args[0].c_str()); // Verify that the vector specified was an integer and that it was in the valid range of values. // If that was okay, verify that the subscript is an integer as well. if ( !IsInt(args[0]) || vecIndex < 0 || vecIndex > 2 ) { cerr << "ERROR: invalid vector specification '" << args[0] << "' entered." << endl; } else { subscript = (int) atol((const char *) args[1].c_str()); switch ( command[0] ) { case '?': if ( args[2].length() != 0 ) { cerr << "ERROR: invalid number of parameters for '" << line << "'." << endl; } else if ( !IsInt(args[1]) ) { cerr << "ERROR: invalid subscript specification '" << args[1] << "' entered." << endl; } else { cout << "'?' returns " << (*myList[vecIndex])[subscript] << endl; } break; case '=': if ( buffer.length() > 0 || args[3].length() != 0 ) { cerr << "ERROR: invalid number of parameters for'" << line << "'." << endl; } else if ( !IsInt(args[1]) ) { cerr << "ERROR: invalid subscript specification '" << args[1] << "' entered." << endl; } else if ( !IsInt(args[2]) ) { cerr << "ERROR: invalid integer value for assignment '" << args[2] << "'." << endl; } else { value = (int) atol((const char *) args[2].c_str()); (*myList[vecIndex])[subscript] = value; } break; case 's': if ( args[1].length() != 0 ) { cerr << "ERROR: invalid number of parameters for '" << line << "'." << endl; } else { (*myList[vecIndex]).Status(numEntries, minIndex, maxIndex); cout << "Vector" << vecIndex << " has " << numEntries << " non-zero entries."; if ( numEntries > 0 ) { cout << " Vector subscripts are in the range [" << minIndex << ", " << maxIndex << "]." << endl; } else { cout << endl; } } break; case '*': break; default: cerr << "ERROR: unknown command '" << command << "' entered." << endl; break; } } } } for ( i = 0; i < 3; i += 1 ) { delete myList[i]; } } // main // Local Variables: // compile-command: "g++ -g -o flexvec flexvec.C" // End: