C++实现string类

C++实现string类

string类相比于char*的字符串,在使用中不必担心内存是否足够、字符串长度等等。作为一个类出现,它集成的操作函数足以完成我们大多数情况下的需要。我们可以用 = 进行赋值操作,== 进行比较,+ 做串联等。

C++提供的string类基本满足开发需要,而自己实现string类多在面试题中出现。限于时间,不可能要求具备 std::string 的功能,但至少要求能正确管理资源。

函数声明函数功能
String(const char *str = nullptr);构造函数
String(const String &that);拷贝构造函数
~String(void);析构函数
String &operator=(const String &that);赋值运算符
String operator+(const String &that) const;字符串连接
bool operator==(const String &that) const;判断相等
char operator[](int index) const;数组索引
int length(void) const;返回字符串长度
char *c_str(void) const;返回C风格的字符串
String &exchange(void);字符串逆序
friend ostream &operator<<(ostream &os, const String &that);标准输出
friend istream &operator>>(istream &is, String &that);标准输入

构造函数和析构函数

代码如下

String::String(const char *pstr)
{
    m_pstr = new char[strlen(pstr?pstr:"") + 1];
    strcpy(m_pstr, pstr?pstr:"");
}

String::String(const String &that)
{
    m_pstr = new char[strlen(that.m_pstr) + 1];
    strcpy(m_pstr, that.m_pstr);
}

String::~String(void)
{
    if (m_pstr) {
        delete[] m_pstr;
        m_pstr = nullptr;
    }
}

自己实现的String类只维护char *m_pstr一个成员参数,构造函数类内声明有默认参数nullptr,使用三目运算符(? : )判断。构造函数里调用new [],析构函数里必须调用delete []。释放内存后须将m_pstr指向空。

重载函数

代码如下

String &String::operator=(const String &that)
{
    if (&that != this) {
        delete[] m_pstr;
        m_pstr = new char[strlen(that.m_pstr) + 1];
        strcpy(m_pstr, that.m_pstr);
    }
    return *this;
}

String String::operator+(const String &that) const
{
    String newString;
    if (!that.m_pstr) {
        newString = *this;
    } else if (!this->m_pstr) {
        newString = that;
    } else {
        newString.m_pstr = new char[strlen(this->m_pstr) +
                                    strlen(that.m_pstr) + 1];
        strcpy(newString.m_pstr, this->m_pstr);
        strcat(newString.m_pstr, that.m_pstr);
    }
    return newString;
}

bool String::operator==(const String &that) const
{
    if (strlen(this->m_pstr) != strlen(that.m_pstr)) {
        return false;
    } else {
        return strcmp(this->m_pstr, that.m_pstr)?false:true;
    }
}

char String::operator[](int index) const
{
    if (index > 0 && index < strlen(this->m_pstr)) {
        return this->m_pstr[index];
    } else {
        return '\0';
    }
}

ostream &operator<<(ostream &os, const String &that)
{
    os << that.m_pstr;
    return os;
}

istream &operator>>(istream &is, String &that)
{
    is >> that.m_pstr;
    return is;
}

重载 = 运算符时须注意深、浅拷贝问题。在申请新的内存之前必须释放旧内存,防止内存泄漏。重载 + 运算符时判断其中一个字符串是否为空,增加代码运行效率。重载 [] 运算符时要注意不能访问越界。

功能函数

代码如下

int String::length(void) const
{
    return strlen(this->m_pstr);
}

char *String::c_str(void) const
{
    return this->m_pstr;
}

String &String::exchange(void)
{
    for (int i = 0; i < strlen(m_pstr) / 2; i++) {
        m_pstr[i] ^= m_pstr[strlen(m_pstr) - i - 1];
        m_pstr[strlen(m_pstr) - i - 1] ^= m_pstr[i];
        m_pstr[i] ^= m_pstr[strlen(m_pstr) - i - 1];
    }
    return *this;
}

功能函数大体是对C风格的函数进行封装,方法、种类很多,这里不做过多介绍。

完整源代码

string.h

#ifndef __STRING_H
#define __STRING_H

#include <iostream>
using namespace std;

class String {
    friend ostream &operator<<(ostream &os, const String &that);
    friend istream &operator>>(istream &is, String &that);
public:
    String(const char *str = nullptr);
    String(const String &that);
    ~String(void);
    String &operator=(const String &that);
    String operator+(const String &that) const;
    bool operator==(const String &that) const;
    char operator[](int index) const;
    int length(void) const;
    char *c_str(void) const;
    String &exchange(void);
private:
    char *m_pstr;
};

#endif /* __STRING_H */

string.c

#include <cstring>
#include "string.h"

String::String(const char *pstr)
{
    m_pstr = new char[strlen(pstr?pstr:"") + 1];
    strcpy(m_pstr, pstr?pstr:"");
}

String::String(const String &that)
{
    m_pstr = new char[strlen(that.m_pstr) + 1];
    strcpy(m_pstr, that.m_pstr);
}

String::~String(void)
{
    if (m_pstr) {
        delete[] m_pstr;
        m_pstr = nullptr;
    }
}

String &String::operator=(const String &that)
{
    if (&that != this) {
        delete[] m_pstr;
        m_pstr = new char[strlen(that.m_pstr) + 1];
        strcpy(m_pstr, that.m_pstr);
    }
    return *this;
}

String String::operator+(const String &that) const
{
    String newString;
    if (!that.m_pstr) {
        newString = *this;
    } else if (!this->m_pstr) {
        newString = that;
    } else {
        newString.m_pstr = new char[strlen(this->m_pstr) +
                                    strlen(that.m_pstr) + 1];
        strcpy(newString.m_pstr, this->m_pstr);
        strcat(newString.m_pstr, that.m_pstr);
    }
    return newString;
}

bool String::operator==(const String &that) const
{
    if (strlen(this->m_pstr) != strlen(that.m_pstr)) {
        return false;
    } else {
        return strcmp(this->m_pstr, that.m_pstr)?false:true;
    }
}

char String::operator[](int index) const
{
    if (index > 0 && index < strlen(this->m_pstr)) {
        return this->m_pstr[index];
    } else {
        return '\0';
    }
}

ostream &operator<<(ostream &os, const String &that)
{
    os << that.m_pstr;
    return os;
}

istream &operator>>(istream &is, String &that)
{
    is >> that.m_pstr;
    return is;
}

int String::length(void) const
{
    return strlen(this->m_pstr);
}

char *String::c_str(void) const
{
    return this->m_pstr;
}

String &String::exchange(void)
{
    for (int i = 0; i < strlen(m_pstr) / 2; i++) {
        m_pstr[i] ^= m_pstr[strlen(m_pstr) - i - 1];
        m_pstr[strlen(m_pstr) - i - 1] ^= m_pstr[i];
        m_pstr[i] ^= m_pstr[strlen(m_pstr) - i - 1];
    }
    return *this;
}
C++string是一个用于处理字符串的标准库。它提供了一系列成员函数和操作符重载,使得字符串的操作更加方便和高效。 C++string位于命名空间std,因此在使用之前需要包含头文件< string >。 下面是一个简单的示例,展示了如何使用string来创建、初始化和操作字符串: ```cpp #include <iostream> #include <string> int main() { // 创建一个空字符串 std::string str; // 初始化字符串 std::string greeting = "Hello, world!"; // 获取字符串长度 int length = greeting.length(); std::cout << "Length: " << length << std::endl; // 连接字符串 std::string name = "Alice"; std::string message = greeting + " My name is " + name; std::cout << "Message: " << message << std::endl; // 获取子串 std::string substring = message.substr(7, 5); std::cout << "Substring: " << substring << std::endl; // 查找子串 size_t position = message.find("world"); if (position != std::string::npos) { std::cout << "Found at position: " << position << std::endl; } else { std::cout << "Not found" << std::endl; } return 0; } ``` 上述示例,我们首先创建了一个空字符串`str`,然后使用赋值运算符将字符串"Hello, world!"赋给了变量`greeting`。接着,我们使用`length()`函数获取了字符串的长度,并使用`+`运算符将多个字符串连接起来形成新的字符串。我们还使用`substr()`函数获取了字符串的子串,并使用`find()`函数查找了子串在原字符串的位置。 除了上述示例的操作,string还提供了许多其他有用的成员函数和操作符重载,如插入、删除、替换、比较等。你可以参考C++的官方文档或其他相关资料来了解更多关于string的详细信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值