**前言:cstring库是C语言标准库string.h的C++版本,主要用于处理C分格字符串(以空字符'\0'结尾的字符数组),通过#include <cstring>引入。**C++中的string类包含了cstring库的所有功能。本文介绍string类中的一些方法,了解string类是如何实现与cstring库相同功能的。
目录
[1. 默认构造函数](#1. 默认构造函数)
[2. 比较操作符重载函数](#2. 比较操作符重载函数)
[3. 赋值操作符重载函数](#3. 赋值操作符重载函数)
[4. 中括号重载函数](#4. 中括号重载函数)
一个简略版的string类如下:
cpp
#include <iostream>
class MyClassString
{
public:
MyClassString();///default constructor
MyClassString(const char* s)
{
len = std::strlen(s);
str = new char[len + 1];
std::strcpy(str, s);
}
MyClassString(const MyClassString&);//copy constructor
~MyClassString();///destructor
public:
int length() const;
friend bool operator<(const MyClassString &st, const MyClassString& st2);
friend bool operator>(const MyClassString &st, const MyClassString& st2);
friend bool operator==(const MyClassString &st, const MyClassString& st2);
friend std::istream& operator>> (std::istream& is, const MyClassString& st);
friend std::ostream& operator<< (std::ostream& os, const MyClassString& st)
{
os << st.str;
return os;
}
char& operator[](int i);
const char& operator[](int i) const;
MyClassString& operator= (const MyClassString& s);
MyClassString& operator= (const char* s);
private:
char* str;///pointer to string
int len;///length of string
static int num_strings;///number of object
static const int CINLIM = 80;///cin input limit
};
程序说明:
1. 默认构造函数
默认构造函数的定义如下:
cpp
MyClassString::MyClassString()
{
len = 0;
str = new char[1];
str[0] = '\0';///default string
}
其中,第二行在分配内存空间时,使用new char[1]而不是new char,是为了与析构函数中的代码(delete []str;)兼容。
delete []与使用new []初始化的指针和空指针都兼容,因此对于默认构造函数,还可以写成如下形式:
cpp
MyClassString::MyClassString()
{
len = 0;
str = 0;///sets str to the null pointer
}
2. 比较操作符重载函数
在string类中,执行比较操作的方法有3个。如果第一个字符串在第二个字符串之前,则operator<()函数返回true。
operate<()函数定义如下:
cpp
bool operator>(const MyClassString &st, const MyClassString& st2)
{
if (std::strcmp(st.str, st2.str) > 0)
{
return true;
}
else
{
return false;
}
}
strcmp函数说明:
- 函数原型:int strcmp(const char *s1, const char *s2);
- 参数 :两个指向字符串的指针(
s1和s2)。- 返回值:整数类型,表示比较结果。
- 原理 :从第一个字符开始,依次对比
s1和s2对应位置的字符(基于ASCII值),当遇到不同字符 或字符串结束符\0时停止比较。当s1等于s2时,返回0;当s1小于s2时(基于ASCII值),返回负数;当s1大于s2时(基于ASCII值),返回正数;
同理,operate>()和operate==()方法的定义如下:
cpp
bool operator<(const MyClassString &st, const MyClassString& st2)
{
return (std::strcmp(st.str, st2.str) < 0);
}
bool operator==(const MyClassString &st, const MyClassString& st2)
{
return (std::strcmp(st.str, st2.str) == 0);
}
将比较操作符重载函数设置为友元函数,可以使string对象与C字符串的比较更加方便。如:
cpp
MyClassString testString("test");
MyClassString testString2("abcd");
if (testString > testString2)
{
cout << testString << "大于" << testString2 << endl;
}
else
{
cout << testString << "小于" << testString2 << endl;
}
if (testString > "xyzw")
{
cout << testString << "大于" << "xyzw" << endl;
}
else
{
cout << testString << "小于" << "xyzw" << endl;
}
3. 赋值操作符重载函数
如果没有对赋值操作符进行重载,那么将一个常规字符串(如C分格的字符串)复制到MyClassString类中,则需要编写如下代码:
cpp
MyClassString test_string;
char temp[80];
std::cin.getline(temp, 80);
test_string = temp;
getline函数读取输入的字符串。getline函数会在遇到换行符后将输入的字符串存入到temp字符数组中,并自动在末尾添加字符串结尾标记'\0'。最后一条语句中,程序使用构造函数MyClassString(const char* s)创建一个临时MyClassString对象,对象包含了temp中的字符串拷贝(只有一个参数的构造函数将被用作转换函数)。然后使用MyClassString& operator= (const MyClassString&)函数将临时对象中的信息复制到MyClassString对象test_string中,最后程序使用析构函数来删除临时对象。
上面字符串赋值的方式效率较低,为此,可以通过重载赋值操作符,使得能够直接使用常规字符串进行赋值,而不必创建临时对象。重载赋值操作符函数的代码如下:
cpp
MyClassString& MyClassString::operator= (const char* s)
{
delete[] str;
len = std::strlen(s);
str = new char[len + 1];
std::strcpy(str, s);
return *this;
}
函数说明:重载赋值操作符函数中,首先释放原来字符串占据的内存空间,并为新字符串分配足够的内存,字符串与字符数组相比,末尾多了个'\0'字符,因此字符串的长度要在字符数组长度基础上加1。其中,strlen函数
strlen函数是C语言标准库函数,用于计算C风格字符串的长度(即以空字符'\0'结尾的字符数组)。
- 函数原型为:size_t strlen(const char* str);
- 函数参数:指向以
'\0'结尾的字符串的指针(如const char*或char[])- 返回值:字符串中字符的数量(不包括结尾的
'\0'),类型为size_t(无符号整数)- 头文件:使用时需包含头文件
<cstring>
4. 中括号重载函数
对于C字符串来说,可以使用中括号访问其中的字符。在C++中可以通过重载中括号操作符,使C++字符串也能通过中括号访问其中的字符。通常,二元操作符位于两个操作数之间,但对于中括号操作符,一个操作数位于第一个中括号的前面,另一个操作数位于中括号之间。例如,对于表达式:tempString[1],tempString是第一个操作数,1是第二个操作数。重载中括号操作符函数的定义如下:
cpp
char& operator[](int i)
{
return str[i];
}
将函数返回值声明为char &,意味着可以给特定元素赋值。假设有下面的语句:
cpp
MyClassString testString("might");
testString[0] = 'n';
第二条语句通过中括号操作符重载函数被转化为如下形式:
cpp
testString.operator[][0] = 'n';
由于中括号操作符重载函数返回的是指向testString.str[0]的引用,因此上述语句等同于如下代码:
cpp
testString.str[0] = 'n';
上面的代码自然是不合语法的,因为testString对象不能直接访问私有数据成员,但因为重载了中括号操作符,因此可以通过中括号操作符重载函数访问私有数据成员str,最终字符串str的内容由"might"被修改为"night"。