目录
C++ string类
值得注意的是 , string不是STL的容器,string是basic_string类模板的一个实例,string是一个模板类, 它使用char来实例basic_string, string集成的操作函数与STL中容器中的操作函数大部分很相似, 因为sting本身也是用顺序表来实现的(与vector容器类似)
C++之所以用C++标准程序库中的string来代替C中的char*(C++中还是可以用char*, 这是为了与C保持兼容),是因为它和C中的char*比较起来,不必担心内存是否足够、字符串长度等等,而且作为一个类出现,他集成的操作函数足以完成我们大多数情况下的需要。我们也可以把string看成是C++的基本数据类型。
string定义在标准命名空间std中, 所以要么在用之前加using namespace std; 使string对外可见, 要么不嫌麻烦 std::string
使用string这个模板类要加头文件<string>注意:
1. string是表示字符串的字符串类
2.string的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
3. string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>string;
4. 不能操作多字节或者变长字符的序列(举个例子, string s = "你好"; 当你pop_back()时, 并不是删除字符 "好", 而是只删除char类型的的长度也就是1字节, 而汉字在常见编码方式下都比1字节长)
string类的常用接口说明
string其中大部分接口与矢量容器vector接口保持一致, 功能用法也一样, 这些与vector保持一致接口用起来就与vector<char> 一样, 这里对这些保持一致的接口并不做过多的说明 , string可以看做在vector<char>的基础上多了一些处理字符串的接口函数 链接 :vector接口说明
1. string类对象的常见构造
函数名称 | 函数功能 |
---|---|
string () | 构造一个空的字符串 |
string (const char* c_s) | 用一个char*类型的字符串c_s来构造一个string类型的的字符串 |
string(const char* c_s, size_t n) | 截取c_s中前n个字符, 来构造字符串 |
string (const char* c_s, size_t pos, size_t npos) | 截取c_s中从下标为pos的字符到下标为npos的字符, 来构造字符串 |
string (const string& s) | 拷贝构造函数, 构造一个与s一模一样的字符串 |
string (const string& s, size_t pos) | 截取s中从下标为pos的字符开始往后的所有有效字符, 来构造字符串 |
string (const string& s, size_t pos, size_t npos) | 截取s中从下标为pos的字符到下标为npos的字符, 来构造字符串 |
string (size_t n, char c) | 构造一个有n个字符c的字符串 |
template <class InputIterator> string (InputIterator begin, InputIterator end) | 以区间[begin, end) (不包含end)内的字符作为字符串s的初值, 这里的begin和end是迭代器 |
~string() | 析构 |
来看具体应用 :
//头文件
#include<iostream>
#include<string>
#include <typeinfo>
using namespace std;
void test() {
//string的构造函数
string s;//string()
string s1("abcdef");//string(const char* s)
string s2(4, 'a'); //string(size_t n, char c)
string s3(s1); //string(const string& s)
string s4(s1, 3); //string(const string& s, size_t n)
string s5(s1, 1, 5);
string s6("abcdefe", 3);
string s7("scscssr", 2, 6);
cout << typeid(s1.begin()).name() << endl;
cout << typeid(*s1.begin()).name() << endl;
string::iterator begin = s1.begin();
string::iterator end = s1.end();
string s8(begin, end);
cout << "s: " << endl
<< "s1:" << s1 << endl
<< "s2:" << s2 << endl
<< "s3:" << s3 << endl
<< "s4:" << s4 << endl
<< "s5:" << s5 << endl
<< "s6:" << s6 << endl
<< "s7:" << s7 << endl
<< "s8:" << s8 << endl;
for (int i = 0; begin + i < end; ++i) {
cout << *(begin + i);
}
cout << endl;
cout << endl;
system("pause");
system("cls");
}
值得注意的是最后一个函数 string (string::iterator begin, string::iterator end), 其中两个参数都是迭代器, 迭代器是一个变量, 迭代器可以指向string中的某个元素,通过迭代器就可以读写它指向的元素。从这一点上看,迭代器和指针类似。可以看到string中的迭代器变量解引用之后是char类型, 本质上迭代器就是char*类型 .
2. string类对象的容量操作
函数名称 | 函数功能 |
---|---|
size_t size() const | 返回字符串有效字符长度 |
size_t length() const | 返回字符串有效字符长度 |
size_t capacity ( ) const | 返回空间总大小 |
bool empty ( ) const | 检测字符串是否为空串,是返回true,否则返回false |
void clear() | 清空有效字符(将字符串变成空串) |
void resize ( size_t n, char c = 0 ) | 将有效字符的个数(size)改成n个,多出的空间用字符c填充(注意, 字符个数只会增加, 如传入比有效长度小的值则不作操作) |
void resize ( size_t n ) | 将有效字符的个数(size)改成n个,多出的空间用字符'\0'填充(注意, 字符个数只会增加, 如传入比有效长度小的值则不作操作) |
void reserve ( size_t n = 0 ) | 为字符串预留空间(扩容, 改变的是容量(capacity)的大小)(注意, 扩容只会增加, 如传入比原容量小的值则不作操作) |
注意 :
size函数和length作用是一样的
resize和reserve都只能向大调整
resize函数会调用reserve函数
void test1() {
string s1("abcdef");//string(const char* s)
string s2(4, 'a'); //string(size_t n, char c)
string s3(s1); //string(const string& s)
cout << "sting类的容量操作\n";
cout << "s1有效长度是:" << s1.size() << endl;
//size_t size() const 返回字符串有效字符长度
cout << "s1有效长度是:" << s1.length() << endl;
//size_t length() const 返回字符串有效字符长度
cout << "s2有效长度是:" << s2.size() << endl;
cout << "s2有效长度是:" << s2.length() << endl;
cout << "s1的容量是:" << s1.capacity() << endl;
//size_t capacity() const 返回空间总大小
cout << "s2的容量是:" << s2.capacity() << endl;
s1.reserve(20);
//void reserve(size_t res_arg = 0) 为字符串预留空间
cout << "s1有效长度是:" << s1.size() << endl;
cout << "s1的容量是:" << s1.capacity() << endl;
s2.resize(25);
//void resize(size_t n) 将有效字符的个数改成n个,多出的空间用0填充
cout << "s2有效长度是:" << s2.size() << endl;
cout << "s2的容量是:" << s2.capacity() << endl;
s2 += "字符串结束";
cout << "s2:" << s2 << endl;
s3.resize(20, 'z');
//void resize(size_t n, char c) 将有效字符的个数该成n个,多出的空间用字符c填充
cout << "s3有效长度是:" << s3.size() << endl;
cout << "s3的容量是:" << s3.capacity() << endl;
cout << "s3:" << s3 << endl;
s1.empty() ? cout << "s1为空\n" : cout << "s1不为空!\n";
//bool empty() const 检测字符串释放为空串,是返回true,否则返回false
cout << "清空s2\n";
s2.clear();
s2.empty() ? cout << "s2为空\n" : cout << "s2不为空!\n";
system("pause");
system("cls");
}
3.string类对象的访问操作
函数名称 | 函数功能 |
---|---|
char& operator[] ( size_t pos ) | 返回pos位置的字符,const string类对象调用 |
const char& operator[] (size_t pos) const | 返回pos位置的字符,非const string类对象调用 |
void test2() {
//string类对象的访问操作
string s1("abcdef");
const string s2("xyz");
cout << "s1:" << s1 << endl;
for (size_t i = 0; i < s1.size(); ++i) {
cout << s1[i] << " ";
//char& operator[] ( size_t pos ) 返回pos位置的字符,非const string类对象调用
}
cout << endl;
cout << "s2:" << s2 << endl;
for (size_t i = 0; i < s2.size(); ++i) {
cout << s2[i] << " ";
//char& operator[] ( size_t pos ) 返回pos位置的字符,const string类对象调用
}
cout << endl;
system("pause");
system("cls");
}
4. string类对象的修改操作
函数名称 | 重载函数 | 函数功能 |
---|---|---|
void push_back(char c) | / | 在字符串后尾插字符c |
string& append | string& append (const string& str); string& append (const string& str, size_t subpos, size_t sublen); string& append (const char* s); string& append (const char* s, size_t n); string& append (size_t n, char c); template <class InputIterator> string& append (InputIterator first, InputIterator last); | 在字符串后尾插字符或字符串 |
string& operator+= | string& operator+= (const string& str); string& operator+= (const char* s); string& operator+= (char c); | 在字符串后追加一个字符串s在字符串后追加一个C字符串s 在字符串后追加字符c |
const char* c_str( )const | / | 返回C格式字符串 |
size_t find | size_t find (const string& str, size_t pos = 0) const; size_t find (const char* s, size_t pos = 0) const; size_t find (const char* s, size_t pos, size_t n) const; size_t find (char c, size_t pos = 0) const; | 从字符串pos位置开始往后找字符或字符串,返回其在此字符字符串中的位置 |
size_t rfind | size_t rfind (const string& str, size_t pos = npos) const; size_t rfind (const char* s, size_t pos = npos) const; size_t rfind (const char* s, size_t pos, size_t n) const; size_t rfind (char c, size_t pos = npos) const; | 从字符串pos位置开始往前找字符或字符串,返回其在此字符串中的位置 |
string substr(size_t pos = 0, size_t n = npos)const | / | 在str中从pos位置开始,往后截取n个字符,然后返回内容是这n个字符的字符串 |
void test3() {
string s("abcdef");
string s1("higk");
string s2("qrst");
cout << "s:" << s << endl;
s.push_back('g');//void push_back(char c) 在字符串后尾插字符c
cout << "s:" << s << endl;
s.append(s1);//string& append (const char* s); 在字符串后追加一个字符串
s.append("dsscs");
s.append(8, 'a');
cout << "s:" << s << endl;
s += "lmnop";//string& operator+=(const char* s) 在字符串后追加一个字符串
cout << "s:" << s << endl;
s += s2;//string& operator+=(const string& str)在字符串后追加sting类字符串str
cout << "s:" << s << endl;
s += 'u';//string& operator+=(char c) 在字符串后追加字符c
cout << "s:" << s << endl;
s.pop_back();//void pop_back() 删除字符串最后一个字符
cout << "s:" << s << endl;
const char* c_s = s1.c_str();//const char* c_str( )const 返回C格式字符串
cout << "c_s:" << c_s << endl;
char c = 'd';
size_t pos = 0;
size_t n = s.find(c, pos);//pos<s.size();否则会发生访问越界
//size_t find (char c, size_t pos =0)const //pos是缺省参数, 不传就是从0开始
//从字符串pos位置开始往后找字符c,找到字符返回字符串中的下标,找不到返回-1,
//因为返回值是size_t所以是4294967295
n != (size_t)-1 ? cout << c << "在字符串s中下标为" << n << "的位置\n" :
cout << c << "不在从下标" << pos << "位置开始往后的字符串中\n";
n = s.find(s1/*缺省参数默认0*/);//pos<s.size();否则会发生访问越界
//size_t find (string c, size_t pos =0)const //pos是缺省参数, 不传就是从0开始
//从字符串pos位置开始往后找字串c,找到字符串c
//返回c在被找字符串中的下标,找不到返回-1, 因为返回值是size_t所以是4294967295
n != (size_t)-1 ? cout << s1 << "在字符串s中下标为" << n << "的位置\n" :
cout << s1 << "不在从下标" << pos << "位置开始往后的字符串中\n";
n = s.rfind(c_s, s.size() - 1);//pos<s.size();否则会发生访问越界
//size_t find (char* c, size_t pos =0)const //pos是缺省参数, 不传就是从0开始
//从字符串pos位置开始往后找字串c,找到字符串c
//返回c在被找字符串中的下标,找不到返回-1, 因为返回值是size_t所以是4294967295
n != (size_t)-1 ? cout << c_s << "在字符串s中下标为" << n << "的位置\n" :
cout << c_s << "不在从下标" << pos << "位置开始往后的字符串s中\n";
size_t npos = 10;
n = s.rfind(c, npos);//npos<s.size();否则会发生访问越界
//size_t rfind (char c, size_t pos =0)const//pos是缺省参数, 默认为0
//从字符串pos位置开始往前找字符c
//找到字符返回字符串中的下标,找不到返回-1, 因为返回值类型size_t所以是4294967295
n != (size_t)-1 ? cout << c << "在字符串s中下标为" << n << "的位置\n" :
cout << c << "不在从下标" << npos << "位置开始往前的字符串中\n";
string s3 = s.substr(pos, npos);//npos<s.size(), pos>=0, npos-pos>=0;
//pos为缺省参数
//string substr(size_t pos = 0, size_t n= npos)const
//在str中从pos位置开始,截取n个字符,然后将其返回
cout << "s3:" << s3 << endl;
system("pause");
system("cls");
}
注意 :
在string尾部追加字符时,s.push_back('c') , s.append(1, 'c') , s += 'c'三种的实现方式差不多,一般情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
对string操作时,如果能够大概预估到放多少字符,可以先通过reserve()函数把空间预留好, 这样就不会出现后期操作中频繁扩容,导致效率降低的情况发生
5. string类非成员函数(友元函数)
函数名称 | 重载的函数 | 函数功能 |
---|---|---|
operator+ | string operator+ (const string& lhs, const string& rhs); string operator+ (const string& lhs, const char* rhs); string operator+ (const char* lhs, const string& rhs); string operator+ (const string& lhs, char rhs); string operator+ (char lhs, const string& rhs); | 返回字符(串)+字符(串) 此函数效率较低 |
operator<< | ostream& operator<< (ostream& os, const string& str); | 输出运算符重载, 打印字符串 |
operator>> | istream& operator>> (istream& is, string& str); | 输入运算符重载, 输入字符串 |
getline | istream& getline (istream& is, string& str, char delim); istream& getline (istream& is, string& str); | 获取一行字符串, char delim, 是结束符标识. |
relational operators | bool operator== (const string& lhs, const string& rhs); bool operator== (const char* lhs, const string& rhs); bool operator== (const string& lhs, const char* rhs); bool operator!= (const string& lhs, const string& rhs); bool operator!= (const char* lhs, const string& rhs); bool operator!= (const string& lhs, const char* rhs); bool operator< (const string& lhs, const string& rhs); bool operator< (const char* lhs, const string& rhs); bool operator< (const string& lhs, const char* rhs); bool operator<= (const string& lhs, const string& rhs); bool operator<= (const char* lhs, const string& rhs); bool operator<= (const string& lhs, const char* rhs); bool operator> (const string& lhs, const string& rhs); bool operator> (const char* lhs, const string& rhs); bool operator> (const string& lhs, const char* rhs); bool operator>= (const string& lhs, const string& rhs); bool operator>= (const char* lhs, const string& rhs); bool operator>= (const string& lhs, const char* rhs); | 比较两个字符串 string和char*比较 char*和string比较 string和string比较
|
string类(实现常用接口)
string.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
#include<cstring>
#include<cassert>
using namespace std;
class String {
size_t m_capacity;
char* m_data;
size_t m_size;
public:
typedef char* Iterator;
//using Iterator = typename String::Iterator;
String();
String(const String&);
String(const char*);
String(size_t, char);
String(const String&, size_t);
String& operator=(const String&);
String& operator=(const char*);
template <class InputIterator>
String(InputIterator begin, InputIterator end) :m_size(0)
, m_capacity(15)
, m_data(new char[m_capacity])
{
reserve(end - begin);
m_size = end - begin;
strncpy(m_data, begin, end - begin);
}
~String();
Iterator begin()const;
Iterator end()const;
size_t size() const;
size_t length() const;
size_t capacity() const;
bool empty() const;
void clear();
void resize(size_t n, const char c = ' ');
void reserve(size_t res_arg);
char& operator[] (size_t pos) const;
char& operator[] (size_t pos);
void push_back(const char c);
void pop_back(const char c);
String& append(const char* s);
String& append(size_t n, const char c);
String& append(const String& s);
template <class InputIterator>
String& append(InputIterator first, InputIterator last) {
int size = last - first + m_size;
reserve(size);
strncpy(m_data + m_size, first, last - first);
m_size = size;
return *this;
}
const char* c_str()const;
size_t find(const char c, size_t pos = 0)const;
size_t find(const char* c, size_t pos = 0)const;
size_t find(const String& t, size_t pos = 0)const;
size_t rfind(const char c, size_t pos = 0)const;
size_t rfind(const char* s, size_t pos = 0)const;
size_t rfind(const String& t, size_t pos = 0)const;
String substr(size_t pos = 0, size_t n = 0)const;
String& operator+=(const char c);
String& operator+=(const String& s);
String& operator+=(const char* s);
friend String operator+(const char* s, const String& t);
String operator+(const char* s)const;
String operator+(const String& t)const;
bool operator<(const String& t)const;
bool operator>(const String& t)const;
bool operator<=(const String& t)const;
bool operator>=(const String& t)const;
bool operator==(const String& t)const;
bool operator!=(const String& t)const;
bool operator<(const char* s)const;
bool operator>(const char* s)const;
bool operator<=(const char* s)const;
bool operator>=(const char* s)const;
bool operator==(const char* s)const;
bool operator!=(const char* s)const;
friend bool operator<(const char* t1, const String& t2);
friend bool operator>(const char* t1, const String& t2);
friend bool operator<=(const char* t1, const String& t2);
friend bool operator>=(const char* t1, const String& t2);
friend bool operator==(const char* t1, const String& t2);
friend bool operator!=(const char* t1, const String& t2);
friend istream& operator>>(istream& is, String& t);
friend ostream& operator<<(ostream& os, const String& t);
friend istream& getline(istream& is, String& str, char n);
friend istream& getline(istream& is, String& str);
};
string.cpp
#include "string.h"
String::Iterator String::begin()const {
return m_data;
}
String::Iterator String::end() const{
return m_data + m_size;
}
String::String() :m_size(0),
m_capacity(15),
m_data(new char[m_capacity])
{
memset(m_data, 0, m_capacity);
}
String::String(const String& t):m_size(0)
,m_capacity(15)
,m_data(new char[m_capacity])
{
if (this == &t) {
return;
}
memset(m_data, 0, m_capacity);
reserve(t.m_capacity);
m_size = t.m_size;
m_capacity = t.m_capacity;
strncpy(m_data, t.m_data, m_size);
}
String::String(const char* t) :m_size(0)
, m_capacity(15)
, m_data(new char[m_capacity])
{
if (t == nullptr) {
assert(false);
}
size_t size = strlen(t);
reserve(size);
m_size = size;
strcpy(m_data, t);
}
String::String(size_t n, char c) :m_size(0)
, m_capacity(15)
, m_data(new char[m_capacity])
{
reserve(n);
m_size = n;
memset(m_data, c, n);
}
String::String(const String& t, size_t n) :m_size(0)
, m_capacity(15)
, m_data(new char[m_capacity])
{
reserve(n);
m_size = n;
strncpy(m_data, t.m_data, n);
}
String::~String() {
if (m_data) {
delete[]m_data;
}
m_data = nullptr;
m_size = 0;
m_capacity = 0;
}
String& String::operator=(const String& t) {
if (this == &t) {
return *this;
}
reserve(t.m_capacity);
strcpy(m_data, t.m_data);
m_size = t.m_size;
return *this;
}
String& String::operator=(const char* s) {
if (s == nullptr) {
assert(false);
}
if (!strcmp(m_data, s)) {
return *this;
}
size_t size = strlen(s) + m_size;
reserve(size);
m_size = size;
strcpy(m_data, s);
return *this;
}
size_t String::size() const {
return m_size;
}
size_t String::length() const {
return m_size;
}
size_t String::capacity() const {
return m_capacity;
}
bool String::empty() const {
return m_size == 0;
}
void String::clear() {
m_size = 0;
}
void String::resize(size_t n, const char c) {
if (n > m_size) {
size_t m = m_size;
reserve(n);
m_size = n;
/*for (size_t i = m - 1; i < m_size; ++i) {
m_data[i] = c;
}*/
memset(m_data + m, c, m_capacity - m);
}
}
void String::reserve(size_t res_arg = 0) {
if (res_arg > m_capacity) {
m_capacity = (res_arg / m_capacity + 1) * 16 - 1;
m_data = (char*)realloc(m_data, m_capacity);
memset(m_data + m_size, 0, m_capacity - m_size);
}
}
char& String::operator[] (size_t pos) const {
return m_data[pos];
}
char& String::operator[] (size_t pos) {
return m_data[pos];
}
void String::push_back(const char c) {
reserve(m_size);
m_data[m_size++] = c;
}
void String::pop_back(const char c) {
if (m_size) {
--m_size;
}
}
String& String::append(const char* s) {
if (s == nullptr) {
assert(false);
}
int size = strlen(s) + m_size;
reserve(size);
strcpy(m_data + m_size, s);
m_size = size;
return *this;
}
String& String::append(size_t n, const char c) {
while (n--) {
push_back(c);
}
return *this;
}
String& String::append(const String& str) {
int size = str.m_size + m_size;
reserve(size);
strncpy(m_data + m_size, str.m_data, str.m_size);
m_size = size;
return *this;
}
String& String::operator+=(const String&str) {
int size = str.m_size + m_size;
reserve(size);
strncpy(m_data + m_size, str.m_data, str.m_size);
m_size = size;
return *this;
}
String& String::operator+=(const char* s) {
if (s == nullptr) {
assert(false);
}
int size = strlen(s) + m_size;
reserve(size);
strcpy(m_data + m_size, s);
m_size = size;
return *this;
}
String& String::operator+=(const char c) {
push_back(c);
return *this;
}
String operator+(const char* s, const String& t) {
if (s == nullptr) {
assert(false);
}
String res;
res = s;
int size = res.m_size + t.m_size;
res.reserve(size);
strncpy(res.m_data + res.m_size, t.m_data, t.m_size);
res.m_size = size;
return res;
}
String String::operator+(const char* s)const {
if (s == nullptr) {
assert(false);
}
String res = *this;
int size = strlen(s) + m_size;
res.reserve(size);
strcpy(res.m_data + res.m_size, s);
res.m_size = size;
return res;
}
String String::operator+(const String& t)const {
String res = *this;
int size = res.m_size + t.m_size;
res.reserve(size);
strncpy(res.m_data + res.m_size, t.m_data, t.m_size);
res.m_size = size;
return res;
}
const char* String::c_str()const {
return m_data;
}
size_t String::find(const char c, size_t pos)const {
if (pos < 0 || pos >= m_size) {
return -1;
}
char* tmp = strchr(m_data + pos, c);
if (tmp) {
return tmp - m_data;
}
else {
return -1;
}
}
size_t String::find(const char* c, size_t pos) const {
if (c == nullptr) {
assert(false);
}
if (pos < 0 || pos >= m_size) {
return -1;
}
char* tmp = strstr(m_data + pos, c);
if (tmp) {
return tmp - m_data;
}
else {
return -1;
}
}
size_t String::find(const String& t, size_t pos)const {
if (pos < 0 || pos >= m_size) {
return -1;
}
char* tmp = strstr(m_data + pos, t.m_data);
if (tmp) {
return tmp - m_data;
}
else {
return -1;
}
}
size_t String::rfind(const char c, size_t pos)const{
char* tmp = nullptr;
strncpy(tmp, m_data, pos);
char* m = nullptr;
if (tmp) {
m = strchr(tmp, c);
}
if (m) {
return m - tmp;
}
else {
return -1;
}
}
size_t String::rfind(const char* s, size_t pos)const {
if (s == nullptr) {
assert(false);
}
char* tmp = nullptr;
strncpy(tmp, m_data, pos);
char* m = nullptr;
if (tmp) {
m = strstr(tmp, s);
}
if (m) {
return m - tmp;
}
else {
return -1;
}
}
size_t String::rfind(const String& t, size_t pos)const {
char* tmp = new char[pos + 1];
tmp[pos] = 0;
strncpy(tmp, m_data, pos);
char* m = nullptr;
if (tmp) {
m = strstr(tmp, t.c_str());
}
if (m) {
return m - tmp;
delete[]tmp;
}
else {
return -1;
delete[]tmp;
}
}
String String::substr(size_t pos, size_t n)const {
String res;
if (pos > m_size)return res;
if (pos + n > m_size) {
n = m_size - pos;
}
res.reserve(n);
res.m_size = n;
strncpy(res.m_data, m_data + pos, n);
return res;
}
istream& operator>>(istream& is, String& t) {
char ch;
t.m_size = 0;
is >> ch;
while (ch != '\n') {
t.push_back(ch);
ch = getchar();
}
return is;
}
ostream& operator<<(ostream& os, const String& t) {
for (auto i : t) {
os << i;
}
return os;
}
istream& getline(istream& is, String& t, char n) {
char ch;
t.m_size = 0;
is >> ch;
while (ch != n) {
t.push_back(ch);
ch = getchar();
}
return is;
}
istream& getline(istream& is, String& t) {
char ch;
t.m_size = 0;
is >> ch;
while (ch != '\n') {
t.push_back(ch);
ch = getchar();
}
return is;
}
bool String::operator<(const String& t)const {
size_t n;
m_size < t.m_size ? n = m_size : n = t.m_size;
return strncmp(m_data, t.m_data, n) < 0;
}
bool String::operator>(const String& t)const {
size_t n;
m_size < t.m_size ? n = m_size : n = t.m_size;
return strncmp(m_data, t.m_data, n) > 0;
}
bool String::operator<=(const String& t)const {
//size_t n;
//m_size < t.m_size ? n = m_size : n = t.m_size;
//return strncmp(m_data, t.m_data, n) < 0 || m_size == t.m_size && !strncmp(m_data, t.m_data, n);
return *this < t || *this == t;
}
bool String::operator>=(const String& t)const {
//size_t n;
//m_size < t.m_size ? n = m_size : n = t.m_size;
//return strncmp(m_data, t.m_data, n) > 0 || m_size == t.m_size && !strncmp(m_data, t.m_data, n);
return *this > t || *this == t;
}
bool String::operator==(const String& t)const {
size_t n;
m_size < t.m_size ? n = m_size : n = t.m_size;
return m_size == t.m_size && !strncmp(m_data, t.m_data, n);
}
bool String::operator!=(const String& t)const {
//size_t n;
//m_size < t.m_size ? n = m_size : n = t.m_size;
//return m_size != t.m_size || !strncmp(m_data, t.m_data, n);
return !(*this == t);
}
bool String::operator<(const char* s)const {
if (s == nullptr) {
assert(false);
}
size_t n = strlen(s);
m_size < n ? n = m_size : n;
return strncmp(m_data, s, n) < 0;
}
bool String::operator>(const char* s)const {
if (s == nullptr) {
assert(false);
}
size_t n = strlen(s);
m_size < n ? n = m_size : n;
return strncmp(m_data, s, n) > 0;
}
bool String::operator<=(const char* s)const{
if (s == nullptr) {
assert(false);
}
return *this < s || *this == s;
}
bool String::operator>=(const char* s)const{
if (s == nullptr) {
assert(false);
}
return *this > s || *this == s;
}
bool String::operator==(const char* s)const{
if (s == nullptr) {
assert(false);
}
size_t L = strlen(s);
size_t n;
m_size < L ? n = m_size : n = L;
return m_size == strlen(s) && !strncmp(m_data, s, n);
}
bool String::operator!=(const char* s)const{
if (s == nullptr) {
assert(false);
}
return !(*this == s);
}
bool operator<(const char* t1, const String& t2) {
if (t1 == nullptr) {
assert(false);
}
/*size_t n;
size_t size = strlen(t1);
size < t2.m_size ? n = size : n = t2.m_size;
return strncmp(t1, t2.m_data, n) < 0;*/
return t2 > t1;
}
bool operator>(const char* t1, const String& t2) {
if (t1 == nullptr) {
assert(false);
}
/*size_t n;
size_t size = strlen(t1);
size < t2.m_size ? n = size : n = t2.m_size;
return strncmp(t1, t2.m_data, n) > 0;*/
return t2 < t1;
}
bool operator<=(const char* t1, const String& t2){
if (t1 == nullptr) {
assert(false);
}
return t2 >= t1;
/*size_t n;
size_t size = strlen(t1);
size < t2.m_size ? n = size : n = t2.m_size;
return strncmp(t1, t2.m_data, n) < 0 || size == t2.m_size && !strncmp(t1, t2.m_data, n);*/
}
bool operator>=(const char* t1, const String& t2){
if (t1 == nullptr) {
assert(false);
}
return t2 <= t1;
/*size_t n;
size_t size = strlen(t1);
size < t2.m_size ? n = size : n = t2.m_size;
return strncmp(t1, t2.m_data, n) > 0 || size == t2.m_size && !strncmp(t1, t2.m_data, n);*/
}
bool operator==(const char* t1, const String& t2){
if (t1 == nullptr) {
assert(false);
}
/*size_t n;
size_t size = strlen(t1);
size < t2.m_size ? n = size : n = t2.m_size;
return size == t2.m_size && !strncmp(t1, t2.m_data, n);*/
return t2 == t1;
}
bool operator!=(const char* t1, const String& t2){
if (t1 == nullptr) {
assert(false);
}
//return !(t1 == t2);
return !(t2 == t1);
}
test.h
#pragma once
#include"string.h"
void test1();
void test2();
void test3();
void test4();
void test5();
test.cpp
#include"test.h"
void test1() {
cout << "test1()\n\n";
String s;
s = "bcd";
String s1;
s1 = "abcdefghijklmn";
cout << s.size() << endl;
cout << s.capacity() << endl;
s.resize(30, 'c');
cout << s.capacity() << endl;
s.empty() ? cout << "s为空\n" : cout << "s不为空\n";
cout << s1.find('c') << endl;
cout << s1.find("nop") << endl;
cout << s1.find(s) << endl;
cout << s << endl;
s.clear();
s.empty() ? cout << "s为空\n" : cout << "s不为空\n";
cout << s << endl;
system("pause");
system("cls");
}
void test2() {
cout << "test2()\n\n";
String s;
s = "bcd";
String s1;
s1 = "abcdefghijklmn";
String s2("rst");
String s3(s2);
String s4(5, 'z');
cout << "s: " << s << endl;
cout << "s1: " << s1 << endl;
cout << "s2 :" << s2 << endl;
cout << "s3 :" << s3 << endl;
cout << "s4 :" << s4 << endl;
s1 += 'o';
cout << "s1: " << s1 << endl;
s1 += "pq";
cout << "s1: " << s1 << endl;
s1 += s2;
cout << "s1: " << s1 << endl;
s1 = "字母" + s1;
cout << "s1: " << s1 << endl;
s1 = s1 + "uv";
cout << "s1: " << s1 << endl;
String s5 = "wx";
s1 = s1 + s5;
cout << "s1: " << s1 << endl;
const char* c_s = s1.c_str();
cout << "c_S: ";
for (size_t i = 0; i < s1.size(); ++i) {
cout << c_s[i];
}
cout << endl;
String::Iterator begin = s1.begin();
String::Iterator end = s1.end();
String s6(s1.begin(), s1.end());
String s8;
s8.append(s2.begin(), s2.end());
cout << "s6: " << s6 << endl;
cout << "s8: " << s8 << endl;
system("pause");
system("cls");
}
void test3() {
cout << "test3()\n\n";
String s1;
s1 = "abcdefghijklmn";
const char* c_s2 = "lmn";
const char* c_s3 = "abcf";
const char* c_s4 = "ghi";
String s2(c_s2);
String s3(c_s3);
String s4(c_s4);
cout << "s1 :" << s1 << endl;
cout << "s2 :" << s2 << endl;
cout << "s3 :" << s3 << endl;
cout << "s4 :" << s4 << endl;
cout << "c_s2 :" << c_s2 << endl;
cout << "c_s3 :" << c_s3 << endl;
cout << "c_s4 :" << c_s4 << endl;
char c1 = 'd';
char c2 = 'z';
cout << s1.find(c1) << endl;
cout << s1.find(c2) << endl;
cout << s1.find(c_s2) << endl;
cout << s1.find(c_s3) << endl;
cout << s1.find(c_s4) << endl;
cout << s1.find(s2) << endl;
cout << s1.find(s3) << endl;
cout << s1.find(s4) << endl;
cout << s1.rfind(s2, s1.size()) << endl;
cout << s1.rfind(s3, s1.size()) << endl;
cout << s1.rfind(s4, s1.size()) << endl;
cout << s1.substr(10, 10) << endl;
String s10;
s10 = "123456789";
cout << s10.substr(3, 7) << endl;
cout << s10.substr(10, 7) << endl;
system("pause");
system("cls");
}
void test4() {
cout << "test4()\n\n";
String s1 = "abcde";
String s2 = "abc";
String s3 = "cde";
String s4(s1);
cout << "s1: " << s1 << endl;
cout << "s2: " << s2 << endl;
cout << "s3: " << s3 << endl;
cout << "s4: " << s4 << endl;
s1 < s2 ? cout << "s1<s2\n" : cout << "s1>=s2\n";
s3 > s2 ? cout << "s3>s2\n" : cout << "s3<=s2\n";
s1 <= s2 ? cout << "s1<=s2\n" : cout << "s1>s2\n";
s3 >= s2 ? cout << "s3>=s2\n" : cout << "s3<s2\n";
s1 == s4 ? cout << "s1==s4\n" : cout << "s1!=s4\n";
s1 != s2 ? cout << "s1!=s2\n" : cout << "s1==s2\n";
const char* c_s1 = s1.c_str();
const char* c_s2 = s2.c_str();
const char* c_s3 = s3.c_str();
const char* c_s4 = s4.c_str();
cout << "c_s1: " << c_s1 << endl;
cout << "c_s2: " << c_s2 << endl;
cout << "c_s3: " << c_s3 << endl;
cout << "c_s4: " << c_s4 << endl;
s1 < c_s2 ? cout << "s1<c_s2\n" : cout << "s1>=c_s2\n";
s3 > c_s2 ? cout << "s3>c_s2\n" : cout << "s3<=c_s2\n";
s1 <= c_s2 ? cout << "s1<=s2\n" : cout << "s1>s2\n";
s3 >= c_s2 ? cout << "s3>=s2\n" : cout << "s3<s2\n";
s1 == c_s4 ? cout << "s1==c_s4\n" : cout << "s1!=c_s4\n";
s1 != c_s2 ? cout << "s1!=c_s2\n" : cout << "s1==c_s2\n";
cout << "\n\n\n";
c_s2 > s1 ? cout << " c_s2>s1\n" : cout << "c_s2<=s1\n";
c_s2 < s3 ? cout << " c_s2<s3\n" : cout << "c_s2>=s3\n";
c_s2 >= s1 ? cout << "c_s2>=s1\n" : cout << "c_s2<s1\n";
c_s2 <= s3 ? cout << "c_s2<=s3\n" : cout << "c_s2>s3\n";
c_s4 == s1 ? cout << "c_s4==s1\n" : cout << "c_s4!=s1\n";
c_s2 != s1 ? cout << "c_s2!=s1\n" : cout << "c_s2==s1\n";
system("pause");
system("cls");
}
void test5() {
cout << "test5()\n\n";
String s1;
cout << "请输入s1\n";
cin >> s1;
cout << "s1: " << s1 << endl;
String s2;
cout << "请输入s2\n";
getline(cin, s2);
cout << "s2: " << s2 << endl;
cout << "请输入s2, #结束\n";
getline(cin, s2, '#');
cout << "s2: " << s2 << endl;
system("pause");
system("cls");
}
main.cpp
#include"string.h"
#include"test.h"
int main() {
test1();
test2();
test3();
test4();
test5();
return 0;
}