a、標準庫包含一個string類,但創建自己的string類可以弄明設計和編寫C++類的許多問題。使用基本的char數據類型編寫一個string類,看看它如何隱藏使用C樣式字符串時的復雜性。
為MyString類創建一個頭文件,把它放在自己的命名空間中。給這個類提供兩個私有數據成員:整型長度和char*,char*指向對象所管理的字符串。為什么要把長度作為該類的一個數據成員存儲?
b、創建類的一個實現文件(.cpp),并提供構造函數,從下面的數據類型中構建MyString對象:
·一個字符串字面量(例如 const char*類型),以便編寫MyString s1("hello")。
·一個重復多次的字符。默認的重復次數應是1。使用這個構造函數的例子如MyString s2('c', 5)。
·一個整數值,這樣MyString s3(10)就存儲了字符串"10"。
這些構造函數是顯式的還是隱式的?構造函數在需要時應提供錯誤處理。
c、構造函數為存儲字符串而分配內存;提供一個析構函數,在刪除對象時正確地釋放內存。
d、編寫該類的副本構造函數,以便從其他字符串中創建和初始化MyString對象。
e、給類添加一些成員函數:
·返回字符串的長度
·輸出字符串
·索引從0開始,找出某個字符或子字符串在字符串中的位置,如果沒有找到,就返回-1
現在可以編寫一個測試程序,以各種方式創建并處理mystring對象。保證所有的成員都工作正常。

MyString.h
// MyString.h
// Definition of the MyString class representing strings
#ifndef MYSTRING_H
#define MYSTRING_H
namespace Louis {
class MyString {
public:
MyString(); // Default constructor
MyString(const char* pString); // Construct from a C-style string
MyString(char ch, int n); // Construct from repeated character
MyString(int number); // Construct string representation of integer
MyString(const MyString& rString); // Copy constructor
~MyString(); // Destructor
int length() const{ return strLength; } // Return length excluding terminating null
int find(char ch) const; // Find the occurrence of a character
int find(const char* pString) const; // Find the occurrence of C-style string
int find(const MyString& rString) const;// Find the occurrence of a MyString as a sub-string
void show() const; // Output the string
private:
size_t strLength;
char* pStr;
};
} // End of namespace Louis
#endif

MyString.cpp
// MyString.cpp
// Definitions for member of the MyString class
#include "MyString.h"
#include <cstdlib>
#include <iostream>
using std::cout;
using std::endl;
namespace Louis {
// Default constructor
MyString::MyString() {
strLength = 0; // Length excludes terminating null - this is empty string
pStr = new char[1]; // Allocate space for string in the free store
*pStr = '\0'; // Store terminating null
}
// Construct from a C-style string
MyString::MyString(const char* pString) {
strLength = strlen(pString); // strlen() returns length excluding terinating null
pStr = new char[strLength+1]; // Space must allow for null, hence strLength+1
strcpy(pStr, pString); // Copy argument string to data member
}
// Construct from repeated character
MyString::MyString(char ch, int n) {
strLength = n;
pStr = new char[strLength+1];
for (unsigned int i=0; i<strLength; *(pStr+i++)=ch) // 3rd expression stores ch then increments i
; // No loop statement
*(pStr+strLength) = '\0'; // Store terminating null
}
// Construct string representation of integer
MyString::MyString(int number) {
char buffer[20]; // Buffer to store string representation
int temp = number;
if (number<0) // If it is negative.
number = -number; // reverse the sign
// Convert digits to characters in reverse order
int len = 0;
do {
buffer[len++] = static_cast<char>('0' + number%10);
number /= 10;
}while(number>0);
if (temp<0) // If it was negative
buffer[len++] = '-'; // Append a minus sign
buffer[len] = '\0'; // Append terminal \0
strLength = len; // Store length of string
pStr = new char[strLength+1]; // Allocate space
strcpy(pStr, buffer); // Copy string to data member
// String is reversed so reverse it in place
char ch = 0;
for (int i=0, j=len-1; i<j; i++, j--) {
ch = pStr[i];
pStr[i] = pStr[j];
pStr[j] = ch;
}
}
// Copy constructor
// Needs to allocate space for a copy of the string, then copy it
MyString::MyString(const MyString& rString) {
strLength = rString.strLength; // Store the length
pStr = new char[strLength+1]; // Allocate the required space
strcpy(pStr, rString.pStr); // Copy the string
}
// Destructor
// releases free store memory allocated to store string
MyString::~MyString() {
//std::cout << "Destructor called." << std::endl;
delete[] pStr; // Must use array form of delete here
}
// Find the position of a character
// Compares succesive characters in the satring with the argument
int MyString::find(char ch) const {
for (unsigned int i=0; i<strLength; i++)
if (ch == *(pStr+i)) // If we find the character,
return i; // return its position,
return -1; // otherwise return -1
}
// Find the position of a string
// Searches for the first character of the substring
// and looks for the remaining characters if it is found
int MyString::find(const char* pString) const {
bool found = false; // Sub-string found indicator
// Search for the sub-string. We only need to look for
// the first character up to the position where there is
// enough room left for the sub-string to appear.
for (unsigned int i=0; i<strLength-strlen(pString)+1; i++)
if (*(pStr+i) == *pString) { // If we find the first charcter
found = true;
for (unsigned int j=1; j<strlen(pString); j++) // look for the rest the sub-string
if (*(pStr+i+j) != *(pString+j)) { // If any character doesn't match,
found = false; // we didn't find it
break; // so go to next iteration in outer loop
}
if (found) // If we found it,
return i; // Return the position,
}
return -1; // otherwise return -1
}
// Find the occurrence of a MyString as a sub-string
int MyString::find(const MyString& rString) const {
return find(rString.pStr); // Just use the previous function to do it
}
// Display the string
void MyString::show() const {
if (strLength)
cout << endl << pStr;
else
cout << endl << "String is empty.";
}
} // End of namespace mySapce

main.cpp
// main.cpp
// Creating and Testing the MyString class
#include "MyString.h"
#include <iostream>
using std::cout;
using std::endl;
void main() {
Louis::MyString proverb("Too many cooks spoil the broth.");
char word[] = "cook";
int position = proverb.find(word);
// Search for a C-style string
cout << "\nThe word '" << word;
if (position < 0)
cout << "' was not found in:";
else
cout << "' appears starting at position " << position << " in:";
proverb.show();
cout << endl;
// Search for a character
char ch = 'p';
position = proverb.find(ch);
cout << "\n\nThe character '" << ch;
if (position < 0)
cout << "' was not found in:";
else
cout << "' appears at position " << position << " in:";
proverb.show();
cout << endl;
// check other ways of creating MyString objects
Louis::MyString number(22);
Louis::MyString value("value = 22");
Louis::MyString repeated('2', 10);
repeated.show();
cout << "\nLength of string is " << repeated.length(); // Display the length
// Search for MyString SubStrings in MyString objects
position = value.find(number);
cout << "\n\nThe string:";
number.show();
if (position < 0)
cout << "' was not found in:";
else
cout << "\nappears at position " << position << " in:";
value.show();
cout << endl;
position = repeated.find(number);
cout << "\n\nThe string:";
number.show();
if (position < 0)
cout << "\n was not found in:";
else
cout << "\nappears at position " << position << " in:";
repeated.show();
cout << endl;
}