12
String
- #if !defined( _MYSTRING_H )
- #define _MYSTRING_H
- #include <iostream>
- using namespace std;
- class String {
- friend bool operator==( const String &, const String & );
- friend bool operator!=( const String &, const String & );
- friend bool operator<( const String &, const String & );
- friend bool operator<=( const String &, const String & );
- friend bool operator>( const String &, const String & );
- friend bool operator>=( const String &, const String & );
- friend String operator+( const String &, const String & );
- friend ostream &operator<<( ostream &, const String & );
- friend istream &operator>>( istream &, String & );
- private:
- unsigned len;
- char *buf;
- public:
- ~String( );
- String( unsigned =0 );
- String( char, unsigned );
- String( const char * );
- String( const String &r );
- #if 1
- String &operator=( const String & );
- #endif
- String &operator+=( const String & );
- char &operator[]( int ) const;
- operator const char *() const;
- unsigned length( ) const { return len; };
- istream &getline( istream &, char );
- void append( String & );
- void put( String &, int );
- void insert( String &, int );
- void remove( int, int =1 );
- void erase( );
- #if defined( STANDALONE )
- void print( const char * =0 ) const;
- #endif
- };
- #endif
- #include "String.h"
- #include <iostream>
- #include <string.h>
- #include <memory.h>
- #include <assert.h>
- using namespace std;
- #ifdef DEBUG
- int debug = 1; // 0 - off, 1 - on
- #endif
- #ifdef DEBUG
- #define ONDEBUG( expr ) do { if ( debug ) { expr; } } while ( 0 )
- #else
- #define ONDEBUG( expr )
- #endif
- String::~String( )
- {
- ONDEBUG( cout << "String::~String()\n"; );
- delete [] buf;
- }
- String::String( unsigned n ) : len( n )
- {
- ONDEBUG( cout << "String::String( unsigned n=" << n << " )\n"; );
- buf = new char[ len+1 ];
- for( int i = 0; i < len; i++ )
- buf[ i ] = ' '; // fill with spaces
- buf[ len ] = '\0';
- }
- String::String( char c, unsigned n) : len( n )
- {
- ONDEBUG( cout << "String::String( char c=" << c << ", unsigned n=" << n << " )\n"; );
- buf = new char[ len+1 ];
- for( int i = 0; i < len; i++ )
- buf[ i ] = c; // fill with char
- buf[ len ] = '\0';
- }
- String::String( const char *s ) : len( strlen( s ) ) // legal!
- {
- ONDEBUG( cout << "String::String( const char *s=\"" << s << "\" )\n"; );
- buf = new char[ len+1 ];
- for( int i = 0; i < len; i++ )
- buf[ i ] = s[ i ]; // copy string
- buf[ len ] = '\0';
- }
- String::String( const String &s ) : len( s.len )
- {
- ONDEBUG( cout << "String::String( const String &s=" << &s << " )\n"; );
- buf = new char[ len+1 ];
- for( int i = 0; i < s.len; i++ )
- buf[ i ] = s.buf[ i ]; // copy string
- buf[ len ] = '\0';
- }
- String::operator const char *() const
- {
- ONDEBUG( cout << "String::operator const char *\n"; );
- return buf;
- }
- #if 1
- String& String::operator=( const String &s )
- {
- ONDEBUG( cout << "String::operator=( " << &s << " )\n"; );
- if ( &s == this )
- return *this;
- len = s.len;
- delete [] buf;
- buf = new char[ len+1 ];
- strcpy( buf, s.buf );
- return *this;
- }
- #endif
- String& String::operator+=( const String &s )
- {
- ONDEBUG( cout << "String::operator+=( " << &s << " )\n"; );
- int nlen = len+s.len;
- char *nbuf = new char[ nlen+1 ];
- strcpy( nbuf, buf );
- strcpy( nbuf+len, s.buf );
- delete [] buf;
- len = nlen;
- buf = nbuf;
- return *this;
- }
- char &String::operator[]( int i ) const
- {
- ONDEBUG( cout << "String::operator[ " << i << " ]\n"; );
- assert( i >= 0 && i < len );
- return buf[ i ];
- }
- ostream &operator<<( ostream &ostr, const String &s )
- {
- return ostr << s.buf;
- }
- istream &operator>>( istream &istr, String &s )
- {
- char nbuf[ 1024 ]; // reasonably large enough
- istr >> nbuf;
- s = nbuf; // explain!
- return istr;
- }
- String operator+( const String &s1, const String &s2 )
- {
- #if 1
- String s( s1.len + s2.len );
- strcpy( s.buf, s1.buf );
- strcat( s.buf, s2.buf );
- return s;
- #else
- char s[ s1.len + s2.len + 1 ];
- strcpy( s, s1.buf );
- strcpy( s+s1.len, s2.buf );
- return String( s );
- #endif
- }
- bool operator==( const String &s1, const String &s2 )
- {
- #if 0
- return (strcmp( s1.buf, s2.buf ) == 0);
- #else
- return (strcmp( s1, s2 ) == 0); // using operator char *
- #endif
- }
- bool operator!=( const String &s1, const String &s2 )
- {
- #if 0
- return (strcmp( s1.buf, s2.buf ) != 0);
- #else
- return (strcmp( s1, s2 ) != 0); // using operator char *
- #endif
- }
- bool operator>=( const String &s1, const String &s2 )
- {
- #if 0
- return (strcmp( s1.buf, s2.buf ) >= 0);
- #else
- return (strcmp( s1, s2 ) >= 0); // using operator char *
- #endif
- }
- bool operator<=( const String &s1, const String &s2 )
- {
- #if 0
- return (strcmp( s1.buf, s2.buf ) <= 0);
- #else
- return (strcmp( s1, s2 ) <= 0); // using operator char *
- #endif
- }
- bool operator>( const String &s1, const String &s2 )
- {
- #if 0
- return (strcmp( s1.buf, s2.buf ) > 0);
- #else
- return (strcmp( s1, s2 ) > 0); // using operator char *
- #endif
- }
- bool operator<( const String &s1, const String &s2 )
- {
- #if 0
- return (strcmp( s1.buf, s2.buf ) < 0);
- #else
- return (strcmp( s1, s2 ) < 0); // using operator char *
- #endif
- }
- istream &String::getline( istream &istr, char c='\n' )
- {
- char nbuf[ 1024 ]; // reasonably large enough
- istr.getline( nbuf, 1024, c );
- if ( istr )
- {
- len = strlen( nbuf );
- delete [] buf;
- buf = new char[ len+1 ];
- strcpy( buf, nbuf );
- }
- else
- {
- len = 0;
- delete [] buf;
- buf = new char[ len+1 ];
- buf[ len ] = '\0';
- }
- return istr;
- }
- void String::append( String &s )
- {
- int nlen = len+s.len;
- char *nbuf = new char[ nlen+1 ];
- memcpy( nbuf, buf, len );
- memcpy( nbuf+len, s.buf, s.len );
- nbuf[ nlen ] = '\0';
- len = nlen;
- buf = nbuf;
- }
- void String::put( String &s, int w )
- { // put s at position w - append if w<0 or w>=len
- if ( w < 0 || w >= len )
- append( s );
- else if ( (w+s.len) > len )
- {
- int nlen = w + s.len;
- char *nbuf = new char[ nlen+1 ];
- memcpy( nbuf, buf, w );
- memcpy( nbuf+w, s.buf, s.len );
- nbuf[ nlen ] = '\0';
- len = nlen;
- buf = nbuf;
- }
- else
- memcpy( buf+w, s.buf, s.len );
- }
- void String::insert( String &s, int w )
- { // insert s at position w - append if w<0 or w>=len
- if ( w < 0 || w >= len )
- append( s );
- else
- {
- int nlen = len + s.len;
- char *nbuf = new char[ nlen+1 ];
- memcpy( nbuf, buf, w );
- memcpy( nbuf+w, s.buf, s.len );
- memcpy( nbuf+w+s.len, buf+w, len-w );
- nbuf[ nlen ] = '\0';
- len = nlen;
- buf = nbuf;
- }
- }
- void String::erase( )
- { // empty string
- len = 0;
- delete [] buf;
- buf = new char[ 1 ];
- buf[ 0 ] = '\0';
- }
- void String::remove( int w, int n )
- { // remove n characters at position w - remove all if n<0, from end if w<0 or w>=len
- if ( n < 0 || n >= len )
- erase();
- else
- {
- if ( w < 0 || w >= len )
- w = len - n;
- int nlen = len - n;
- char *nbuf = new char[ nlen + 1 ];
- memcpy( nbuf, buf, w );
- memcpy( nbuf+w, buf+w+n, nlen-w );
- nbuf[ nlen ] = '\0';
- len = nlen;
- buf = nbuf;
- }
- }
- #if defined( STANDALONE )
- void String::print( const char *leading ) const
- {
- if ( leading )
- cout << leading;
- cout << "this=" << this << " len=" << len << "\tbuf(" << &buf << ")=[" << buf << "]" << endl;
- }
- int main() {
- String s1;
- s1.print();
- String s2( 4 );
- s2.print();
- String s3( '@', 10 );
- s3.print();
- {
- String s4( "ABC$DEF" );
- s4.print();
- }
- const String s5( "DON'T CHANGE!" );
- s5.print();
- cout << endl;
- String john = "John";
- john.print();
- cout << john << endl;
- String paul;
- paul = "Paul"; // calls a constructor!
- paul.print();
- cout << paul << endl;
- // try this without defining operator=
- john = paul;
- john.print();
- paul[0] = 'S';
- // paul.operator[](0) = 'S'; // if char &operator[]( unsigned ) const;
- paul.print();
- john.print();
- cout << ">>>>>\n";
- {
- String grand( "grand" );
- String child( "child" );
- cout << "grand+child=\t[" << grand + child << "]\n";
- cout << "grand+\"child\"=\t[" << grand + "child" << "]\n";
- }
- cout << "<<<<<\n";
- cout << ">>>>>\n";
- {
- String grand( "grand" );
- String child( "child" );
- grand += child;
- cout << "grand+=child-> len=" << grand.length() << "\tbuf=[" << grand << "]\n";
- }
- cout << "<<<<<\n";
- String a, b;
- cout << "Enter 2 strings or ^D/^Z:\n";
- #if 0
- while ( cin >> a >> b ) {
- #else
- while ( a.getline( cin ) && b.getline( cin ) ) {
- #endif
- a.print( "a-> " ), b.print( "b-> " );
- if ( a == b )
- cout << "\t[" << a << "]==[" << b << "]\n";
- if ( a != b )
- cout << "\t[" << a << "]!=[" << b << "]\n";
- if ( a >= b )
- cout << "\t[" << a << "]>=[" << b << "]\n";
- if ( a <= b )
- cout << "\t[" << a << "]<=[" << b << "]\n";
- if ( a > b )
- cout << "\t[" << a << "]>[" << b << "]\n";
- if ( a < b )
- cout << "\t[" << a << "]<[" << b << "]\n";
- cout << "Try again 2 strings or ^D/^Z:\n";
- }
- {
- char *hello = "Hello";
- String s0 = hello;
- String s1 = s0;
- String s2 = " my dear";
- String s3 = " my darling";
- String s4 = " lovely";
- s1.print( "s1-> " );
- s1.append( s2 );
- s1.print( "s1-> " );
- s1 = s0;
- s1.print( "s1-> " );
- s1.put( s2, -1 );
- s1.print( "s1-> " );
- s1.put( s3, 5 );
- s1.print( "s1-> " );
- s1.put( s2, 5 );
- s1.print( "s1-> " );
- s1 = s0;
- s1.print( "s1-> " );
- s1.insert( s4, 100 );
- s1.print( "s1-> " );
- s1 = s0;
- s1.print( "s1-> " );
- s1.append( s2 );
- s1.print( "s1-> " );
- s1.insert( s4, 8 );
- s1.print( "s1-> " );
- s1.erase();
- s1.print( "s1-> " );
- s1 = s0;
- s1.append( s2 );
- s1.print( "s1-> " );
- s1.remove( 5, 3 );
- s1.print( "s1-> " );
- s1.remove( -1, 5 );
- s1.print( "s1-> " );
- }
- return 0; // exit() doesn't call destructors
- }
- #endif
Comments