热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

怎么利用C++实现Mystring类

这篇文章主要介绍“怎么利用C++实现Mystring类”,在日常操作中,相信很多人在怎么利用C++实现Mystring类问题上存在疑惑,小编查阅了各式资料,整

这篇文章主要介绍“怎么利用C++实现Mystring类”,在日常操作中,相信很多人在怎么利用C++实现Mystring类问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎么利用C++实现Mystring类”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

功能实现

<基本功能>

1> 实现头文件的封装:MyString.h

2> 缺省构造函数对字符串的初始化( MyString() )

3> 使用构造函数初始化字符串的另外两种方式 * 2( 动态指针+拷贝构造函数 )

4> 析构函数( 释放动态申请的字符串空间 )

5> 重载输出运算符( <<)

6> 重载赋值运算符 * 2( = )

7> 重载下标运算符( [],索引输出 )

<拓展功能>

1> 字符串长度的比较

2> 字符串的排序功能

3> 字符串的倒置

4> 字符串中指定两个字符的交换

5> 查找某字符串是否位于指定的字符串中(采用暴力查找)

<细节修改>

1> 使用自定义函数来替换strlen()和strcpy()

一: 基本功能 (实现源码)

1) MyString.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
 
#include 
#include     //会借用strlen与strcpy函数实现相应的功能
using namespace std;
 
class MyString {
public:
    MyString();
    MyString(const char *const);
    MyString(const MyString &);
    ~MyString();
    int length()const;    //const函数不能修改其数据成员,仅仅起到输出数据的作用
    int size() const;    //和length功能一致
    const char * getString() const;    //直接调用字符串首指针返回
    friend ostream & operator << (ostream &, const MyString &);    //重载输出运算符
    MyString & operator = (const MyString &);
    MyString & operator = (const char *    );
    char & operator [] (const int index);
 
private:
    char * str;    //指向数组首地址(此时为野指针)
    int len;
 
};

2)MyString.cpp

#include "MyString.h"
using namespace std;
 
MyString::MyString()    //构造空字符串
{
    str = new char[1];
    str[0] = &#39;\0&#39;;
    len = 0;
}
 
MyString::MyString(const char * const P)    //按照动态指针来构造相应的字符串
{
    if (P)
    {
        len = strlen(P);    //取长度
        str = new char[len + 1];    //开空间
        strcpy(str, P);    //复制值
    }
    else
    {
        MyString();    //如果传入的字符串为空,直接调用缺省值构造函数
    }
}
 
MyString::MyString(const MyString & AnotherMyString)  //拷贝构造函数,这里的形参使用了const,该形参类中的所有函数都要使用const来修饰
{
    len = AnotherMyString.length();
    str = new char[len + 1];
    strcpy(str, AnotherMyString.str);
}
 
int MyString::length() const   //求长度成员函数
{
    return len;
}
 
int MyString::size() const
{
    return len;
}
 
const char * MyString::getString()const
{
    return str;
}
 
MyString & MyString::operator=(const MyString &AnotherMyString)
{
    if (&AnotherMyString == this)
    {
        return *this;
    }
    delete[] str;
    len = AnotherMyString.length();
    str = new char[len + 1];
    strcpy(str, AnotherMyString.str);
    return *this;
    // TODO: 在此处插入 return 语句
}
 
MyString & MyString::operator=(const char * P)
{
    delete[] str;
    len = strlen(P);
    str = new char[len + 1];
    strcpy(str, P);
    return *this;
    // TODO: 在此处插入 return 语句
}
 
char & MyString::operator[](const int index)
{
    if (index > len)    //如果索引越界,输出最后一个字符
    {
        cout << "Warning!!!" << endl;
        cout << "Out of boundary! The last char is: ";
        return str[len - 1];
    }
    else
    {
        return str[index-1];
    }
    // TODO: 在此处插入 return 语句
}
 
MyString::~MyString()    //释放数组空间
{
    delete[] str;
    len = 0;
}
 
ostream & operator << (ostream & output, const MyString & str)    //重载输出运算符
{
    output << str.getString();
    return output;
    // TODO: 在此处插入 return 语句
}

这里需要提到的一点是析构函数中的delete[] str;

怎么利用C++实现Mystring类

 

使用new得来的空间使用delete释放;使用new[]得来的空间使用delete[]释放;这是永远不会错的。

但是更加深入一点去理解:

使用new[]得到的空间如果 动态申请的数据类型时基本数据类型也可以使用delete直接释放,但是如果使用new[]申请的数据的类型时自定义类型(例如类名),这就必须使用delete[]来进行释放,只有这样才能够调用自定义类型的析构函数进行对自定义类型进行释放。

除此之外,再提一点关于delete[]的注意事项:

当使用new[]动态生成内存的时候,删除的时候必须将删除的指针指向new[]出来的内存的首地址:

#include 
using namespace std;
 
int main()
{
    int *p = new int[3];
    *p = 1;
    p++;
    *p = 2;
    delete[]p;
    cout << "*" << endl;
    return 0;
}

这一段小程序中:

因为p指针不是指向了首地址,所以程序虽然没报错,但是无法正常运行!我们可以将申请的首地址保存起来,供删除的时候使用。

3)test_main.cpp

#include "MyString.h"
using namespace std;
 
int main()
{
    MyString a;
    cout << "【调用缺省构造函数实现初始化】" << endl;
    cout << "string a = " << a << endl;
    cout << "Length = " << a.length() << endl << endl;
 
    MyString b("123456");
    cout << "【调用普通构造函数实现初始化】" << endl;
    cout << "string b = " << b << endl;
    cout << "Length = " << b.length() << endl << endl;
 
    MyString c(b);
    cout << "【调用拷贝构造函数实现初始化】" << endl;
    cout << "string c = " << c << endl;
    cout << "Length = " << c.length() << endl << endl;
 
    MyString d = b;    //这里不会再次调用缺省构造函数进行初始化
    cout << "【调用 =(对象) 实现赋值】" << endl;
    cout << "string d = " << d << endl;
    cout << "Length = " << d.length() << endl << endl;
 
    MyString e = "00000000";
    cout << "【调用 =(动态指针) 实现赋值】" << endl;
    cout << "string d = " << e << endl;
    cout << "Length = " << e.length() << endl << endl;
 
    MyString f = "abcdefghijklmn";
    char str = f[5];
    cout << "【调用 []  实现索引定位输出】" << endl;
    cout << "f[5] = " << str << endl << endl;
 
    return 0;
}

二:拓展功能

字符串长度的比较

使用/>=/<=等符号进行比较,返回bool值

  • bool operator >(const MyString &str);

  • bool operator >(const char * c_str);

  • bool operator <(const MyString &str);

  • bool operator <(const char * c_str);

  • bool operator >=(const MyString &str);

  • bool operator >=(const char * c_str);

  • bool operator <=(const MyString &str);

  • bool operator <=(const char * c_str);

字符串的排序功能

使用类中的成员函数对类中的私有字符串进行从小到大的排序:

  • A.Sort_String_LB();

  • A.Sort_String_BL();

字符串的倒置

使用类中的成员函数对类中的私有字符串进行倒置:

A.Reverse();

字符串中指定两个字符的交换

A.ChangeTwoCharPosition(int firstposition,int second position);

查找某字符串是否位于指定的字符串中(采用暴力查找)

A.Find(char *search_string);

完整版源码

MyString.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
 
#include 
#include     //会借用strlen与strcpy函数实现相应的功能
using namespace std;
 
class MyString {
public:
    //构造函数+析构函数
    MyString();
    MyString(const char *const);
    MyString(const MyString &);
    ~MyString();
 
    //直接调用字符串首指针返回,返回的指针可以直接使用cout<<输出
    const char * getString() const;    
 
    //求字符串的长度(直接返回类中的私有成员len的值)
    //const函数不能修改其数据成员,仅仅起到输出数据的作用
    int length()const;    
    int size() const;   
 
    //重载赋值运算符,使得可以使用对象与"xxxxxx"来赋值
    MyString & operator = (const MyString &);
    MyString & operator = (const char *    );
 
    //重载下标运算符
    char & operator [] (const int index);
 
    //重载输出运算符
    friend ostream & operator << (ostream &, const MyString &);    
 
    //字符串长度比较
    bool operator >(const MyString &str);
    bool operator >(const char * c_str);
    bool operator <(const MyString &str);
    bool operator <(const char * c_str);
    bool operator >=(const MyString &str);
    bool operator >=(const char * c_str);
    bool operator <=(const MyString &str);
    bool operator <=(const char * c_str);
 
    //字符串内部内容的冒泡排序(ASCII码),Little->Big
    void Sort_String_LB();
    void Sort_String_BL();
 
    //对字符串进行倒置
    void Reverse();
 
    //交换字符串中两个字符的位置
    void ChangeTwoCharPosition(int firstposition, int secondposition);
 
    //查询某字符串是否是指定字符串的子串(暴力模式)
    bool Find(char *search_string);
 
private:
    char * str;    //指向数组首地址(此时为野指针)
    int len;    //字符串的长度
 
};

MyString.cpp

#include "MyString.h"
using namespace std;
 
MyString::MyString()    //构造空字符串
{
    str = new char[1];
    str[0] = &#39;\0&#39;;
    len = 0;
}
 
MyString::MyString(const char * const P)    //按照动态指针来构造相应的字符串
{
    if (P)
    {
        len = strlen(P);    //取长度
        str = new char[len + 1];    //开空间
        strcpy(str, P);    //复制值
    }
    else
    {
        MyString();    //如果传入的字符串为空,直接调用缺省值构造函数
    }
}
 
MyString::MyString(const MyString & AnotherMyString)  //拷贝构造函数,这里的形参使用了const,该形参类中的所有函数都要使用const来修饰
{
    len = AnotherMyString.length();
    str = new char[len + 1];
    strcpy(str, AnotherMyString.str);
}
 
int MyString::length() const   //求长度成员函数
{
    return len;
}
 
int MyString::size() const
{
    return len;
}
 
const char * MyString::getString()const
{
    return str;
}
 
MyString & MyString::operator=(const MyString &AnotherMyString)
{
    if (&AnotherMyString == this)
    {
        return *this;
    }
    //delete[] str;
    len = AnotherMyString.length();
    str = new char[len + 1];
    strcpy(str, AnotherMyString.str);
    return *this;
    // TODO: 在此处插入 return 语句
}
 
MyString & MyString::operator=(const char * P)
{
    //delete[] str;
    len = strlen(P);
    str = new char[len + 1];
    strcpy(str, P);
    return *this;
    // TODO: 在此处插入 return 语句
}
 
char & MyString::operator[](const int index)
{
    if (index > len)    //如果索引越界,输出最后一个字符
    {
        cout << "Warning!!!" << endl;
        cout << "Out of boundary! The last char is: ";
        return str[len - 1];
    }
    else
    {
        return str[index-1];
    }
    // TODO: 在此处插入 return 语句
}
 
bool MyString::operator>(const MyString & str)
{
    if (this->len > str.len)
    {
        return true;
    }
    else
    {
        return false;
    }
    return false;
}
 
bool MyString::operator>(const char * c_str)
{
    if (this->len > int (strlen(c_str)))
    {
        return true;
    }
    else
    {
        return false;
    }
    return false;
}
 
bool MyString::operator<(const MyString & str)
{
    if (this->len < str.len)
    {
        return true;
    }
    else
    {
        return false;
    }
    return false;
}
 
bool MyString::operator<(const char * c_str)
{
    if (this->len < int(strlen(c_str)))
    {
        return true;
    }
    else
    {
        return false;
    }
    return false;
}
 
bool MyString::operator>=(const MyString & str)
{
    if (this->len > str.len)
    {
        return true;
    }
    else if (this->len = str.len)
    {
        return true;
    }
    else
    {
        return false;
    }
    return false;
}
 
bool MyString::operator>=(const char * c_str)
{
    if (this->len > int(strlen(c_str)))
    {
        return true;
    }
    else if (this->len = strlen(c_str))
    {
        return true;
    }
    else
    {
        return false;
    }
    return false;
}
 
bool MyString::operator<=(const MyString & str)
{
    if (this->len < str.len)
    {
        return true;
    }
    else if (this->len = str.len)
    {
        return true;
    }
    else
    {
        return false;
    }
    return false;
}
 
bool MyString::operator<=(const char * c_str)
{
    if (this->len > int (strlen(c_str)))
    {
        return true;
    }
    else if (this->len = strlen(c_str))
    {
        return true;
    }
    else
    {
        return false;
    }
    return false;
}
 
void MyString::Sort_String_LB()
{
    int length = this->len;
    char temp_data;
    char *c_str = this->str;
    bool ischanged = false;
    for (int i = length-1; i > 0; i--)
    {
        for (int j = 0; j < i; j++)
        {
            if (c_str[j] > c_str[j + 1])
            {
                temp_data = c_str[j];
                c_str[j] = c_str[j + 1];
                c_str[j + 1] = temp_data;
                ischanged = true;
            }
        }
        if (!ischanged)
        {
            return;
        }
    }
}
 
void MyString::Sort_String_BL()
{
    int length = this->len;
    char temp_data;
    char *c_str = this->str;
    bool ischanged = false;
    for (int i = length - 1; i > 0; i--)
    {
        for (int j = 0; j < i; j++)
        {
            if (c_str[j] < c_str[j + 1])
            {
                temp_data = c_str[j];
                c_str[j] = c_str[j + 1];
                c_str[j + 1] = temp_data;
                ischanged = true;
            }
        }
        if (!ischanged)
        {
            return;
        }
    }
}
 
void MyString::Reverse()
{
    int length = this->len;
    char *c_str = this->str;
    char temp_data;
    for (int i = 0; i < length/2; i++)
    {
        temp_data = c_str[i];
        c_str[i] = c_str[length-1-i];
        c_str[length-1-i] = temp_data;
    }
}
 
void MyString::ChangeTwoCharPosition(int firstposition, int secondposition)
{
    int length = this->len;
    char *c_str = this->str;
    char temp_data;
    if (firstposition > len || secondposition > len)
    {
        cout << "输入下标越界,数组实际长度为: " << length << endl;
        return;
    }
    else
    {
        temp_data = c_str[firstposition-1];
        c_str[firstposition-1] = c_str[secondposition-1];
        c_str[secondposition-1] = temp_data;
    }
}
 
bool MyString::Find(char * search_string)   
{
    int length = this->len;
    char *c_str = this->str;
    bool judge = false;
    //确保i每次可以往后移动一位
    int temp_data=0;
 
    for (int i = 0,j=0; j < strlen(search_string)&&i

Test_Possess.cpp

#include "MyString.h"
using namespace std;
 
int main()
{
    MyString a;
    cout << "【调用缺省构造函数实现初始化】" << endl;
    cout << "string a = " << a << endl;
    cout << "Length = " << a.length() << endl << endl;
 
    MyString b("123456");
    cout << "【调用普通构造函数实现初始化】" << endl;
    cout << "string b = " << b << endl;
    cout << "Length = " << b.length() << endl << endl;
 
    MyString c(b);
    cout << "【调用拷贝构造函数实现初始化】" << endl;
    cout << "string c = " << c << endl;
    cout << "Length = " << c.length() << endl << endl;
 
    MyString d = b;    //这里不会再次调用缺省构造函数进行初始化
    cout << "【调用 =(对象) 实现赋值】" << endl;
    cout << "string d = " << d << endl;
    cout << "Length = " << d.length() << endl << endl;
 
    MyString e = "00000000";
    cout << "【调用 =(动态指针) 实现赋值】" << endl;
    cout << "string d = " << e << endl;
    cout << "Length = " << e.length() << endl << endl;
 
    MyString f = "abcdefghijklmn";
    char str = f[5];
    cout << "【调用 []  实现索引定位输出】" << endl;
    cout << "f[5] = " << str << endl << endl;
 
    //测试字符串的大小比较功能
    MyString A1 = "123456789";
    MyString B1 = "4321";
    MyString C1 = "456";
    MyString D1 = "456789";
    if (A1 >= B1)
    {
        cout << "A1>=B1" << endl;
    }
    else
    {
        cout << "A1

三:细节部分修改

本次更新了 "取消了strlen()与strcpy()的使用,在间接调用该接口的自定义函数中,使用自定义方法实现这两个接口的功能" 

这里仅仅给出了替换部分部分示例,其他部分也可按照相同原理替换:

1.使用指针实例化对象部分

MyString::MyString(char * P)    //按照动态指针来构造相应的字符串
{
    char * temp_P = P;   //使得指针指向的内存重置
    if (P)
    {
        int xx_length = 0;
        while (*P != &#39;\0&#39;)
        {
            xx_length++;
            P = P + sizeof(char);
        }
        len = xx_length;
        P = temp_P;
        //len = strlen(P);    //取长度
        str = new char[len + 1];    //开空间
        strcpy(str, P);    //复制值
    }
    else
    {
        MyString();    //如果传入的字符串为空,直接调用缺省值构造函数
    }
}

2.重载 "=" 运算符函数的过程

MyString & MyString::operator=(char * P)
{
    //delete[] str;
    char *temp_P = P;
    int xx_length = 0;
    char temp = &#39;0&#39;;
    while (*P != &#39;\0&#39;)
    {
        xx_length++;
        P = P + sizeof(char);
    }
    //len = strlen(P);
    len = xx_length;
    P = temp_P;
    str = new char[len + 1];
    for (int i = 0; i < len; i++)
    {
        *str = *P;
        str += sizeof(char);
        P += sizeof(char);
    }
    //strcpy(str, P);
    return *this;
    // TODO: 在此处插入 return 语句
}

( 附加:对于自定义的类,需要尽量减少对其他头文件的需求。)

到此,关于“怎么利用C++实现Mystring类”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程笔记网站,小编会继续努力为大家带来更多实用的文章!


推荐阅读
  • 本文介绍了在Cpp中将字符串形式的数值转换为int或float等数值类型的方法,主要使用了strtol、strtod和strtoul函数。这些函数可以将以null结尾的字符串转换为long int、double或unsigned long类型的数值,且支持任意进制的字符串转换。相比之下,atoi函数只能转换十进制数值且没有错误返回。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
  • 本文介绍了一个题目的解法,通过二分答案来解决问题,但困难在于如何进行检查。文章提供了一种逃逸方式,通过移动最慢的宿管来锁门时跑到更居中的位置,从而使所有合格的寝室都居中。文章还提到可以分开判断两边的情况,并使用前缀和的方式来求出在任意时刻能够到达宿管即将锁门的寝室的人数。最后,文章提到可以改成O(n)的直接枚举来解决问题。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • c语言\n不换行,c语言printf不换行
    本文目录一览:1、C语言不换行输入2、c语言的 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 本文介绍了解决二叉树层序创建问题的方法。通过使用队列结构体和二叉树结构体,实现了入队和出队操作,并提供了判断队列是否为空的函数。详细介绍了解决该问题的步骤和流程。 ... [详细]
  • 本文介绍了UVALive6575题目Odd and Even Zeroes的解法,使用了数位dp和找规律的方法。阶乘的定义和性质被介绍,并给出了一些例子。其中,部分阶乘的尾零个数为奇数,部分为偶数。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
  • 本文整理了Java中java.lang.NoSuchMethodError.getMessage()方法的一些代码示例,展示了NoSuchMethodErr ... [详细]
author-avatar
beitianmolang
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有