测试程序
/// @file exam_1_1.cpp
/**
1.完善MyString, 引用计数RefMyString
operator=
operator+
operator[](int nIndex)
operator==
operator!=
operator>
*/
#include "common.h"
#include "MyString.h"
void fnTestString();
void clear_cin();
int main(int argc, char** argv, char** envp)
{
fnTestString();
cout << "END, press any key to quit" << endl;
clear_cin();
getchar();
return 0;
}
void fnTestString()
{
CMyString str("hello");
CMyString str1(str);
CMyString str2 = CMyString("hello world");
str1 = "vc6";
cout << str1 << endl;
str2 += " vc6";
cout << str2 << endl;
str1 = str2 + " c++";
cout << str1.c_str() << endl;
cout << (str1 >= "hello") << endl;
cout << str[2] << endl;
cout << str[-1] << endl;
cout << str.c_str() << endl;
cout << (str2 > NULL) << endl;
cout << (str2 >= "hello") << endl;
cout << (str2 < "hello") << endl;
cout << (str2 <= "hello") << endl;
cout << (str2 == "hello") << endl;
cout << (str2 != "hello") << endl;
cout << str2.StringFormatV("test %d", 1) << endl;
}
void clear_cin()
{
cin.clear();
cin.sync();
}
公用头文件
/// @file common.h
/// @brief 公用头文件
#ifndef COMMON_H_1460AB26_69BA_45E7_8E75_3867BF8DA316
#define COMMON_H_1460AB26_69BA_45E7_8E75_3867BF8DA316
#include <iostream>
#include <limits>
#include <string>
#include <crtdbg.h>
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <stdarg.h>
using namespace std;
#ifndef BOOL
#define BOOL int
#define TRUE 1
#define FALSE 0
#endif // #ifndef BOOL
#ifndef NULL
#define NULL 0
#endif // #ifndef NULL
#ifndef SAFE_DELETE
#define SAFE_DELETE(x) \
{ \
if (NULL != (x)) \
{ \
delete (x); \
(x) = NULL; \
} \
}
#endif // #ifndef SAFE_DELETE
#ifndef SAFE_DELETE_ARY
#define SAFE_DELETE_ARY(x) \
{ \
if (NULL != (x)) \
{ \
delete[] (x); \
(x) = NULL; \
} \
}
#endif // #ifndef SAFE_DELETE_ARY
#endif // #ifndef COMMON_H_1460AB26_69BA_45E7_8E75_3867BF8DA316
RefCount.h
// RefCount.h: interface for the CRefCount class.
//
//
#if !defined(AFX_REFCOUNT_H__2F7675D6_BDC0_4BE6_A0FD_14F51476D8ED__INCLUDED_)
#define AFX_REFCOUNT_H__2F7675D6_BDC0_4BE6_A0FD_14F51476D8ED__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "common.h"
#include "MyString.h"
class CMyString;
class CRefCount
{
public:
CRefCount(CMyString* pOwner);
CRefCount(const CRefCount* pObj);
CRefCount(const CRefCount& Obj);
virtual ~CRefCount();
void addRef(); ///< 引用计数++
int releaseRef(); ///< 引用计数--
int* getRefCount() {return m_piRefCount;}
CMyString* getOwner() {return m_pOwner;}
private:
void cpyAndAddRef(const CRefCount* pObj);
private:
int* m_piRefCount; ///< 引用计数点数指针
CMyString* m_pOwner; ///< 引用计数所有者指针
};
#endif // !defined(AFX_REFCOUNT_H__2F7675D6_BDC0_4BE6_A0FD_14F51476D8ED__INCLUDED_)
MyString.h
// MyString.h: interface for the CMyString class.
//
//
#if !defined(AFX_MYSTRING_H__F5118BD7_4C05_47F1_AD8E_D18B1F44B0CA__INCLUDED_)
#define AFX_MYSTRING_H__F5118BD7_4C05_47F1_AD8E_D18B1F44B0CA__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "common.h"
#include "RefCount.h"
class CRefCount;
class CMyString
{
/// 构造函数, 析构函数, 拷贝构造函数
public:
CMyString();
CMyString(const char* psrc);
virtual ~CMyString();
CMyString(CMyString& src);
CMyString(CMyString* psrc);
/// 转换运算符重载
/// 运算符重载
void operator = (const char* pSrc);
CMyString operator + (const char* pSrc);
CMyString& operator += (const char* pSrc);
bool operator > (const char* pSrc);
bool operator >= (const char* pSrc);
bool operator < (const char* pSrc);
bool operator <= (const char* pSrc);
bool operator == (const char* pSrc);
bool operator != (const char* pSrc);
const char* operator [] (size_t nIndex) const;
/// 成员方法
virtual BOOL IsRefCountNULL();
virtual CRefCount* getRefCount() {return m_pRefCount;}
const char* c_str() const;
const char* StringFormatV(char* szFormat, ...);
private:
virtual CMyString* strcat(const char* pSrc);
void setString(const char* pSrc);
CMyString* strcpy(const char* pSrc);
int compare(const char* pSrc);
void init(CMyString* pRefOwner);
void init_refcount(CMyString* pRefOwner);
void uninit();
BOOL uninit_refcount();
// member data
private:
char* m_lpString; ///< 开辟(new)的字符串缓冲区
int m_nLen; ///< 字符串长度
/// 如果最终要操作的字符串比缓冲区小, 就不用另外再开辟缓冲区了
int m_nSpaceLen; ///< 缓冲区总长度
CRefCount* m_pRefCount; ///< 引用计数
};
ostream& operator<< (ostream& cout, CMyString& right);
#endif // !defined(AFX_MYSTRING_H__F5118BD7_4C05_47F1_AD8E_D18B1F44B0CA__INCLUDED_)
MyString.cpp
// MyString.cpp: implementation of the CMyString class.
//
//
#include "MyString.h"
//
// Construction/Destruction
//
CMyString::CMyString()
: m_pRefCount(NULL)
{
init(this);
}
CMyString::~CMyString()
{
uninit();
}
CMyString::CMyString(CMyString& src)
: m_pRefCount(NULL)
{
init(&src);
this->strcpy(src.c_str());
}
CMyString::CMyString(CMyString* psrc)
: m_pRefCount(NULL)
{
init(psrc);
if (NULL != psrc)
{
this->strcpy(psrc->c_str());
}
}
CMyString::CMyString(const char* psrc)
: m_pRefCount(NULL)
{
init(this);
if (NULL != psrc)
{
this->strcpy(psrc);
}
}
void CMyString::operator = (const char* pSrc)
{
strcpy(pSrc);
}
CMyString CMyString::operator + (const char* pSrc)
{
CMyString tmp;
tmp = *this;
tmp += pSrc;
return tmp;
}
CMyString& CMyString::operator += (const char* pSrc)
{
strcat(pSrc);
return *this;
}
const char* CMyString::operator [] (size_t nIndex) const
{
char* pRc = "";
if ((NULL != m_lpString)
&& (nIndex >= 0)
&& (nIndex < strlen(m_lpString)))
{
pRc = m_lpString + nIndex;
}
return pRc;
}
int CMyString::compare(const char* pSrc)
{
int iRc = 0;
const char * pMe = (NULL != m_lpString) ? m_lpString : "";
const char * pSrcCpy = (NULL != pSrc) ? pSrc : "";
/// strcmp入参为空指针会报错
iRc = ::strcmp(pMe, pSrcCpy);
return iRc;
}
bool CMyString::operator > (const char* pSrc)
{
return (compare(pSrc) > 0);
}
bool CMyString::operator >= (const char* pSrc)
{
return (compare(pSrc) >= 0);
}
bool CMyString::operator < (const char* pSrc)
{
return (compare(pSrc) < 0);
}
bool CMyString::operator <= (const char* pSrc)
{
return (compare(pSrc) <= 0);
}
bool CMyString::operator == (const char* pSrc)
{
return (compare(pSrc) == 0);
}
bool CMyString::operator != (const char* pSrc)
{
return (compare(pSrc) != 0);
}
void CMyString::init(CMyString* pRefOwner)
{
if (NULL != pRefOwner)
{
m_lpString = NULL;
m_nLen = 0;
m_nSpaceLen = 0;
init_refcount(pRefOwner);
}
}
BOOL CMyString::IsRefCountNULL()
{
if (NULL == m_pRefCount)
{
return TRUE;
}
return (NULL == m_pRefCount->getRefCount());
}
void CMyString::init_refcount(CMyString* pRefOwner)
{
if (NULL == m_pRefCount)
{
m_pRefCount = new CRefCount(pRefOwner);
}
if (NULL != m_pRefCount)
{
m_pRefCount->addRef();
}
}
void CMyString::uninit()
{
if (uninit_refcount())
{
SAFE_DELETE_ARY(m_lpString);
}
SAFE_DELETE(m_pRefCount);
}
BOOL CMyString::uninit_refcount()
{
BOOL bRc = FALSE;
if (NULL != m_pRefCount)
{
bRc = (0 == m_pRefCount->releaseRef());
}
return bRc;
}
void CMyString::setString(const char* pSrc)
{
this->strcpy(pSrc);
}
const char* CMyString::c_str() const
{
if (NULL == m_lpString)
{
return "";
}
else
{
return m_lpString;
}
}
CMyString* CMyString::strcpy(const char* pSrc)
{
int iLenNew = 0;
char* pNewString = NULL;
if (NULL == pSrc)
{
return this;
}
iLenNew = ::strlen(pSrc);
if (iLenNew > (m_nSpaceLen - 1))
{
pNewString = new char[iLenNew + 1];
_ASSERT(NULL != pNewString);
pNewString[0] = '\0';
::strcpy(pNewString, pSrc);
SAFE_DELETE_ARY(m_lpString);
m_nLen = iLenNew;
m_nSpaceLen = m_nLen + 1;
m_lpString = pNewString;
}
else
{
m_nLen = strlen(pSrc);
_ASSERT(NULL != m_lpString);
if (0 != ::strcmp(m_lpString, pSrc))
{
::strcpy(m_lpString, pSrc);
}
}
return this;
}
CMyString* CMyString::strcat(const char* pSrc)
{
int iLenNew = 0;
char* pNewString = NULL;
if (NULL == pSrc)
{
return this;
}
if (NULL == m_lpString)
{
this->strcpy(pSrc);
return this;
}
iLenNew = m_nLen + strlen(pSrc);
if (iLenNew > (m_nSpaceLen - 1))
{
pNewString = new char[iLenNew + 1];
pNewString[0] = '\0';
::strcpy(pNewString, m_lpString);
SAFE_DELETE_ARY(m_lpString);
::strcat(pNewString, pSrc);
m_nLen = iLenNew;
m_nSpaceLen = m_nLen + 1;
m_lpString = pNewString;
}
else
{
m_nLen += strlen(pSrc);
::strcat(m_lpString, pSrc);
}
return this;
}
const char* CMyString::StringFormatV(char* szFormat, ...)
{
size_t nStrLen = 1024 * 100; ///< 默认开100K空间
va_list args;
char* pNewString = NULL;
va_start(args, szFormat);
/**
_MSC_VER Defines the compiler version.
Defined as 1200 for Microsoft Visual C++ 6.0. Always defined.
*/
if (_MSC_VER > 1200)
{
/// vs6不允许这么用, vs2010可以
/// 估算需要的缓冲区长度
nStrLen = _vsnprintf(NULL, 0, szFormat, args);
}
pNewString = new char[nStrLen + 1];
_ASSERT(pNewString);
::memset(pNewString, 0, (nStrLen + 1) * sizeof(char));
nStrLen = _vsnprintf(pNewString, nStrLen, szFormat, args);
va_end(args);
this->strcpy(pNewString);
return this->c_str();
}
ostream& operator<< (ostream& cout, CMyString& right)
{
cout << right.c_str();
return cout;
}
RefCount.cpp
// RefCount.cpp: implementation of the CRefCount class.
//
//
#include "RefCount.h"
//
// Construction/Destruction
//
using namespace std;
CRefCount::CRefCount(CMyString* pOwner)
:m_piRefCount(NULL)
,m_pOwner(NULL)
{
if (NULL != pOwner)
{
if (pOwner->IsRefCountNULL())
{
m_piRefCount = new int(0);
}
else
{
m_piRefCount = pOwner->getRefCount()->getRefCount();
}
m_pOwner = pOwner;
addRef();
}
}
CRefCount::CRefCount(const CRefCount* pObj)
{
cpyAndAddRef(pObj);
}
CRefCount::CRefCount(const CRefCount& Obj)
{
cpyAndAddRef(&Obj);
}
void CRefCount::cpyAndAddRef(const CRefCount* pObj)
{
if ((NULL == pObj) || (this == pObj))
{
return;
}
m_piRefCount = pObj->m_piRefCount;
m_pOwner = pObj->m_pOwner;
addRef();
}
CRefCount::~CRefCount()
{
if (0 == releaseRef())
{
if (NULL != m_pOwner)
{
/// CRefCount作为m_pOwner中的一个new出来的指针
/// 这里不能删除m_pOwner
/// 会引起递归调用
/// 只能将m_pOwner置为空
/// 让调用者显式释放m_pOwner
m_pOwner = NULL;
}
if (NULL != m_piRefCount)
{
delete m_piRefCount;
m_piRefCount = NULL;
}
}
}
void CRefCount::addRef()
{
int iRc = 0;
if (NULL != m_piRefCount)
{
(*m_piRefCount)++;
iRc = *m_piRefCount;
}
}
int CRefCount::releaseRef()
{
int iRc = 0;
iRc = (NULL != *m_piRefCount) ? (--(*m_piRefCount)) : 0;
return iRc;
}