- 论坛徽章:
- 0
|
初学C++,在VC++6.0中写了一个简单的String类,请多批评指正,谢谢!- #include <iostream.h>
- #include <string.h>
- #include <assert.h>
- #include <stdlib.h>
- class String
- {
- private: // 私有数据成员:
- unsigned length; // length of string in characters(not counting null terminator)
- char *char_ptr; // pointer to string contents,用于保存字符串
- public:
- //String() { length = 0; char_ptr = NULL; };
- //取消上述默认构造函数,否则与下面的有默认参数的通用构造函数冲突:
- // warning C4520: 'String' : multiple default constructors specified
- inline String(const char *pstr = NULL); // conversion/default constructor
- // 通用构造函数,默认参数只在定义中写
- // 由于有默认参数,会与 String() 冲突
- String(const String &another); // copy constructor,拷贝构造函数
- //拷贝构造函数,经常被称作X(X&),是一种特殊的构造函数,它由编译器调用来完成
- //一些基于同一类的其他对象的构件及初始化。它的唯一的一个参数(对象的引用)
- //是不可变的(因为是const型的)。
- String(const unsigned count, const char ch);
- ~String(); // // destructor,析构函数
- // assignment operator,赋值运算符
- const String & operator = (const String &right);
- const String & operator = (const char *pstr);
- const String & operator = (int nNum);
- // 重载[], 实现数组运算
- char& operator [] (unsigned int nIdx); // subscript operator (modifiable lvalue)
- // 重载[], 实现数组运算(对象为常量)
- //const char& operator [] (unsigned int nIdx) const;
- // 重载[], 实现数组运算
- char operator[](unsigned int) const; // subscript operator (rvalue)
- // 重载[]
- String& operator [] (const String& obj);
- // 重载(), return a substring
- String operator () (const unsigned nIdx, const unsigned count) const;
- // 重载+=,实现与对象相加
- String& operator += (const String& right); // concatenation operator
- // 重载+=,实现与字符串相加
- String& operator += (const char *pstr);
- const String operator+(const String& right) const;
- friend String operator+(const String s1, const String s2);
- // 如果写成 friend String operator+(const String &s1, const String &s2);
- // 则后面的3条语句:
- // return s1 + String(cs2);
- // return String(cs1) + s2;
- // String c = a + b;
- // 报错:error C2593: 'operator +' is ambiguous
- friend String operator+(const String &s1, const char * cs2);
- friend String operator+(const char * cs1, const String &s2);
- friend String operator&(const String &s1, const String &s2);
- friend String operator&(const String &s1, const char * cs2);
- friend String operator&(const char * cs1, const String &s2);
- bool operator!() const; // is String empty?
- bool operator > (const String &right);
- bool operator >= (const String &right);
- bool operator < (const String &right);
- bool operator <= (const String &right);
- bool operator == (const String &right);
- // 重载比较运算符!=
- bool operator != (const String &right);
- friend ostream &operator << (ostream &out, const String &s)
- {//输出
- if(&s == NULL)
- out << "<NULL>";
- else if(s.char_ptr == NULL)
- out << "{NULL}";
- else
- out << s.char_ptr;
- return out;
- }
- friend istream &operator >> (istream &in, String &s)
- {//输入
- char tmp[255]; //用于存储输入流
- in >> tmp;
- s = tmp; //使用赋值运算符
- return in; //使用return可以支持连续使用>>运算符
- }
- int getLength() const { return length; };
- char *getPtr() const { return char_ptr; };
- String substr(unsigned st, unsigned len); // 提取子串,st为开始位置,len为提取长度
- String & append(const String &right); // 拼接
- // 如果命名为strcat则会与string.h中的strcat冲突,报错:
- // error C2661: 'strcat' : no overloaded function takes 2 parameters
- String & append(const char *pstr); // 拼接
- int find(const char *pstr, unsigned st); // 查找,st开始位置,可不填,默认为0
- int find(const String &another, unsigned st); // 查找,st开始位置,可不填,默认为0
- String & replace(const char *src, const char *dst); // 替换
- String & replace(const String &src, const String &dst); // 替换
- };
- inline String::String(const char *pstr /* = NULL */) // 通用构造函数
- // 声明为inline函数,则该函数在程序中被执行时是语句直接替换,而不是被调用
- {
- if(pstr == NULL)
- cout << "--- 通用构造函数调用之初,pstr=(NULL)\n";
- else
- cout << "--- 通用构造函数调用之初,pstr=[" << pstr << "]\n";
- if(pstr == NULL) { length = 0; char_ptr = NULL; return; }
- length = strlen(pstr);
- char_ptr = new char[length + 1];
- strcpy(char_ptr, pstr);
- }
- String::String(const String &another) // 拷贝构造函数
- // 类String拷贝构造函数与普通构造函数的区别是:
- // 在函数入口处无需与NULL进行比较,这是因为“引用”不可能是NULL,
- // 而“指针”可以为NULL。
- {
- cout << "--- 拷贝构造函数调用之初,another=[" << another << "]\n";
- // if(*this != another) // 这种写法会调用下面重载的操作符 !=
- if(this != &another)
- {
- if(another.length == 0) { length = 0; char_ptr = NULL; return; }
- // 在类的成员函数内可以访问同种类对象的私有成员(同种类肯定是友元关系)
- length = another.length;
- char_ptr = new char[length + 1];
- strcpy(char_ptr, another.char_ptr);
- }
- }
- String::String(const unsigned count, const char ch)
- {
- cout << "--- 另一个构造函数调用之初,count=" << count << ", ch=" << ch << endl;
- if(count <= 0) { length = 0; char_ptr = NULL; return; }
- length = count;
- char_ptr = new char[length + 1];
- memset(char_ptr, ch, length);
- char_ptr[length] = 0x00;
- }
- String::~String() // 析构函数
- {
- cout << "--- 执行析构函数, length=" << length;
- if(length > 0)
- cout << ", char_ptr:" << char_ptr << endl; // endl 等效于 "\n"
- else
- cout << endl; // endl 等效于 "\n"
- if(length > 0 && !char_ptr) delete []char_ptr;
- // 由于 char_ptr是内部数据类型,也可以写成 delete char_ptr;
- char_ptr = NULL;
- length = 0;
- }
- const String & String::operator = (const String &right) // 赋值运算符
- {
- cout << "--- 执行赋值运算, right=" << right << endl;
- // 检查自赋值, 注意不要将检查自赋值的if语句“if(this == &right)”
- // 错写成为“if(*this == right)”
- if(this == &right) return *this;
- // 释放原有资源。如果现在不释放,以后就没机会了,将造成内存泄露。
- if(!char_ptr) delete []char_ptr;
- if(right.length == 0) { length = 0; char_ptr = NULL; return *this; }
- // 分配新的内存资源,并复制内容
- length = right.length;
- char_ptr = new char[length + 1];
- strcpy(char_ptr, right.char_ptr); // 函数strcpy则连'\0'一起复制。
- // 返回本对象的引用,目的是为了实现象 a = b = c 这样的链式表达。
- // 注意不要将 return *this 错写成 return this
- return *this;
- }
- const String & String::operator = (const char *pstr) // 赋值运算符
- {
- cout << "--- 执行赋值运算, pstr=" << pstr << endl;
- if(pstr == NULL) { length = 0; char_ptr = NULL; return *this; }
- // 释放原有资源
- if(!char_ptr) delete []char_ptr;
- // 如果不加 if(!char_ptr) 判断将可能导致下述错误:
- // Debug Error!
- // DAMAGE:after Normal block(#53)at 0x00441940.
- length = strlen(pstr);
- char_ptr = new char[length + 1];
- strcpy(char_ptr, pstr);
- // 返回本对象的引用
- return *this;
- }
- const String& String::operator = (int nNum) // 赋值运算符
- {
- cout << "--- 执行赋值运算, nNum=" << nNum << endl;
- char szNum[24];
- itoa(nNum, szNum, 10);
- if(!char_ptr) delete []char_ptr;
- char_ptr = new char[strlen(szNum) + 1];
- strcpy(char_ptr, szNum);
- return *this;
- }
- // 重载[], 实现数组运算,return reference to character in String as a modifiable lvalue
- char& String::operator [] (unsigned int nIdx)
- {
- cout << "--- 执行[]运算, modifiable lvalue" << endl;
- // test for subscript out of range
- if(nIdx < 0 || nIdx >= length )
- {
- cerr << "Error: Subscript " << nIdx
- << " out of range" << endl;
- exit(1); // terminate program
- }
- return char_ptr[nIdx]; // non-const return; modifiable lvalue
- }
- /*
- // 重载[], 实现数组运算(对象为常量)
- const char& String::operator [] (unsigned int nIdx) const
- {
- assert(nIdx <= length);
- return char_ptr[nIdx];
- }
- */
- // return reference to character in String as rvalue
- char String::operator[](unsigned int nIdx) const // subscript operator (rvalue)
- {
- cout << "--- 执行[]运算, subscript operator (rvalue)" << endl;
- assert(nIdx <= length);
- return char_ptr[nIdx]; // returns copy of this element
- }
- // 重载[]
- String& String::operator [] (const String& obj)
- {
- if(obj.char_ptr == NULL)
- {
- return *this;
- }
- char *pTmp = new char[length + obj.length + 1];
- strcpy(pTmp, char_ptr);
- strcat(pTmp, obj.char_ptr);
- if(!char_ptr) delete []char_ptr;
- char_ptr = pTmp;
- return *this;
- }
- // 重载()
- String String::operator () (const unsigned nIdx, const unsigned count) const
- {
- if(nIdx < 0 || count <= 0 || nIdx >= length) return NULL;
- String result;
- if(nIdx + count > length)
- result.length = length - nIdx;
- else
- result.length = count;
- result.char_ptr = new char[result.length + 1];
- strncpy(result.char_ptr, char_ptr + nIdx, result.length);
- result.char_ptr[result.length] = 0x00;
- return result;
- }
- // 重载+=,实现与对象相加.
- // Concatenate right operand to this object and store in this object.
- String &String::operator+=(const String &right)
- {
- cout << "--- 执行+=运算, right=" << right << endl;
- if(&right == NULL)
- {
- return *this;
- }
- char *tempPtr = char_ptr; // hold to be able to delete
- length += right.length; // new String length
- char_ptr = new char[length + 1]; // create space
- assert(char_ptr != 0); // terminate if memory not allocated
- strcpy(char_ptr, tempPtr); // left part of new String
- strcat(char_ptr, right.char_ptr); // right part of new String
- delete [] tempPtr; // reclaim old space
- return *this; // enables concatenated calls
- }
- // 重载+=,实现与字符串相加
- String& String::operator += (const char *pstr)
- {
- cout << "--- 执行+=运算, pstr=" << pstr << endl;
- if(pstr == NULL)
- {
- return *this;
- }
- char *pTmp = new char[length + strlen(pstr) + 1];
- strcpy(pTmp, char_ptr);
- strcat(pTmp, pstr);
- if(!char_ptr) delete []char_ptr;
- char_ptr = pTmp;
- return *this;
- }
- const String String::operator+(const String& right) const
- {
- cout << "--- 执行 + 运算, right=" << right << endl;
- if(&right == NULL)
- {
- return *this;
- }
- char* r = new char [length + right.length + 1]; // temporary
- assert(r != 0);
- strcpy(r, char_ptr); // init with left string
- strcpy(r + length, right.char_ptr); // add right string
- String result(r); // construct String object
- delete [] r; // free temporary
- return result;
- }
- String operator+(const String s1, const String s2)
- {
- cout << "--- 执行 + 运算, s1=" << s1 << ", s2=" << s2 << endl;
- String s3;
- s3.length = s1.length + s2.length;
- s3.char_ptr = new char[s3.length + 1];
- if(s1.length > 0)
- strcpy(s3.char_ptr, s1.char_ptr);
- else
- strcpy(s3.char_ptr, "");
- if(s2.length > 0)
- strcat(s3.char_ptr, s2.char_ptr);
- s3.char_ptr[s3.length] = 0x00;
- return s3;
- }
- String operator+(const String &s1, const char * cs2)
- {
- cout << "--- 执行 + 运算, s1=" << s1 << ", cs2=" << cs2 << endl;
- return s1 + String(cs2);
- }
- String operator+(const char * cs1, const String &s2)
- {
- cout << "--- 执行 + 运算, cs1=" << cs1 << ", s2=" << s2 << endl;
- return String(cs1) + s2;
- }
- String operator&(const String &s1, const String &s2)
- {
- cout << "--- 执行 & 运算, s1=" << s1 << ", s2=" << s2 << endl;
- String s3;
- s3.length = s1.length + s2.length;
- s3.char_ptr = new char[s3.length + 1];
- strcpy(s3.char_ptr, s1.char_ptr);
- strcat(s3.char_ptr, s2.char_ptr);
- return s3;
- }
- String operator&(const String &s1, const char * cs2)
- {
- cout << "--- 执行 & 运算, s1=" << s1 << ", cs2=" << cs2 << endl;
- return s1 + String(cs2);
- }
- String operator&(const char * cs1, const String &s2)
- {
- cout << "--- 执行 & 运算, cs1=" << cs1 << ", s2=" << s2 << endl;
- return String(cs1) + s2;
- }
- bool String::operator!() const // is String empty?
- {
- cout << "--- 执行 !() 运算, length=" << length << endl;
- return length == 0;
- }
- bool String::operator > (const String &right)
- {
- if(length > 0 && right.length == 0) return true;
- if(length == 0 && right.length > 0) return false;
- int pos = 0;
- while(char_ptr[pos] == right.char_ptr[pos] && char_ptr[pos] != '\0') pos++;
- if(char_ptr[pos] > right.char_ptr[pos]) return true;
- else return false;
- }
- bool String::operator >= (const String &right)
- {
- if(length > 0 && right.length == 0) return true;
- if(length == 0 && right.length > 0) return false;
- int pos = 0;
- while(char_ptr[pos] == right.char_ptr[pos] && char_ptr[pos] != '\0') pos++;
- if(char_ptr[pos] > right.char_ptr[pos] ||
- (char_ptr[pos] == right.char_ptr[pos] && char_ptr[pos] == '\0'))
- return true;
- else return false;
- }
- bool String::operator < (const String &right)
- {
- return !((*this) >= right);
- }
- bool String::operator <= (const String &right)
- {
- return !((*this) > right);
- }
- bool String::operator == (const String &right)
- {
- //return !((*this) > right) && !((*this) < right);
- return !strcmp(char_ptr, right.char_ptr);
- }
- bool String::operator != (const String &right)
- {
- return !((*this) == right);
- }
- String String::substr(unsigned st, unsigned n)
- {
- if(st < 0 || n <= 0 || st + n > length) return NULL;
- char *tmp = new char[n+1];
- for(unsigned i = 0; i < n; i++)
- {
- tmp[i] = char_ptr[st + i];
- }
- tmp[n] = '\0';
- return String(tmp);
- }
- String &String::append(const String &right)
- {
- if(&right == NULL || right.length == 0) return *this;
- char* r = new char [length + right.length + 1]; // temporary
- assert(r != 0);
- strcpy(r, char_ptr); // init with left string
- strcpy(r + length, right.char_ptr); // add right string
- if(!char_ptr) delete []char_ptr;
- char_ptr = r;
- return *this;
- }
- String &String::append(const char *pstr)
- {
- if(NULL == pstr) return *this;
- char *tmp = new char[length + strlen(pstr) + 1];
- assert(tmp != 0);
- strcpy(tmp, char_ptr);
- strcat(tmp, pstr);
- if(!char_ptr) delete []char_ptr;
- char_ptr = tmp;
- return *this;
- }
- int String::find(const char *pstr, unsigned st = 0)
- {
- if(st < 0 || st >= length) return -1;
- int strPos = st;
- while(char_ptr[strPos] != '\0')
- {
- int curPos = strPos;
- int pPos = 0;
- if(char_ptr[strPos] != pstr[pPos])
- {
- strPos++;
- continue; //如果当前字符不相等,继续下一个字符
- }
- while(char_ptr[curPos] == pstr[pPos] && pstr[pPos] != '\0')
- {
- curPos++;
- pPos++; //相等的部分跳过
- }
- if(pstr[pPos] == '\0') return strPos;
- else
- {
- strPos++;
- continue;//如果当前字符不相等,继续下一个字符
- }
- }
- return -1;
- }
- int String::find(const String &another, unsigned st)
- {
- return find(another.char_ptr, st);
- }
- String &String::replace(const char *src, const char *dst)
- {
- if(src == NULL || dst == NULL) return *this;
- int pos = find(src);
- if(pos < 0) return *this; //没有源串就退出函数
- int lenSrc = 0, lenDst = 0;
- while(src[lenSrc++]);
- while(dst[lenDst++]);
- lenSrc -= 1;
- lenDst -= 1;
- char *tmp = new char[length + lenDst - lenSrc + 1];
- int curChar = 0;
- while(curChar < pos)
- {
- tmp[curChar] = char_ptr[curChar];
- curChar++;
- }
- int i = 0;
- while(i < lenDst)
- {
- tmp[curChar] = dst[i];
- curChar++;
- i++;
- }
- pos += lenSrc;
- while(pos < (int)length)
- {
- tmp[curChar] = char_ptr[pos];
- curChar++;
- pos++;
- }
- tmp[curChar] = '\0';
- if(!char_ptr) delete []char_ptr;
- char_ptr = tmp;
- return replace(src, dst); //递归调用替换所有串
- }
- String &String::replace(const String &src, const String &dst)
- {
- return replace(src.char_ptr, dst.char_ptr);
- }
- void main()
- {
- String s("12345"); // 测试
- cout << "=== @main(), s=[" << s << "]\n";
- String o = s;
- cout << "=== @main(), after o=s, o:" << o << endl;
- o = "12345678";
- cout << "=== @main(), after o='12345678', o:" << o << endl;
- cout << "=== @main(), o.substr(2,2):" << o.substr(2,2) << endl;
- o.append(String("ABC"));
- cout << "=== @main(), after o.strcat(ABC), o:" << o << endl;
- o.append("DEF");
- cout << "=== @main(), after o.strcat(DEF), o:" << o << endl;
- s = "123435333336";
- o = "123435333336";
- cout << "=== @main(), s 和 o 重新赋值, s=[" << s << "], o=[" << o << "]\n";
- cout << "=== @main(), true=" << true << ", false=" << false << endl;
- cout << "=== @main(), 检测 s == o 结果: " << (s == o) << endl;
- cout << "=== @main(), 检测 s != o 结果: " << (s != o) << endl;
- cout << "=== @main(), 检测 s > o 结果: " << (s > o) << endl;
- cout << "=== @main(), 检测 s >= o 结果: " << (s >= o) << endl;
- cout << "=== @main(), 检测 s < o 结果: " << (s < o) << endl;
- cout << "=== @main(), 检测 s <= o 结果: " << (s <= o) << endl;
- String ss = s(3, 4);
- cout << "=== @main(), ss=s(3,4): " << ss << endl;
- cout << "=== @main(), after s.replace(...), result=[" << s.replace(String("3"),String("A")) << "]\n\n";
- String a="aaa";
- String b="bbb";
- String c = a + b;
- cout << "=== @main(), c=a+b=[" << c << "]\n";
- String d = a + "!!!ddd";
- cout << "=== @main(), d=[" << d << "]\n";
- String e = "eee " + b;
- cout << "=== @main(), e=[" << e << "]\n";
- String f = a & b;
- cout << "=== @main(), f=a&b=[" << f << "]\n";
- String r(10, 'x');
- cout << "=== @main(), r=[" << r << "]\n";
- r += a;
- cout << "=== @main(), r+=a, =[" << r << "]\n";
- r += "Hello";
- cout << "=== @main(), r+=\"Hello\", =[" << r << "]\n";
- String s1, s2, s3, s4, s5, s6;
- s1 = s2 = s3 = s4 = "Hello!";
- s6 = s5 + "666";
- cout << "=== @main(), s6=[" << s6 << "]\n";
- cout << "=== @main(), !s5=" << (!s5) << "\n";
- cout << "=== @main(), !s6=" << (!s6) << "\n";
- char c1 = s6[2];
- cout << "=== @main(), c1 = s6[2]=" << c1 << "\n";
- s6[2] = '2';
- cout << "=== @main(), s6[2]=" << s6[2] << "\n";
- }
复制代码 |
|