自己实现C++的string类

使用C++的朋友对string类都不会陌生,string类使用起来很是方便,比C的字符数组好用多了,但是我们能不能自己实现一个属于自己的string类呢?

实现一个具有基本功能的string类并不难,但是还是得掌握以下几点知识:构造函数、析构函数、运算符重载、指针、引用等等。

我自己实现了一个string类,一来是想用自己学的知识做一些有实际作用的东西,二则使用自己的东西也很有成就感,现在给大家作为参考,有错误或者不合理的地方欢迎大家指正。

为了区别标准库中的string类和相关标识符,我的类名叫mystring,而相关函数名也大多以这种方式处理,其中每个函数都经过本人测试,在参数合法的前提下均能正常使用,但组合在一起使用的情况则没有进行太多测试。

首先是mystring.h文件

#ifndef MYSTRING_H_INCLUDED
#define MYSTRING_H_INCLUDED

#include <iostream>

using namespace std;

class mystring
{
public:
    mystring();
    mystring(const char * ptr_s);
    mystring(const mystring & refer_str);//拷贝构造函数
    int mylength();//计算字符串的长度
    ~mystring();
    friend istream & operator>>(istream & is, mystring & refer_str);
    friend ostream & operator<<(ostream & os, const mystring & refer_str);
    mystring & operator=(const mystring & refer_str);
    void mygetline();//对输入按行读取
    char & operator[](int n);
    friend mystring operator+(const mystring & refer_str_1, const mystring & refer_str_2);
    mystring & operator+=(const mystring & refer_str);
    friend bool operator==(const mystring & refer_str_1, const mystring & refer_str_2);
    friend bool operator!=(const mystring & refer_str_1, const mystring & refer_str_2);
    mystring mysubstr(int pos, int posn);//计算一个字符串的子串,pos为起始位置,从0开始,posn为希望求得的子串的长度
    friend void mystrswap(mystring & str1, mystring & str2);//交换两个字符串
    int myfind(char ch, int pos = 0);//从pos开始查找字符ch在当前字符串中的位置,pos从0开始,返回值也从0开始
    mystring & myerase(int pos, int posn);//从pos开始删除当前字符串中的字符,pos从0开始,posn表示希望删除的字符数量,返回删除后字符串的引用,也即当前字符串
    mystring & myinsert(int pos, const mystring & refer_str);//将refer_str代表的字符串插入到当前字符串中,pos表示插入的位置,0 <= pos <= mystrlen((*this).ptr_s)
    mystring & myinsert(int pos, const mystring & refer_str, int posn);//将refer_str代表的字符串插入到当前字符串中,pos表示插入的位置,0 <= pos <= mystrlen((*this).ptr_s),0 <= posn <= mystrlen(refer_str.ptr_s)
private:
    char * ptr_s;
};

int mystrlen(const char * ptr_s);//计算字符串的长度
void mystrcpy(char * ptr_s_1, const char * ptr_s_2);//将ptr_s_2指向的内容复制到ptr_s_1所指向的空间,但前提后者空间足够
int mystrcmp(const char * ptr_s_1, const char * ptr_s_2);//比较ptr_s_1指向的内容和ptr_s_2指向的内容,若两者相同返回0,前者大返回1,前者小返回-1
void mystrcat(char * ptr_s_1, const char * ptr_s_2);//将ptr_s_2指向的内容连接到ptr_s_1指向的内容的后面,但需保证ptr_s_1所指向的空间足够,并且ptr_s_1所指向的空间必须经过初始化,即包含有意义的字符串结束符\0

#endif // MYSTRING_H_INCLUDED

我的想法是尽量不使用标准库,但为了重载>>和<<这两个运算符并实现mygetline()函数,还是得在mystring.h中包含iostream。

然后是mystring.cpp文件

#include "mystring.h"

mystring::mystring()
{
    ptr_s = new char[1];
    *ptr_s = ‘\0‘;
}

mystring::mystring(const char * ptr_s)
{
    this->ptr_s = new char[mystrlen(ptr_s)+1];
    mystrcpy(this->ptr_s, ptr_s);
}

mystring::mystring(const mystring & refer_str)
{
    ptr_s = new char[mystrlen(refer_str.ptr_s)+1];
    mystrcpy(ptr_s, refer_str.ptr_s);
}

int mystring::mylength()
{
    return mystrlen(ptr_s);
}

mystring::~mystring()
{
    delete [] ptr_s;
}

istream & operator>>(istream & is, mystring & refer_str)
{
    delete [] refer_str.ptr_s;
    char ch_tmp[1000];// 申请一块在一般情况下足够大的内存
    is >> ch_tmp;
    refer_str.ptr_s = new char[mystrlen(ch_tmp)+1];
    mystrcpy(refer_str.ptr_s, ch_tmp);
    return is;
}

ostream & operator<<(ostream & os, const mystring & refer_str)
{
    os << refer_str.ptr_s;
    return os;
}

mystring & mystring::operator=(const mystring & refer_str)
{
    if(this == &refer_str)
        return *this;
    else
    {
        delete [] ptr_s;
        ptr_s = new char[mystrlen(refer_str.ptr_s)+1];
        mystrcpy(ptr_s, refer_str.ptr_s);
        return *this;
    }
}

void mystring::mygetline()
{
    delete [] ptr_s;
    char ch_tmp[1000];// 申请一块在一般情况下足够大的内存
    cin.getline(ch_tmp, 1000);
    ptr_s = new char[mystrlen(ch_tmp)+1];
    mystrcpy(ptr_s, ch_tmp);
}

char & mystring::operator[](int n)
{
    return *(ptr_s+n);
}

mystring operator+(const mystring & refer_str_1, const mystring & refer_str_2)
{
    mystring str_tmp;
    str_tmp.ptr_s = new char[mystrlen(refer_str_1.ptr_s)+mystrlen(refer_str_2.ptr_s)+1];
    mystrcpy(str_tmp.ptr_s, refer_str_1.ptr_s);
    mystrcpy(str_tmp.ptr_s+mystrlen(refer_str_1.ptr_s), refer_str_2.ptr_s);
    return str_tmp;
}

mystring & mystring::operator+=(const mystring & refer_str)
{
    mystring str_tmp;
    str_tmp.ptr_s = new char[mystrlen(ptr_s)+mystrlen(refer_str.ptr_s)+1];
    mystrcpy(str_tmp.ptr_s, ptr_s);
    mystrcpy(str_tmp.ptr_s+mystrlen(ptr_s), refer_str.ptr_s);
    delete [] ptr_s;
    ptr_s = new char[mystrlen(str_tmp.ptr_s)+1];
    mystrcpy(ptr_s, str_tmp.ptr_s);
    return *this;
}

bool operator==(const mystring & refer_str_1, const mystring & refer_str_2)
{
    int ret = mystrcmp(refer_str_1.ptr_s, refer_str_2.ptr_s);
    if(ret == 0)
        return true;
    else
        return false;
}

bool operator!=(const mystring & refer_str_1, const mystring & refer_str_2)
{
    int ret = mystrcmp(refer_str_1.ptr_s, refer_str_2.ptr_s);
    if(ret == 0)
        return false;
    else
        return true;
}

mystring mystring::mysubstr(int pos, int posn)
{
    mystring str_tmp;
    delete [] str_tmp.ptr_s;
    str_tmp.ptr_s = new char[posn+1];
    for(int i = 0;i < posn;i++)
        *(str_tmp.ptr_s+i) = *(ptr_s+pos+i);
    *(str_tmp.ptr_s+posn) = ‘\0‘;
    return str_tmp;
}

void mystrswap(mystring & str1, mystring & str2)
{
    char * ptr_s;
    ptr_s = str1.ptr_s;
    str1.ptr_s = str2.ptr_s;
    str2.ptr_s = ptr_s;
}

int mystring::myfind(char ch, int pos)
{
    int str_length = mystrlen(ptr_s);
    int i;
    for(i = 0;i < str_length-pos;i++)
        if(*(ptr_s+pos+i) == ch)
            return pos+i;
    return -1;
}

mystring & mystring::myerase(int pos, int posn)
{
    mystring str_tmp;
    delete [] str_tmp.ptr_s;
    int str_length = mystrlen(ptr_s);
    str_tmp.ptr_s = new char[str_length-posn+1];
    for(int i = 0;i < pos;i++)
        *(str_tmp.ptr_s+i) = *(ptr_s+i);
    for(int i = pos+posn;i < str_length;i++)
        *(str_tmp.ptr_s+i-posn) = *(ptr_s+i);
    *(str_tmp.ptr_s+str_length-posn) = ‘\0‘;
    char * ptr_s_tmp;
    ptr_s_tmp = str_tmp.ptr_s;
    str_tmp.ptr_s = ptr_s;
    ptr_s = ptr_s_tmp;
    return *this;
}

mystring & mystring::myinsert(int pos, const mystring & refer_str)
{
    mystring str_tmp;
    delete [] str_tmp.ptr_s;
    int str_length_1 = mystrlen(ptr_s);
    int str_length_2 = mystrlen(refer_str.ptr_s);
    str_tmp.ptr_s = new char[str_length_1+str_length_2+1];
    int i;
    for(i = 0;i < pos;i++)
        *(str_tmp.ptr_s+i) = *(ptr_s+i);
    mystrcpy(str_tmp.ptr_s+i, refer_str.ptr_s);
    while(i < str_length_1)
    {
        *(str_tmp.ptr_s+str_length_2+i) = *(ptr_s+i);
        i++;
    }
    *(str_tmp.ptr_s+str_length_1+str_length_2) = ‘\0‘;
    char * ptr_s_tmp;
    ptr_s_tmp = str_tmp.ptr_s;
    str_tmp.ptr_s = ptr_s;
    ptr_s = ptr_s_tmp;
    return *this;
}

mystring & mystring::myinsert(int pos, const mystring & refer_str, int posn)
{
    mystring str_tmp;
    delete [] str_tmp.ptr_s;
    int str_length = mystrlen(ptr_s);
    str_tmp.ptr_s = new char[str_length+posn+1];
    int i;
    for(i = 0;i < pos;i++)
        *(str_tmp.ptr_s+i) = *(ptr_s+i);
    for(int j = 0;j < posn;j++)
        *(str_tmp.ptr_s+pos+j) = *(refer_str.ptr_s+j);
    while(i < str_length)
    {
        *(str_tmp.ptr_s+posn+i) = *(ptr_s+i);
        i++;
    }
    *(str_tmp.ptr_s+str_length+posn) = ‘\0‘;
    char * ptr_s_tmp;
    ptr_s_tmp = str_tmp.ptr_s;
    str_tmp.ptr_s = ptr_s;
    ptr_s = ptr_s_tmp;
    return *this;
}

int mystrlen(const char * ptr_s)
{
    int length = 0;
    while(*(ptr_s++) != ‘\0‘)
        length++;
    return length;
}

void mystrcpy(char * ptr_s_1, const char * ptr_s_2)
{
    while(*ptr_s_2 != ‘\0‘)
    {
        *ptr_s_1 = *ptr_s_2;
        ptr_s_1++;
        ptr_s_2++;
    }
    *ptr_s_1 = ‘\0‘;
}

int mystrcmp(const char * ptr_s_1, const char * ptr_s_2)
{
    int length_1 = mystrlen(ptr_s_1);
    int length_2 = mystrlen(ptr_s_2);
    int length_shorter = length_1 > length_2 ? length_2 : length_1;
    int i;
    for(i = 0;i < length_shorter;i++)
        if(*(ptr_s_1+i) != *(ptr_s_2+i))
            break;
    if(i == length_shorter)
    {
        if(length_1 == length_2)
            return 0;
        else if(length_1 > length_2)
            return 1;
        else
            return -1;
    }
    else
    {
        if(*(ptr_s_1+i) > *(ptr_s_2+i))
            return 1;
        else
            return -1;
    }
}

void mystrcat(char * ptr_s_1, const char * ptr_s_2)
{
    ptr_s_1 += mystrlen(ptr_s_1);
    while(*ptr_s_2 != ‘\0‘)
    {
        *ptr_s_1 = *ptr_s_2;
        ptr_s_1++;
        ptr_s_2++;
    }
    *ptr_s_1 = ‘\0‘;
}

实现时很多地方用到了指针,指针确实非常强大。

这样只要将这两个文件放在目标工程文件夹里,并且在开头加上

#include "mystring.h"

就可以使用自己的string类了,如果自己需要什么个性化的功能,还可以自由添加修改。

时间: 2024-10-08 09:47:59

自己实现C++的string类的相关文章

java String 类 基础笔记

字符串是一个特殊的对象. 字符串一旦初始化就不可以被改变. String s = "abc";//存放于字符串常量池,产生1个对象 String s1=new String("abc");//堆内存中new创建了一个String对象,产生2个对象 String类中的equals比较字符串中的内容. 常用方法: 一:获取 1.获取字符串中字符的个数(长度):length();方法. 2.根据位置获取字符:charAt(int index); 3.根据字符获取在字符串中

String类实现

String类是应用框架中不可或缺的类 重载运算符实现字符串的操作 #idndef IOTECK_STRING_H_#define IOTECK_STRING_H_namespace iotek{ class String { public: String(const char*=NULL); ~String(); String(const String&); //拷贝构造函数 //String a; a=b; String& operator=(const String &);

String类

一.概述 Sting s1 = "abc";    //s1是一个类类型变量,"abc"是一个对象. String s2 = new String("abc"); //s1 . s2 的区别: 前者在内存中有一个对象,后者在内存中有两个对象. s1.equals(s2) 为true  因为 String复写了equals方法 二.常见的功能-获取和判断 获取: 1.int length(); 获取长度 2.char chatAt(int inde

C++实现String类

这是一道十分经典的面试题,可以短时间内考查学生对C++的掌握是否全面,答案要包括C++类的多数知识,保证编写的String类可以完成赋值.拷贝.定义变量等功能. #include<iostream> using namespace std; class String { public: String(const char *str=NULL); String(const String &other); ~String(void); String &operator =(cons

java中String类的构造函数

String类中的构造函数String(); 构造一个空字符串对象String(byte[] bytes); 通过byte数组构造字符串对象String(byte[] bytes,int offset,int length);通过byte数组,从offset开始,总共length长的字节构造字符串对象String(char[] value); 通过char数组构造字符串对象String(byte[] char,int offset,int length);通过char数组,从offset开始,总

Java (六、String类和StringBuffer)

Java String 类 字符串广泛应用 在Java 编程中,在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串. 创建字符串 // ==比较的是字符串在栈中存放的首地址,而equals()比较的是两个字符串的内容是否相同 //普通的声明字符串的方法,只会在字符串常量池里开辟空间,并且开辟空间之前,会检查字符串常量池里是否已存在 //相同的数据,如果有,直接指向已存在的数据,如果没有会在字符串常量池里开辟一个新的空间 String s = "ccy"

JAVA API(一)String类和StringBuffer类

1.String类和StringBuffer类 在程序中经常会用到字符串,所谓的字符串就是指一连串的字符,它是由多个单个字符连接而成的.字符串中可以包含任意字符,这些字符必须包含在一对双引号""之内,如"abc".在Java中定义了String和StringBuffer类来封装字符串,并提供了一系列操作字符串的方法,它们都位于java.lang包中,因此不需要导包就可以直接使用.下面将对String类和StringBuffer类详细讲解. 1.1String类的初始

String类replaceAll方法正则替换深入分析

作者网址: https://my.oschina.net/shipley/blog/98973 背景:      前几天有人发了一个关于下面问题的贴,对这个有点好奇,故花时间做了点研究.        对单个反斜杠字符串替换成双斜杠的Java实现如下:    String s = "\\";    方法一:String sr1 = s.replaceAll("\\\\", "\\\\\\\\");    方法二:String sr1 = s.re

java11-3 String类的获取功能

package cn_String2;/* String类的获取功能 int length():获取字符串的长度. char charAt(int index):获取指定索引位置的字符 int indexOf(int ch):返回指定字符在此字符串中第一次出现处的索引. 为什么这里是int类型,而不是char类型? 原因是:'a'和97其实都可以代表'a' int indexOf(String str):返回指定字符串在此字符串中第一次出现处的索引. int indexOf(int ch,int

C++的string类

关于头文件cstring,提供了strlen及很多与字符串相关的函数的声明. 头文件string,要使用string类,必须在程序中包含头文件string,string类位于std中,必须提供一条using编译指令,或者使用std::string来引用它. 1.string类的使用: 不能将一个数组赋给另一个数组,但可以将一个string对象赋给另一个string对象. size()是string类的一个方法.可以将C++里边的string类理解成类型,我觉的可以理解成,创建:一个新类型,就像j