/////////////////////////////////////////////////////////////// // // // strs.cpp - text string class // // v2.8 // // implementations // // // // Language: Visual C++ Ver 6, Borland C++ Ver 5.0 // // System: Gateway 386/25, MS-DOS 6.0 // // Application: CSE 687 // // Author: Jim Fawcett, Syracuse University // // (315)443-2654, jfawcett@cat.syr.edu // // // // copyright (c) 1996 // // all rights granted to users except right to publish // // // /////////////////////////////////////////////////////////////// #include // exit() #include // strlen() #include "strs.h" int _alloc::_bytes_alloc = 0; // track allocations str::lexType str::lexer = line; // set extraction mode //----< abort with message - private >------------------------- static void killJob(char *msg) { cout << msg << endl; exit(1); } //----< copy constructor >------------------------------------- _alloc::_alloc(const _alloc &a) { int i, Size = a.size(); size(Size,1,1); for(i=0; i------------------------------------------ _alloc::_alloc(int Size) { size(Size,1,1); } //----< destructor >------------------------------------------- _alloc::~_alloc() { delete [] _array; _array = 0; _bytes_alloc -= _size; _size = 0; #ifdef TEST_ALLOC cout << " _bytes_alloc = " << _bytes_alloc << endl; #endif } // //----< allocate memory >-------------------------------------- // // processing: // changes physical size if Size > current _size // or Force != 0 or New != 0 void _alloc::size(int Size, int Force, int New) { if(New || Force || Size > _size) { if(Size < 1) Size = 1; char *temp = new char[Size]; _bytes_alloc += Size; if(!temp) killJob("memory alloc failure in _alloc::size(...)"); if(New) { // allocate for the first time _array = temp; _array[0] = '\0'; _size = Size; } else { // reallocate existing memory int i; for(i=0; i<_size; i++) temp[i] = _array[i]; temp[Size-1] = '\0'; delete [] _array; _array = temp; _bytes_alloc -= _size; _size = Size; } #ifdef TEST_ALLOC cout << " _bytes_alloc = " << _bytes_alloc << endl; #endif } } //----< assignment >------------------------------------------- _alloc& _alloc::operator=(const _alloc &a) { if(this == &a) return *this; if(_size < a._size) size(a._size); strcpy(_array,a._array); return *this; } //----< indexing >--------------------------------------------- char& _alloc::operator[](int n) { static char safe; if(n < 0 || _size <= n) { cout << "index out of bounds in operator[]\n"; return safe; } return _array[n]; } // //----< constructor >------------------------------------------ str::str(int size) : allocator(size), _next(0) { } //----< promotion constructor for strs >----------------------- str::str(const char *s) : allocator(strlen(s)+1) { strcpy(allocator.array(),s); _next = strlen(s); } //----< copy constructor >------------------------------------- str::str(const str &s) : allocator(s.allocator) { strcpy(allocator.array(),s.allocator.array());_next = s._next; } //----< destructor >------------------------------------------- str::~str() { } //----< change logical str size >------------------------------ str& str::len(int n) { if(n == _next) return *this; if(n+1 > allocator.size()) size(2*n); else if(n<0) n=0; int i; for(i=_next; i------------------------------------------- str& str::operator=(const str &s) { if(this == &s) return *this; allocator = s.allocator; _next = s._next; return *this; } // //----< assignment >------------------------------------------- str& str::operator=(const char *s) { int len = strlen(s)+1; if(allocator.size() < len) allocator.size(len); strcpy(allocator.array(),s); _next = len-1; return *this; } //----< additive assignment >---------------------------------- str& str::operator+=(const str &s) { int save = _next; if(_next+s._next+1 > allocator.size()) size(2*(_next+s._next)); strcpy(allocator.array()+save,s.allocator.array()); _next += s._next; return *this; } //----< additive assignment >---------------------------------- str& str::operator+=(const char *s) { int len = strlen(s) + _next + 1; if(allocator.size() < len) allocator.size(2*len); strcpy(allocator.array()+_next, s); _next = len-1; return *this; } //----< append item to end of str >---------------------------- str& str::append(const char& c, int count) { if(_next+count >= allocator.size()) size(2*(_next+count)); int i; for(i=0; i--------------------------------- str& str::del(int index) { if(index < 0 || index >= _next) return *this; int i; for(i=index; i<_next; i++) allocator[i] = allocator[i+1]; if(_next > 0) --_next; return *this; } // //----< stream insertion >------------------------------------- ostream& operator<<(ostream &out, const str &s) { return (out << s.cStr()); } //----< is this character whitespace? >------------------------ int str::isWhite(char ch) { switch(ch) { case '\n' : return 1; case '\t' : return 1; case '\r' : return 1; case '\f' : return 1; case ' ' : return 1; } return 0; } //----< stream extraction >------------------------------------ istream& operator>>(istream &in, str &s) { char ch = ' '; long saveIOSformat = in.flags(); in.unsetf(ios::skipws); s.flush(); if(str::lexer == str::word) { do { // skip initial white space in >> ch; if(ch == EOF) { in.flags(saveIOSformat); return in; } } while(str::isWhite(ch)); do { if(ch == EOF) { in.flags(saveIOSformat); return in; } s.append(ch); in >> ch; } while(!str::isWhite(ch)); // collect non-white space in.putback(ch); } else { do { if(ch == EOF) { s.del(s.len()-1); in.flags(saveIOSformat); return in; } in >> ch; s.append(ch); } while(ch != '\n'); // collect lines s.del(s.len()-1); // strip '\n' like getline() } in.flags(saveIOSformat); return in; } // //----< show str state >--------------------------------------- void str::showState() const { str temp = *this; cout << " -------------------------------------------------\n"; cout << " number of chars: " << _next << endl; cout << " physical str size: " << allocator.size() << endl; if(_next > 0) { cout << " first char: " << temp.allocator[0] << endl; cout << " last char: " << temp.allocator[_next-1] << endl; } cout << " -------------------------------------------------\n"; if(_next < 0 || allocator.size() <= _next) cout << " too many chars for allocated memory in showState()\n"; } //----< check str invariants >--------------------------------- int str::check() const { return ( (strlen(allocator.array())==_next) && (_next-------------------------------------------- #ifdef TEST_STRS #include // ifstream() //----< test function accepting a str object >----------------- void testFunc(str s) { cout << " " << s << endl; } //----< tests start here >------------------------------------- void main() { cout << "\n" << " ======================\n" << " Testing text strings \n" << " ======================\n\n"; // cout << "\n" << " test #1 - void constr, appending, stream insertion:\n" << "-----------------------------------------------------\n"; str testStr1; testStr1.showState(); int i; for(i=0; i<20; i++) testStr1.append(char(int('a')+i)); cout << " testStr1 = " << testStr1 << endl; testStr1.showState(); cout << "\n" << " test #2 - copy constructor:\n" << "-----------------------------\n"; str testStr2 = testStr1; cout << " testStr2 = " << testStr2 << endl; cout << "\n" << " test #3 - C string promotion construction:\n" << "--------------------------------------------\n"; str testStr3 = "platypus"; cout << " testStr3 = " << testStr3 << endl; cout << "\n" << " test #4 - assignment from str:\n" << "--------------------------------\n"; testStr3 = testStr2; cout << " testStr3 = " << testStr3 << endl; testStr3.showState(); cout << endl; cout << "\n" << " test #5 - assignment from C string:\n" << "-------------------------------------\n"; const int numCreatures = 5; char* test[numCreatures] = { "ardvarrk", "viper", "platypus", "moose", "badger" }; testStr3 = test[1]; cout << " testStr3 = " << testStr3 << endl; testStr3.showState(); cout << endl; cout << "\n" << " test #6 - truncation:\n" << "-----------------------\n"; testStr3.len(3); cout << " testStr3 = " << testStr3 << endl; testStr3.showState(); cout << endl; // cout << "\f\n\n" << " test #7 - concatenation with operator+=():\n" << "--------------------------------------------\n"; testStr1.flush(); for(i=0; i> readStr; cout << " " << readStr << endl; } cout << "\n reading next eight lines from file strs.hpp\n"; str::setLex(str::line); readStr.flush(); for(i=0; i<8; i++) { in >> readStr; cout << " " << readStr << endl; } cout << "\f\n\n" << "test #13 - deleting chars from str\n" << "-----------------------------------\n"; int index = 3, imax = testStr1.len(); cout << testStr1 << endl; for(i=index; i