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;
}