_PROPOSING A C++ STRING CLASS_ by Steve Teale [LISTING ONE] class String { public: // String class constants enum string_enum { all = INT_MAX }; // Constructors / destructor String(); // make an empty String String(const String&); // make a String by copying another String(const char *, int count = 0); // make a String from a regular C style string String(char); // make a String from a single char ~String(); // Clean up after a String goes out of scope // Assignments String &operator=(const String&); // Assign from another String String &operator=(const char *); // Assign from a C style string String &operator=(char); // Assign from a single char String &operator+=(const String&); // Concatenate a String to an existing String String &operator+=(const char *); // Concatenate a C style string to a String String &operator+=(char); // Concatenate a char // Other modifiers String &insert(int pos, const String&); // Insert into an existing string String &insert(int pos, const char *); String &insert(int pos, char); String &remove(int pos, int count); // Remove from an existing string String &truncate(int); // Truncate a String // Conversions operator char*() const; // Translate a String to a pointer to its first character operator char() const; // Translate a String to its initial character // Mutators (make an existing String into a variant) String upper() const; // Make a new String by conversion to uppercase String lower() const; String operator()(int start, int len); // Make a new String starting from start, of len characters // Access individual characters char &operator[](int); // Access individual characters as if the String // were an array char operator()(int); // Get the character value of the i'th character. // Searches int match(const String&) const; Š // Return position of first non-matching character int match(const char *) const; int index(const String&, int pos = 0) const; int index(const char *, int = 0) const; // Find the position of a substring or character int index(char, int = 0) const; // Statistics int operator!() const; // Test for an empty string int length() const; // Get the length of the String // Some of the properties of a String are provided by functions which // are friends of the String class friend int strlen(const String&); // Parallel the ANSI C string functions // etc // Concatenations to make a new String friend String operator+(const String&, const String&); friend String operator+(const String&, const char *); friend String operator+(const char *, const String&); // Boolean tests friend int operator==(const String&, const String&); friend int operator==(const String&, const char *); friend int operator==(const char *, const String&); friend int operator!=(const String&, const String&); friend int operator!=(const String&, const char *); friend int operator!=(const char *, const String&); friend int operator>(const String&, const String&); friend int operator>(const String&, const char *); friend int operator>(const char *, const String&); friend int operator<(const String&, const String&); friend int operator<(const String&, const char *); friend int operator<(const char *, const String&); friend int operator>=(const String&, const String&); friend int operator>=(const String&, const char *); friend int operator>=(const char *, const String&); friend int operator<=(const String&, const String&); friend int operator<=(const String&, const char *); friend int operator<=(const char *, const String&); // Input/ output operations friend istream &operator>>(istream&, String&); friend ostream &operator<<(ostream&, const String&); }; [LISTING TWO] #ifndef __STRING_HPP #define __STRING_HPP #include Šclass istream; // forward declarations to avoid including all of iostream.hpp class ostream; class srep { // actual string representation friend class String; private: srep(int, const char * = 0); void *operator new(size_t cs, size_t ss = 0); int refs; int length; char body[1]; }; class String { public: // as above private: char *body() const { return rp? rp->body: 0; } srep *rp; static char dummy; }; inline int strlen(const String &s) { return s.length(); } // and other friend functions which can conveniently be defined inline #endif Figurå 1 (a) String &operator=(char); String &operator+=(char); String &insert(int, const String&); String &insert(int, const char *); String &insert(int, char); String &remove(int, int); int operator!(); (b) String a; Šif (!a) ...; // if a is empty string if (a) ...; // if a is not empty - uses operator char *() (c) friend int operator==(const String&, const String&); friend int operator==(const String&, const char *); friend int operator==(const char *, const String&); Figure 2 (a) String a; ... if (a == "whatever") ...; will cause a sequence something like: String temp = "whatever"; // constructor from const char * if (operator==(a, temp)) ...; // temp destructor call (b) // two members int operator==(const String&); int operator==(const char *); // and a friend friend int operator==(const char *, const String&); Figure 3 (a) String t; // an empty string String a = "good girl"; // initialized from a regular C style string String b = a; // the copy constructor String c = '.'; ŠThis is the idiomatic usage. It would have just the same effect to write: String a("good girl"); String b(a); String c('.'); (b) String d("good girl", 4); // same effect as String d = "good"; (c) String v = "abcd"; v += 1; // result "bcde" ? String w = "provided" w -= "vide" // result "prod" ? w -= 'r'; // result "pod" ? String x = "1234567890" x <<= 1; // result "2345678901" Figure 4 (a) operator char(); // conversion to a char operator char *(); // conversion to a char * (b) void show(char c) { cout << c << ' ' << int(c) << endl; } char array[4] = { '\0', '\0', '\0', '\0' }; String nulls(array,4); String empty; show(nulls); show(empty); ŠFigure 5 (a) String String::upper() const; String String::lower() const; String String::operator()(int start, int length) const; String operator+(const String &a, const String &b); String operator+(const String &a, const char *b); String operator+(const char *a, const String &b); (b) String a = "Cat"; a(0) = 'R'; // a gets "Rat" // a.operator()(0) = 'R'; Figure 6 (a) String a = "The quick brown fox jumped over the lazy dogs back"; String b = "The queen"; String c = "lazy"; a.match(b); // returns 7 a.match("The quick"); // returns -1 a.index(b); // returns -1 a.index(c); // returns 36 a.index("The", 1); // returns -1 a.index("The"); // returns 0 a.index("the"); // returns 32 a.index('b'); // returns 10 a.index('b',11); // returns 46 (b) // C style char *s1 = "Joe", *s2 = "Fred"; if (s1 > s2) ...; // legal, but not usually what was intended! if (!strcmp(s1,s2)) ...; // proper test for equality // C++ style String s1 = "Joe", s2 = "Fred"; if (s1 > s2) ...; // evaluates to true if (s1 == s2) ...; // proper test for equality Figure 6 (a) String a = "The quick brown fox jumped over the lazy dogs back"; String b = "The queen"; String c = "lazy"; a.match(b); // returns 7 a.match("The quick"); // returns -1 a.index(b); // returns -1 a.index(c); // returns 36 a.index("The", 1); // returns -1 a.index("The"); // returns 0 a.index("the"); // returns 32 a.index('b'); // returns 10 a.index('b',11); // returns 46 (b) // C style char *s1 = "Joe", *s2 = "Fred"; if (s1 > s2) ...; // legal, but not usually what was intended! if (!strcmp(s1,s2)) ...; // proper test for equality // C++ style String s1 = "Joe", s2 = "Fred"; if (s1 > s2) ...; // evaluates to true if (s1 == s2) ...; // proper test for equality