1、这些练习都建立
上一习题的基础之上,首先为MyString类提供一个重载的赋值运算符。确保它不是自我赋值。用下面的语句测试这个运算符是否正常工作,其中s1、s2和s3都是MyString对象:
s1=s2;
s1=s1;
s1=s2=s3;
2、重载+运算符,提供字符串连接功能。测试s1=s2+s3;语句正确运行。提供+=运算符,这个运算符应返回什么值?
3、重载[],提供对字符串中单个字符的访问。于是,s1[4]返回s1中的第5个字符。如何确保它可以用于等号的两端?
4、提供==、!=、<和>运算符的重载,用于比较MyString对象。这些布尔运算符应返回什么类型?检查表达式if(s1==s2)是否工作正确?
5、重载()运算符,从MyString对象中返回一个子字符串,于是s1(2,3)返回从s1[2]开始的三个字符。
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
MyString& operator=(const MyString& str); // Overloaded assignment operator
MyString operator+(const MyString& str) const; // string concatenation
MyString& operator+=(const MyString& rStr); // Append MyString
MyString& operator+=(const char* rStr); // Append C-Style string
const char& operator[](int index) const; // subscript operator for const objects
char& operator[](int index); // subscript operator for non-const objects
// Comparison operators all return type bool
bool operator==(const MyString& rStr) const;
bool operator!=(const MyString& rStr) const;
bool operator<(const MyString& rStr) const;
bool operator>(const MyString& rStr) const;
// Return an object corresponding to a substring
MyString operator()(int index, int length) const;
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>
#include <cstring>
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.";
}
// Overloaded assignment operator
MyString& MyString::operator =(const MyString& rStr) {
if (this == &rStr) // Is left string same object as right string?
return *this; // Yes, so just return it.
// object are different so assign rStr to *this
delete[] pStr; //Release memory for left operand (current string for *this object)
strLength = strlen(rStr.pStr); // strlen() returns length excluding terinating null
pStr = new char[strLength+1]; // Allocate space for string to be copied, space must allow for null, hence strLength+1
strcpy(pStr, rStr.pStr); // Copy argument string to data member
return *this;
}
// String concatenation
// Operator must return a new object which is created as a local object
// A copy of the local object will be returned
MyString MyString::operator+(const MyString& rStr) const {
return MyString(*this) += rStr;
}
// Append MyString string
// Operator returns a reference to the left string
// Uses the += operator for C-style strings to append the right string
MyString& MyString::operator+=(const MyString& rStr) {
return *this += rStr.pStr;
}
// Append C-style string
MyString& MyString::operator+=(const char* rStr) {
char* pNewStr = new char[strLength + strlen(rStr) + 1]; // Space for combined string
strcpy(pNewStr, pStr); // Copy left string to new string
strcpy(pNewStr+strLength, rStr); // Append right string to new string
strLength = strlen(pNewStr); // Update length
delete[] pStr; // Release left string memory
pStr = pNewStr; // Left string is new string
return *this; // Return left string
}
// subscript operator for const objects
// cannot be used on the left of an assignment as it return a const reference to char
const char& MyString::operator [](int index) const {
// There validity check would be better using exceptions to signal errors
// rather than calling exit().
if (strLength == 0) {
cout << "\nString is empty in subscript operation. Program aborted.";
exit(1);
}
if (strLength < index || index < 0) {
cout << "\nOut of range index in subscript operation. Program aborted.";
exit(1);
}
if (index < strLength)
return pStr[index];
exit(1);
}
// subscript operator for non-const objects - can be used on the left of an assignment
char& MyString::operator [](int index) {
// These validity check would be better using exceptions to signal errors
// rather than calling exit().
if (strLength == 0) {
cout << "\nString is empty in subscript operation. Program aborted.";
exit(1);
}
if (strLength < index || index < 0) {
cout << "\nOut of range index in subscript operation. Program aborted.";
exit(1);
}
if (index < strLength)
return pStr[index];
exit(1);
}
// Overloaded 'equals' operator
bool MyString::operator ==(const MyString& rStr) const {
return strcmp(pStr, rStr.pStr) == 0;
}
// Overloaded 'not equals' operator
bool MyString::operator !=(const MyString& rStr) const {
return !(*this == rStr);
}
// Overloaded 'greater than' operator
bool MyString::operator >(const MyString& rStr) const {
return strcmp(pStr, rStr.pStr) > 0;
}
// Overloaded 'less than' operator
bool MyString::operator <(const MyString& rStr) const {
return strcmp(pStr, rStr.pStr) < 0;
}
// Overloaded function call operator
// Returns a substring object - not a reference.
// A copy of the local object will be returned.
MyString MyString::operator ()(int index, int length) const {
if (index < 0 || index > strLength || index + length > strLength) {
cout << "\nOut of range in function call operator. Terminating program.";
exit(1);
}
char* pSubStr = new char[length+1]; // Get space for substring
for (int i=0; i<length; i++) // Copy the substring
pSubStr[i] = pStr[index+i];
pSubStr[length] = '\0'; // Append null character for end
MyString tempStr(pSubStr); // Define a new object
delete[] pSubStr; // Delete temporary string
return tempStr; // Return the object
}
} // End of namespace mySapce
main.cpp
// main.cpp
#include <iostream>
using std::cout;
using std::endl;
#include "MyString.h"
using namespace Louis;
void main() {
MyString s1;
MyString s2("s2: aaaaa");
MyString s3("s3: ccccc");
MyString s4;
s4 = s2 + s3;
s1 = s2;
s1 = s1;
s1 = s2 = s3;
s1.show();
s2.show();
s3.show();
s4.show();
s2 += s3;
s2.show();
s2 += " hello";
s2.show();
cout << endl;
cout << s2[s2.length()-1];
cout << endl;
s2[s2.length()-1] = 'x';
cout << s2[s2.length()-1];
cout << endl;
MyString str1("aaaa");
MyString str2("aaaa");
MyString str3("bbbb");
MyString str4("cccc hello world");
if (str1==str2)
cout << "str1 equal str2." << endl;
if (str1 != str3)
cout << "str1 not equal str3." << endl;
if (str1 < str3)
cout << "str1 < str3" << endl;
if (str4 > str3)
cout << "str4 > str3" << endl;
MyString str5 = str4(5,5);
str5.show();
cout << endl;
}