在c++中,string其实就是将字符串封装起来的类,调用类中的成员函数可以完成对类内的字符串进行增删查改,并且将操作符重载,可以更直观的操作字符串,省去了c语言中很多麻烦的操作,有现成的成员函数供我们使用。
举一个简单的例子:在c语言中要在一串字符串的尾部拼接另一个字符串,我们需要做的事情就是定义两个字符串,要使用malloc,然后自己书写拼接逻辑。而在c++中只需要构造出lian两个string对象s1,s2, 使用 s1+=s2,就可以使s2拼接到s1的后面,我们不用关心底层怎么实现,不用写拼接逻辑,并且代码更加直观。
String.h
#include <iostream>
#include <unistd.h>
#include <string.h>
#include <assert.h>
class String
{
public:
String(const char* str = "")
:_size(strlen(str))
,_capacity(_size + 1)
{
_str = new char[_size + 1];
memcpy(_str, str, _size + 1);
}
// s1.Swap(s2);
void Swap(String& s);
// String s2(s1)
String(const String& s)
:_size(s._size)
,_capacity(_size + 1)
{
_str = new char[_size + 1];
memcpy(_str, s._str, _size + 1);
}
// s1 = s2
String& operator=(String s);
~String() {
if(_str) {
delete[] _str;
_str = NULL;
}
}
void Show();
const char* c_str(); //获取String类中的c风格字符串
void Expand(size_t n); //扩容
void PushBack(char ch); //尾部插入一个字符
void PushBack(const char* str); //尾部插入一个字符串
void PopBack(); //尾部删除一个字符
void Insert(size_t pos, char ch); //在pos位置插入一个字符
void Insert(size_t pos, const char* str); //在pos位置插入一个字符串
void Erase(size_t pos, size_t n = 1); //在pos位置删除n个字符串
size_t Find(char ch); //返回String对象中第一次出现ch的下标
size_t Find(const char* str); // //返回String对象中第一次出现str的下标
// s1 + 'a'
String operator+(char ch);
String& operator+=(char ch);
String operator+(const char* str);
String& operator+=(const char* str);
bool operator>(const String& s);
bool operator>=(const String& s);
bool operator<(const String& s);
bool operator<=(const String& s);
bool operator==(const String& s);
bool operator!=(const String& s);
private:
char* _str;
size_t _size;
size_t _capacity;
};
#include "String.h"
using namespace std;
void String::Show() {
std::cout<<"_str :"<<_str<<std::endl;
std::cout<<"_szie :"<<_size<<std::endl;
std::cout<<"_capacity :"<<_capacity<<std::endl<<endl;
}
void String::Swap(String& s) {
_size = s._size;
_capacity = s._capacity;
delete[] _str;
_str = s._str;
s._str = new char[1];
}
String& String::operator= (String s) {
Swap(s);
return *this;
}
const char* String::c_str(){
return _str;
}
void String::Expand(size_t n) {
char* tmp = new char[n];
memcpy(tmp, _str, _size + 1);
delete[] _str;
_str = tmp;
_capacity = n;
}
void String::PushBack(char ch) {
Insert(_size, ch);
}
void String::PushBack(const char* str) {
Insert(_size, str);
}
void String::Insert(size_t pos, char ch) {
assert(pos <= _size);
if(_size >= _capacity - 1) {
Expand(2 * _capacity + 1);
}
for(int i = (int)_size; i > (int)pos; i--) {
_str[i] = _str[i-1];
}
_str[pos] = ch;
++_size;
}
void String::Insert(size_t pos, const char* str) {
assert(pos <= _size);
const char* tmp = str;
size_t size = 0;
for(; *tmp != '\0'; ++tmp) {
++size;
}
if(_capacity < (_size + size)) {
Expand(_capacity + size);
}
for(int i = (int)_size; i >= (int)pos; --i) {
_str[i+size] = _str[i];
}
int i = 0;
while(*(str+i) != '\0') {
_str[pos + i] = *(str + i);
++i;
}
_size += size;
}
void String::PopBack() {
Erase(_size - 1, 1);
}
void String::Erase(size_t pos, size_t n) {
if(_size == 0) {
return;
}
if(n == 0) {
return;
}
assert(pos <= _size);
while((pos + n) <= _capacity) {
_str[pos] = _str[pos+n];
++pos;
}
if(((int)_size - (int)n) > 0) {
_size = _size - n;
} else {
_size = 0;
}
_str[_size] = 0;
}
size_t String::Find(char ch) {
for(size_t i = 0; i<_size; ++i) {
if(_str[i] == ch) {
return i;
}
}
return (size_t)-1;
}
size_t String::Find(const char* str) {
const char* _fast = _str;
const char* _slow = _str;
const char* cur = str;
while(_slow < (_str + _size)) {
_fast = _slow;
if(*_fast == *cur) {
while(*_fast == *cur) {
if(*_fast == '\0') {
break;
}
_fast++, cur++;
}
if(*cur == '\0') {
return _slow - _str;
}
}
_slow++;
cur = str;
}
return (size_t) -1;
}
String String::operator+(char ch) {
String tmp(*this);
tmp.PushBack(ch);
return tmp;
}
String& String::operator+=(char ch) {
this->PushBack(ch);
return *this;
}
String String::operator+(const char* str) {
String tmp(*this);
tmp.PushBack(str);
return tmp;
}
String& String::operator+=(const char* str) {
this->PushBack(str);
return *this;
}
bool String::operator>(const String& s) {
const char* _tmp = _str;
const char* tmp = s._str;
while(*tmp != '\0' && *_tmp != '\0' && *_tmp == *tmp) {
_tmp++, tmp++;
}
if(*_tmp > *tmp) {
return true;
}
return false;
}
bool String::operator>=(const String& s) {
if(*this > s || *this == s) {
return true;
}
return false;
}
bool String::operator<(const String& s) {
const char* _tmp = _str;
const char* tmp = s._str;
while(*tmp != '\0' && *_tmp != '\0' && *_tmp == *tmp) {
_tmp++, tmp++;
}
if(*_tmp < *tmp) {
return true;
}
return false;
}
bool String::operator<=(const String& s) {
if(!(*this > s)) {
return true;
}
return false;
}
bool String::operator==(const String& s) {
const char* _tmp = _str;
const char* tmp = s._str;
while(*_tmp == *tmp) {
if(*_tmp == '\0' && *tmp == '\0') {
return true;
}
_tmp++, tmp++;
}
return false;
}
bool String::operator!=(const String& s) {
if(!(*this == s)) {
return true;
}
return false;
}
void Test(){
// String s1("12345");
// s1.Show();
//
// String s2(s1);
// s2.Show();
//
// String s3 = s2;
// s3.Show();
//
// cout<<"test c_str:"<<s3.c_str()<<endl;
//
// s3.Expand(20);
// s3.Show();
//
// String s4("abc");
// s4.Show();
// s4.PushBack('1');
// s4.Show();
// s4.PushBack("2345");
// s4.Show();
// s4.Insert(8, 'A');
// s4.Show();
// s4.Insert(3, 'd');
// s4.Show();
// s4.Insert(4, "ABCD");
// s4.Show();
// s4.Insert(14, "HHHH");
// s4.Show();
//
// s4.PopBack();
// s4.PopBack();
// s4.PopBack();
// s4.PopBack();
// s4.PopBack();
// s4.Show();
// s4.Erase(0, 4);
// s4.Show();
// s4.Erase(0, 0);
// s4.Show();
// s4.Erase(0, 20);
// s4.Show();
// String s5("abacadabcdaaa");
// cout<<s5.Find('a')<<endl;
// cout<<s5.Find('b')<<endl;
// cout<<(int)s5.Find('A')<<endl<<endl;
//
// cout<<(int)s5.Find("")<<endl;
// cout<<(int)s5.Find("abcd")<<endl;
// cout<<(int)s5.Find("aaa")<<endl;
// cout<<(int)s5.Find("ab")<<endl;
// cout<<(int)s5.Find("abaa")<<endl;
// String s6("a");
// s6 = s6 + 'b';
// s6 += 'c';
// s6 = s6 + "123";
// s6 += "456";
// s6.Show();
// String s7("abcdefg");
// String s8("abcdef");
// cout<<(s7==s7)<<endl;
// cout<<(s7==s8)<<endl;
// cout<<(s7!=s7)<<endl;
// cout<<(s7!=s8)<<endl;
String s7("abcdefg");
String s8("abcdef");
cout<<(s7>=s7)<<endl; //1
cout<<(s7<=s7)<<endl; //1
cout<<(s7>=s8)<<endl; //1
cout<<(s7<=s8)<<endl; //0
cout<<(s7>s7)<<endl; //0
cout<<(s7<s7)<<endl; //0
cout<<(s7>s8)<<endl; //1
cout<<(s7<s8)<<endl; //0
}
int main()
{
Test();
return 0;
}