PPC的C/C++和人工智能学习笔记
每一篇学习笔记,都只是为了更好地掌握和理解

C++语言基础(11-1)_自己实现string类

C++的类基本上学完了,自己做个string类练习:

XString类的头文件XString.h

/* XString.h
 成员变量:
 m_pStr;指针
 m_length; 长度
*/

#pragma once
#ifndef _XSTRING_H
#define _XSTRING_H

class XString
{
public:
 XString(); //空参构造
 XString(const char*); //字符串常量构造
 XString(char, int); //重复字符构造
 XString(const XString& other); //拷贝构造
 ~XString();
public: //方法
 int getLength() const; //获取字符串长度
 bool isEmpty() const; //判断是否为空串
 const char * c_Str() const; //返回C风格字符串
 void copyTo(XString&) const; //复制到
 XString& strCat(const XString&); //把同类型字符串连接到本对象中
 XString& strCat(const char*); //把字符串常量连接到本对象中
 XString& append(char); //尾部增加一个字符
 int findStr(const XString&) const; //查找字串第一次出现的位置,-1表示没找到
 int findStr(const char*) const; //查找字串第一次出现的位置,-1表示没找到
 int findStrPP(const XString&, XString&) const; //字符串查找,返回值表示 找到的个数,位置存放在引用中
 int findStrPP(const char*, XString&) const; //字符串查找
public: //操作符重载 << >> + += = ~ () [] > < == != >= <=
 friend std::ostream& operator << (std::ostream&, const XString&); //<<重载 友元函数
 friend std::istream& operator >> (std::istream&, XString&); //<<重载 友元函数
 XString& operator = (const XString&); //=重载, 同类型赋值
 XString& operator = (const char*); //=重载,字符串常量赋值
 XString operator + (const XString&) const; //+重载,同类加
 friend XString operator +(const XString&, const char*); //+友元实现 字符串常量相加(与上面不同写法)
 XString& operator += (const XString&); // += 重载
 XString& operator += (const char*); // += 重载
 XString& operator ~(); //反序字符串
 char operator [] (int index); //[]重载
 operator const char* (); //()重载 类型强转 转为 const char * 类型
 bool operator > (const XString&) const; //比较 >
 bool operator > (const char*) const; //比较 >
 bool operator < (const XString&) const; // <
 bool operator < (const char*) const; // <
 bool operator >= (const XString&) const; //比较 >=
 bool operator >= (const char*) const; //比较 >=
 bool operator <= (const XString&) const; // <=
 bool operator <= (const char*) const; // <=
 bool operator == (const XString&) const; // ==
 bool operator == (const char*) const; // ==
 bool operator != (const XString&) const; // !=
 bool operator != (const char*) const; // !=
private:
 char *m_pStr; //字符串的指针
 int /*用size_t?*/ m_length;//字符串长度 
};

#endif

XString类的CPP文件XString.cpp

//XString.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string.h>
#include <assert.h>
#include "XString.h"
using std::cout;
using std::endl;
using std::cin;
using std::ostream;
using std::istream;

XString::XString() //无参构造
{
 m_pStr = new char[1]; //构建一个空串
 assert(m_pStr != NULL);
 *m_pStr = '\0'; 
 m_length = 0;
}

XString::XString(const char* str) //字符串常量构造
{
 assert(str != NULL); //断言str不能为NULL
 int len = strlen(str);
 m_pStr = new char[len+1];
 assert(m_pStr != NULL);
 strcpy(m_pStr, str);
 m_length = len;
}

XString::XString(char c, int n) //重复字符构造
{
 assert(n >= 0); //n必须>=0
 m_pStr = new char[n + 1];
 assert(m_pStr != NULL);
 memset(static_cast<void *>(m_pStr), c, n);
 m_pStr[n] = '\0';
 m_length = n;
}

XString::XString(const XString& other) //拷贝构造
{
 assert(other.c_Str() != NULL);
 m_pStr = new char[other.getLength() + 1];
 assert(m_pStr != NULL);
 strcpy(m_pStr, other.c_Str()); //为啥这里直接other.m_pStr 也是可以的
 m_length = other.getLength(); //直接用私有成员可能效率更高些,是不是正规写法就是直接写私有成员
}

XString::~XString()
{
 if (NULL != m_pStr)
 delete[] m_pStr;
 m_pStr = NULL;
}

int XString::getLength() const //获取字符串长度
{
 return m_length;
}

bool XString::isEmpty() const //判断是否为空串
{
 if (m_length == 0)
 return true;
 return false;
}

const char * XString::c_Str() const //返回C风格字符串
{
 return m_pStr;
}

void XString::copyTo(XString& dst) const //复制到
{
 char *pNew = new char[m_length + 1];
 assert(pNew != NULL);
 strcpy(pNew, m_pStr);
 if (dst.m_pStr != NULL)
 delete[] dst.m_pStr;
 dst.m_pStr = pNew;
 dst.m_length = m_length;
}

XString& XString::strCat(const XString& str) //把同类型字符串连接到本对象中
{
 assert(str.m_pStr != NULL); //是空没有意义
 int len = m_length + str.m_length;
 char* pNew = new char[len + 1];
 assert(pNew != NULL);
 strcpy(pNew, m_pStr);
 strcat(pNew, str.m_pStr);
 if (m_pStr != NULL)
 delete[] m_pStr;
 m_pStr = pNew;
 m_length = len;
 return *this;
}

XString& XString::strCat(const char* str) //把字符串常量连接到本对象中
{
 assert(str != NULL);
 int len = m_length + strlen(str);
 char* pNew = new char[len + 1];
 assert(pNew != NULL);
 strcpy(pNew, m_pStr);
 strcat(pNew, str);
 if (m_pStr != NULL)
 delete[] m_pStr;
 m_pStr = pNew;
 m_length = len;
 return *this;
}

XString& XString::append(char ch) //尾部增加一个字符
{
 m_length++;
 char* pNew = new char[m_length + 1];
 assert(pNew != NULL);
 memcpy((void*)pNew, (void*)m_pStr,m_length);
 pNew[m_length - 1] = ch;
 pNew[m_length ] = '\0';
 if (m_pStr != NULL)
 delete[] m_pStr;
 m_pStr = pNew;
 return *this;
}

ostream& operator << (ostream& ot, const XString& xStr) //<<重载 友元函数
{
 ot << xStr.m_pStr;
 return ot;
}

istream& operator >> (istream& it, XString& xStr) //<<重载 友元函数
{
 //尝试实现 带空格的字符串 也能输入,最长输入255
 char ch;
 char str[256] = { 0 };
 int i = 0;
 while (1)
 {
 scanf("%c",&ch); //这里用了scanf... cin不行啊
 if (ch == '\n')
 break;
 str[i++] = ch;
 }
 str[i] = '\0';
 int len = strlen(str); //长度
 char *pNew = new char[len + 1]; //重新分配内存
 assert(pNew != NULL);
 strcpy(pNew, str);
 if (xStr.m_pStr != NULL)
 delete[] xStr.m_pStr;
 xStr.m_length = len; //赋值长度
 xStr.m_pStr = pNew; //赋值指针
 return it;
}

XString& XString::operator = (const XString& other) //=重载,同类赋值
{
 assert(other.m_pStr != NULL);
 char *pNew = new char[other.m_length + 1];
 assert(pNew != NULL);
 strcpy(pNew, other.m_pStr);
 if (m_pStr != NULL)
 delete[] m_pStr;
 m_length = other.m_length;
 m_pStr = pNew;
 return *this; //返回this指向的对象
}

XString& XString::operator = (const char* str) //=重载,字符串常量赋值
{
 assert(str != NULL);
 int len = strlen(str);
 char *pNew = new char[len + 1];
 assert(pNew != NULL);
 strcpy(pNew, str);
 if (m_pStr != NULL)
 delete[] m_pStr;
 m_length = len;
 m_pStr = pNew;
 return *this;
}

char XString::operator [] (int index) //[]重载
{
 return this->m_pStr[index];
}

XString::operator const char* () //()重载 类型强转 转为 const char * 类型
{
 return m_pStr;
}

XString XString::operator + (const XString& str) const //+重载,同类加
{
 XString x;
 x = *this;
 x.strCat(str);
 return x;
}

XString operator +(const XString& str1, const char* str2) //+友元实现 字符串常量相加(与上面不同写法)
{
 XString x;
 x = str1;
 x.strCat(str2);
 return x;
}

XString& XString::operator += (const XString& str) // += 重载 本类对象
{
 this->strCat(str);
 return *this;
}

XString& XString::operator += (const char* str) // += 重载 字符串常量
{
 this->strCat(str);
 return *this;
}

XString& XString::operator ~() //反序字符串
{
 for (int i = 0; i < m_length / 2; ++i)
 {
 char ch;
 ch = m_pStr[i];
 m_pStr[i] = m_pStr[m_length - 1 - i];
 m_pStr[m_length - 1 - i] = ch;
 }
 return *this;
}

bool XString::operator > (const XString& str) const //比较 >
{
 if (strcmp(this->m_pStr, str.m_pStr) > 0)
 return true;
 return false;
}

bool XString::operator > (const char* str) const //比较 >
{
 if (strcmp(this->m_pStr, str) > 0)
 return true;
 return false;
}
bool XString::operator < (const XString& str) const // <
{
 if (strcmp(this->m_pStr, str.m_pStr) < 0)
 return true;
 return false;
}

bool XString::operator < (const char* str) const // <
{
 if (strcmp(this->m_pStr, str) < 0)
 return true;
 return false;
}

bool XString::operator >= (const XString& str) const //比较 >=
{
 if (strcmp(this->m_pStr, str.m_pStr) <= 0)
 return true;
 return false;
}

bool XString::operator >= (const char* str) const //比较 >=
{
 if (strcmp(this->m_pStr, str) >= 0)
 return true;
 return false;
}

bool XString::operator <= (const XString& str) const // <=
{
 if (strcmp(this->m_pStr, str.m_pStr) <= 0)
 return true;
 return false;
}

bool XString::operator <= (const char* str) const // <=
{
 if (strcmp(this->m_pStr, str) >= 0)
 return true;
 return false;
}

bool XString::operator == (const XString& str) const // ==
{
 if (strcmp(this->m_pStr, str.m_pStr) == 0)
 return true;
 return false;
}

bool XString::operator == (const char* str) const // ==
{
 if (strcmp(this->m_pStr, str) == 0)
 return true;
 return false;
}

bool XString::operator != (const XString& str) const // !=
{
 if (strcmp(this->m_pStr, str.m_pStr) != 0)
 return true;
 return false;
}

bool XString::operator != (const char* str) const // !=
{
 if (strcmp(this->m_pStr, str) != 0)
 return true;
 return false;
}
int XString::findStr(const char* str) const //查找字串第一次出现的位置,-1表示没找到
{
 if (NULL == str || strlen(str) > m_length) return -1;
 int len = strlen(str);
 const char* p = m_pStr;
 const char* q = str;
 int i = 0,count = 0;
 while (*p && *q) 
 {
 if (*p == *q)
 {
 ++p;
 ++q;
 ++i;
 if (i == len)
 return count;
 }
 else
 {
 i = 0;
 ++count;
 p = m_pStr + count;
 q = str;
 }
 }//end while
 return -1;
}

int XString::findStr(const XString& str) const //查找字串第一次出现的位置,0表示没找到
{
 return this->findStr(str.m_pStr);
}

int XString::findStrPP(const char* str, XString& res) const //字符串查找,返回值表示 找到的个数,位置存放在引用中
{ //res用来存放 字串出现的位置,比如出现3次分别是 1 4 8,那么res[0]=1 res[1]=4 res[2]=8 返回值是3,返回值0表示没有找到
 if (NULL == str || strlen(str) > m_length) return 0;
 XString tmp = this->m_pStr; //临时对象
 int count = 0;
 int move = 0, pos = 0;
 int absPos;
 while ((pos=tmp.findStr(str)) >= 0)
 {
 ++count;
 absPos = move + pos;
 res.append(absPos);
 move = move + pos + 1;
 if (move < m_length) 
 tmp = this->m_pStr + move;
 else
 break;
 }
 return count;
}

int XString::findStrPP(const XString& str, XString& res) const //字符串查找,返回值表示 找到的个数,位置存放在引用中
{
 return findStrPP(str.m_pStr, res);
}

XString类的测试和调用main.cpp

//main.cpp
//XString 自定义string类的测试和使用
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include "XString.h"
using namespace std;

int main() 
{
 XString x1; //无参构造
 XString x2("abc"); //带参构造
 XString x3('d',10); //10个d的构造
 XString x(x2); //拷贝构造
 cout <<"C风格输出:" << x.c_Str() << " 长度:" << x.getLength() << " 是否为空:" << x.isEmpty() << endl;
 x = "123abc"; //赋值运算符重载
 x = x3;
 cout << "请输入一个字符串(可带空格)输入重载:";
 cin >> x; //输入>>重载,可以获取带空格字符串
 cout << "输出<<重载:" << x << endl; //输出重载
 XString y("123");

 if (x > y) 
 cout << "x=" << x << " y=" << y << " x>y" << endl;
 else
 cout << "x=" << x << " y=" << y << " x<=y" << endl;
 char* p;
 p = const_cast<char*>((const char*)x); //()重载
 cout << "p=" << p << endl;
 x = "abc123";
 y = " 中国 人们";
 x.strCat(y); //连接
 cout << x << endl;
 cout << ~x << endl; //倒序

 x = "12312212";
 y = "2";
 cout << x.findStr(y) << endl; //只查找第一次出现的位置

 //下面是找出所有 y字串 在x 中的位置和出现次数
 XString z;
 cout <<"次数=" <<x.findStrPP(y, z) << endl;
 cout << "z.length="<<z.getLength() << endl;
 for (int i = 0; i < z.getLength(); ++i)
 printf("%d ", z[i]);
 printf("\n");
 return 0;
}

(2017-03-30 www.vsppc.com)

学习笔记未经允许不得转载:PPC的C/C++和人工智能学习笔记 » C++语言基础(11-1)_自己实现string类

分享到:更多 ()

评论 抢沙发

评论前必须登录!