1 实现Str类(不可管理内存)
本次实现是在之前编写Vec类的基础上进行。当然也可以在vector类的基础上进行。
1.1 构造函数
Str的默认构造函数隐式调用Vec类的默认构造函数,生成一个空的Str类型对象。由于Str类还有其他的构造函数,因此显示定义默认构造函数是必要的。
值得注意的是最后一个构造函数是一个模版函数。由于是模版函数,因此它实际上是定义了一组构造函数,随着不同类型的迭代器实例化出不同的构造函数。
例如,这个构造函数可以用于被从一个字符数组构造一个Str类型对象,也可以从Vec<char>类型对象构造Str类型对象。
class Str{
public:
typedef Vec<char>::size_type
//构造函数
//默认构造函数,创建一个空的Str
Str(){}
//生成一个Str对象,包含c的n个副本
Str(size_type n, char c):data(n,c){}
//生成一个Str对象并使用一个空字符结尾的字符数组来初始化
Str(const char* cp){
std::copy(cp, cp+std::strlen(cp), std::back_inserter(data));
}
//生成一个Str对象并使用迭代器b和e之间的内容对它进行初始化
template<class In>Str(In b, In e){
std::copy(b, e, std::back_inserter(data));
}
private:
Vec<char> data;
}
构造函数中还实现了类型转换,通过Str(const char* )构造函数将const char*类型的字符串数组转换为Str类型对象。
例如:
Str s;
s = "hello"
这个表达式中,编译器实际上调用Str(const char* )构造函数为这个字符串字面量构造一个没有名称、局部的、临时的Str类型对象,然后在调用编译器自动生成的赋值运算符函数将这个一临时值赋给s。
1.2 复制构造函数、赋值运算符函数、析构函数
Str类本身没有分配内存的能力,它将管理内存的细节留给了编译器,编译器将自动生成相应的函数,而这些函数通过调用Vec中的相应函数进行操作。
通常一个不需要析构函数的类,也不需要定义复制构造函数或赋值操作符函数。
1.3 重载运算符函数
1.3.1 索引运算符函数
索引运算符函数必须是成员函数。定义了两个版本的索引运算符,一个可以对返回的字符进行写操作,另一个不能对之进行修改。
class Str{
public:
char& operator[](size_t i){return data[i];}
const char& operator[](size_t i) const{return data[i];}
private:
Vec<char> data;
}
1.3.1 输出运算符函数
判断一个函数是否应该是成员函数时,一般判断的方法是看这个函数是否会改变对象的状态。
输入运算符函数当然会改变对象的状态,因为它在使用输入操作时会将一个新值重新读入已存在的对象。
对于二元运算符函数,其左操作数必须作为函数的第一个参数,右操作数必须作为函数的第二个参数。如果该运算算符函数是成员函数,那么第一个参数(也就是左操作数)总是会默认传递给该成员函数。
如果将输入运算符作为成员函数,会引发下面的效果:
我们希望的是:
cin >> s;
//等价于
cin.operator >> (s);
它调用了对象cin的被重载的>>运算符。这种行为暗示着>>运算符必须是istream的一个成员。
由于我们没有权限修改istream的定义,也就不能将这个操作添加到它里面。
如果我们将operator>>作为Str的一个成员,那么用户将不得不用如下的方式来对Str进行输入操作:
实际效果:
s.operator >> (cin);
//等价于
s >> cin;
这与整个库的语法规则不同,因此输入函数不能作为类的成员函数。输出函数也是一样的。
继续完善Str类:
//类外添加声明
std::ostream& operator>>(std::ostream&, Str&);
定义
ostream& operator<<(ostream& os, const Str& s){
for(Str::size_type i = 0;i != s.size();++i)
os << s[i];
return os;
}
1.3.2 输入运算符函数
它需要从输入流中读出 字符并将其存储起来。每次使用输入运算符的时候,会忽略开头的空格佛祖,然后连续读出其他字符并存储起来,直到遇到另一个空格字符或遇到一个文件结尾标志为止。
istream& operator>>(istream& is, Str s){
//抹去存在的值
s.data.clear();//私有成员
//按序读入字符并忽略前面的空格字符
char c;
//只判断循环,为的是清楚前面的空白
while(is.get(c) && isspace(c));
//如果读到非空格字符,重复以上操作直到遇到一个空格字符为止
if(is){
do s.data.push_back(c);//私有成员
while(is.get(c) && !isspace(c));
//如果遇到一个空格字符,将它放在输入流的后面
if(is)
is.unget;//取消最近一次从输入流中读取一个字符的操作
}
}
继续完善Str类:
//类外添加声明
std::istream& operator>>(std::istream&, Str&);
如果这样话,私有成员那两条语句或报错,因为operator>>不是成员函数,不能访问s的私有成员data。如果为data写一个存取器函数,这不能满足要求。因为我们要将像data写入新的数值,不满足只读的要求。
因此我们需要用到友元函数。友元函数拥有与成员函数相同的访问权利。
友元函数的声明可以加在类定义的任何地方:将它加在private标识后面与加在public标示后面没有任何区别。由于友元函数具有特殊的访问权利,因此它是类接口的一部分。一般会将全部友元函数的声明放在一起作为一个相对独立的组。
class Str{
friend std::istream& operator>>(std::istream&, Str&);
}
1.3.3 复合加法赋值运算符函数
由于+=运算符函数会改变运算符的左操作数,因此将它写成成员函数。
class Str{
public:
Str& operator += (const Str& s){
std::copy(s.data.begin(),s.data.end(),std::back_inserter(data));
return *this;/间接引用,返回对象
}
}
1.3.4 加法运算符函数
由于加法运算符函数没有改变左右两个操作数,因此把它写成非成员函数。
首先定义一个局部变量r,然后将其初始化为s的一个副本来生成一个新的Str类型对象,这个初始话过程中用到了Str的复制构造函数,然后调用+=运算副函数,将r与t连接作为r的新值。最后返回r(再次因此调用复制构造函数)作为结果。
Str operator+ (const Str& s, const Str& t){
Str r = s;
r += t;
return r;
}
对于
Str name = "jiangxueHan"
Str greeting = "Hello,"+name+"!";
等同于下面
Str temp1(""Hello");//Str::Str(const char*)
Str temp 2 = temp1 + name;;//operator(const Str&,const Str&);
Str temp3("!");//Str::Str(const char*)
Str S = temp2 + temp3;//operator+(const Str&, const Str&)
由于operator+函数的参数两个都是Str类型,因此遇到混合类型表达式的时候,每次都要调用构造函数将const char*类型转换为Str类型,这样会导致代码用到大量的临时变量,因此这种方法是非常消耗内存的。实际上,真正标准库的string类不是依赖于类型转换实现混合类型的操作数相加,而是重置改加号运算符,为每一种可能的操作数类型的连接定义一个版本。
1.4 汇总代码
// 使用memory管理内存
// Created by MacBook Pro on 2020-03-17.
//
#ifndef ACM_STR_H
#define ACM_STR_H
#include "Vec.h"
#include <iostream>
class Str{
friend std::istream& operator>>(std::istream&, Str&);
public:
//实现+=运算符
Str& operator += (const Str& s){
std::copy (s.data.begin(), s.data.end(), std::back_inserter(data));
return *this;
}
typedef Vec<char>::size_type size_type;
//默认构造
Str(){}
//生成一个Str对象,包含c的n个副本
Str(size_type n, char c):data(n,c){}//使用Vec类中的构造函数构造data数据
//生成一个Str对象并使用一个空字符结尾的字符数组来初始化
Str(const char* cp){
std::copy(cp, cp + std::strlen(cp), std::back_inserter(data));
}
//生成一个Str对象并使用迭代器b和e之间的内容对他进行初始化
template<class In>Str (In b, In e){
std::copy(b, e, std::back_inserter(data));
}
//大小
size_type size() const { return data.size();}
//索引
char& operator[](size_type i) { return data[i];}
const char &operator[](size_type i) const { return data[i];}
private:
Vec<char> data;
};
//输入运算符
std::istream& operator>>(std::istream&, Str&);
//输出运算符
std::ostream& operator<<(std::ostream&, const Str&);
//加号运算符
Str operator+(const Str&, const Str&);
//输出运算符定义
std::ostream& operator<<(std::ostream& os, const Str& s){
for (Str::size_type i = 0; i != s.size(); ++i) {
os << s[i];
}
return os;
}
//输入运算符的定义
std::istream& operator>>(std::istream& is, Str& s){
//抹去存在的值(s)
s.data.clear();
//按序读字符并忽略前面的空格字符
char c;
//值进行循环条件,不进行其他工作
while(is.get(c) && isspace(c));
//读入非空白字符
if(is){
do{
s.data.push_back(c);//直到遇到一个空格字符或超出输入范围
}while(is.get(c) && !isspace(c));
//如果遇到一空格字符,将它放在输入流的后面
if(is){
is.unget();
}
}
return is;
}
//加号运算符的定义
Str operator+ (const Str& s, const Str& t){
Str r = s;
r += t;
return r;
}
#endif //ACM_STR_H
2 Str_c(自行管理内存)
2.1 构造函数
public:
typedef size_t size_type;
typedef char* iterator;
typedef const char* const_iterator;
//构造
//默认构造
Str_c(){create(0,'\0');}
//复制构造
Str_c(const Str_c& s){create(s.begin(), s.end());}
//带参构造(长度、字符)
Str_c(size_type n, char c){create(n,c);}
//带参构造(迭代器始末)
template<class In> Str_c( In b, In e){create(b,e);}
//带参构造(类型转换)
Str_c(const char* cp){create(cp, cp + std::strlen(cp));}
private:
char* d;//指向字符串的第一个字符的指针
char* avail;//指向最后一个有值的字符后面两位的指针
char* limit;//指向字符串的最后一个字符后面的指针
std::allocator<char> alloc;
//构造函数调用
void create(size_type, char);
template <class In> void create(In,In);
定义:
void Str_c::create(Str_c::size_type n, char c) {
d = alloc.allocate(n + 1);
limit = avail = d + n + 1;
std::uninitialized_fill(d, d + n, c);
// alloc.construct(data + n, '\0');
}
template <class In>
void Str_c::create(In b, In e) {
d = alloc.allocate(e - b + 1);//多分配一个长度存储空白字符
limit = avail = std::uninitialized_copy(b, e, d) + 1;//指向e的后面两个为止(后面还多一个空白字符)
}
2.2 赋值运算符函数
public:
//赋值运算符
Str_c& operator=(const Str_c&);
Str_c& operator=(const char*);
定义:
Str_c& Str_c::operator=(const Str_c &s) {
if(&s != this){
uncreate();
create(s.begin(),s.end());
}
return *this;
}
Str_c& Str_c::operator=(const char *s) {
uncreate();
create(s, s + strlen(s));
return *this;
}
2.3 析构函数
public:
//析构函数
~Str_c(){uncreate();}
private:
//析构函数
void uncreate();
void Str_c::uncreate() {
if(avail != 0){
iterator it = avail;
while(it != d){
alloc.destroy(--it);
}
alloc.deallocate(d, limit - d);
}
d = avail = limit = 0;
}
2.4 运算符函数
2.4.1 索引运算符
public:
char& operator[](size_type i){ return d[i];}
const char&operator[](size_type i) const{ return d[i];}
2.4.2 复合加法赋值运算符
public:
//复合加法赋值运算符
Str_c& operator+=(const char* cp){
append(cp, std::strlen(cp));
return *this;
}
Str_c&operator+=(const Str_c& s){
append(s);
return *this;
}
private:
//复合加法赋值运算符
void append(const char*, const size_type);
void append(const char);
void append(const Str_c&);
void prepend(const char*, const size_type);
void Str_c::append(const char* str, const Str_c::size_type n) {
size_type new_length = n + size() + 1;//加入字符串后的长度
if(limit == avail || avail + n >= limit){
ptrdiff_t room = 2 * (limit - d);
while(size_type(room) < new_length){//直到分配的空间可以容纳加入后的字符串
room *= 2;
}
size_type new_size = std::max(room, std::ptrdiff_t(1));
iterator new_data = alloc.allocate(new_size);
std::uninitialized_copy(str, str + std::strlen(str),
std::uninitialized_copy(d, d + size(),new_data));
uncreate();
d = new_data;
avail = new_data + new_length;
limit = new_data + new_size;
}else{
std::uninitialized_copy(str, str + std::strlen(str),
d + size());
avail = d + new_length;
}
}
void Str_c::prepend(const char* str, const Str_c::size_type n) {
size_type new_length = n + size() + 1;//加入的字符串的长度
if(limit == avail || avail + n >= limit){
std::ptrdiff_t room = 2 * (limit - d);
while(size_type(room) < new_length){
room *= 2;
}
size_type new_size = std::max(room, std::ptrdiff_t(1));
iterator new_data = alloc.allocate(new_size);
std::uninitialized_copy(d, d + size(),
std::uninitialized_copy(str, str + std::strlen(str),new_data));
uncreate();
d = new_data;
avail = new_data + new_length;
limit = new_data + new_size;
}else{
std::uninitialized_copy(d, d + size(),
std::uninitialized_copy(str, str + std::strlen(str),d));
avail = d + new_length;
}
}
void Str_c::append(const char c) {
append(&c, 1);
}
void Str_c::append(const Str_c &str) {
append(str.d, str.size());
}
2.4.3 加法运算符
friend Str_c operator+(const char* , const Str_c& );
Str_c operator+(const Str_c& s, const Str_c& t){
Str_c r = s;
r += t;
return r;
}
Str_c operator+(const Str_c& s, const char* t){
Str_c r = s;
r += t;
return r;
}
Str_c operator+(const char* t, const Str_c& s){
Str_c r = s;
r.prepend(t, strlen(t));
return r;
}
2.4.4 比较操作符函数
inline bool operator==(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) == 0;
}
inline bool operator!=(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) != 0;
}
inline bool operator>(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) > 0;
}
inline bool operator>=(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) >= 0;
}
inline bool operator<(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) < 0;
}
inline bool operator<=(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) <= 0;
}
2.4.5 输入运算符
friend std::istream& operator>>(std::istream&, Str_c&);
std::istream& operator >>(std::istream& is, Str_c& s){
s.clear();
char c;
//按序读字符并忽略前面的空格字符
while(is.get(c) && isspace(c));
//读入非空白字符
if(is){
do{
s.append(c);
}while(is.get(c) && !isspace(c));
}
//如果遇到一空格字符,将它放在输入流的后面
if(is){
is.unget();
}
return is;
}
2.4.6 输出运算符
std::ostream& operator<<(std::ostream& os, Str_c& s){
std::copy(s.begin(), s.end(), std::ostream_iterator<char>(os));
return os;
}
2.5 操作数函数
public:
//操作函数
operator void*() const{return is_not_empty();}
private:
//操作函数
void* is_not_empty() const{ return size() > 0 ? d : 0;}
2.6 clear()
public:
//清空
void clear(){destory();}
private:
//clear
void destory();
void Str_c::destory() {
uncreate();
create(0,'\0');
}
2.7 insert()
public:
//插入元素
void insert(const_iterator , const_iterator , const_iterator);
void insert(size_type pos, const Str_c& s);
void Str_c::insert(Str_c::const_iterator out, Str_c::const_iterator b, Str_c::const_iterator e) {
ptrdiff_t dis = e - b;
dis = size_type (dis);
ptrdiff_t pos = out - d;
pos = size_type (pos);
if(pos > size()) throw std::domain_error("");//插入位置非法
size_type new_length = dis + size() + 1;//加入字符串后的长度
// size_type container = size_type (limit - d);//容器长度包括未初始化的
if(limit == avail || avail + dis >= limit){
ptrdiff_t room = 2 * (limit - d);
while(size_type(room) < new_length){//直到分配的空间可以容纳加入后的字符串
room *= 2;
}
size_type new_size = std::max(room, std::ptrdiff_t(1));
iterator new_data = alloc.allocate(new_size);
std::uninitialized_copy(d + pos,d +size(),std::uninitialized_copy(b, e,
std::uninitialized_copy(d, d + pos,new_data)));
uncreate();
d = new_data;
avail = new_data + new_length;
limit = new_data + new_size;
}else{
//暂存插入位置后面的内容
char replica[size_type(avail - out)];
std::copy(d + pos,d + size(), replica);
std::uninitialized_copy(replica, replica + std::strlen(replica),std::uninitialized_copy(b, e, d + pos));
avail = d + new_length;
}
}
void Str_c::insert(Str_c::size_type pos, const Str_c &s) {
const_iterator p = d + pos;
insert(p, s.begin(),s.end());
}
2.8 c_str(),data()
public:
//将其Str_c转换为其他类型
const_iterator c_str() const{ return data();};
const_iterator data() const{ return d;}
public:
//copy将int类型的参数指定的个数的字符复制到char*类型的内存中
size_type copy(char* p, size_type n, size_type pos = 0) const { return copy_characters(p, n, pos);}
private:
//copy
size_type copy_characters(char*, size_type, size_type)const;
size_t Str_c::copy_characters(char* s, Str_c::size_type n, Str_c::size_type pos = 0) const {
size_type sz = size();
//其实位置超过字符串的长度,扔出错误
if(pos > size()) throw std::domain_error("Out of range!");
//保证复制的范围不会超过字符串的最大长度
size_type rlen = std::min(n, sz - pos);
std::copy(d+ pos, d+pos+rlen, s);
return rlen;
}
2.9 getline()
friend std::istream& getline(std::istream&, Str_c& );
std::istream& getline(std::istream& is, Str_c& s){
s.uncreate();
s.create(0,'\0');
char c;
if(is){
while (is.get(c) && c != '\n'){
s.append(c);
}
}
return is;
}
2.10 汇总代码
头文件:
//
// Created by MacBook Pro on 2020-03-17.
//
#ifndef ACM_STR_C_H
#define ACM_STR_C_H
#include <cctype>
#include <memory>
#include <algorithm>
#include <iterator>
#include <cstring>
#include <exception>
class Str_c{
friend std::istream& operator>>(std::istream&, Str_c&);
friend Str_c operator+(const char* , const Str_c& );
friend std::istream& getline(std::istream&, Str_c& );
public:
typedef size_t size_type;
typedef char* iterator;
typedef const char* const_iterator;
//构造
//默认构造
Str_c(){create(0,'\0');}
//复制构造
Str_c(const Str_c& s){create(s.begin(), s.end());}
//带参构造(长度、字符)
Str_c(size_type n, char c){create(n,c);}
//带参构造(迭代器始末)
template<class In> Str_c( In b, In e){create(b,e);}
//带参构造(类型转换)
Str_c(const char* cp){create(cp, cp + std::strlen(cp));}
//赋值运算符
Str_c& operator=(const Str_c&);
Str_c& operator=(const char*);
//析构函数
~Str_c(){uncreate();}
//索引运算符
char& operator[](size_type i){ return d[i];}
const char&operator[](size_type i) const{ return d[i];}
//复合加法赋值运算符
Str_c& operator+=(const char* cp){
append(cp, std::strlen(cp));
return *this;
}
Str_c&operator+=(const Str_c& s){
append(s);
return *this;
}
//操作函数
operator void*() const{return is_not_empty();}
//清空
void clear(){destory();}
//插入元素
void insert(const_iterator , const_iterator , const_iterator);
void insert(size_type pos, const Str_c& s);
//将其Str_c转换为其他类型
const_iterator c_str() const{ return data();};
const_iterator data() const{ return d;}
//copy将int类型的参数指定的个数的字符复制到char*类型的内存中
size_type copy(char* p, size_type n, size_type pos = 0) const { return copy_characters(p, n, pos);}
//字符串长度,不包括\0
size_type size() const{ return avail - d - 1;}
//始末迭代器
iterator begin(){ return d;}
const_iterator begin() const{ return d;}
iterator end() { return d + size();}
const_iterator end() const{ return d + size();}
private:
char* d;//指向字符串的第一个字符的指针
char* avail;//指向最后一个有值的字符后面两位的指针
char* limit;//指向字符串的最后一个字符后面的指针
std::allocator<char> alloc;
//构造函数调用
void create(size_type, char);
template <class In> void create(In,In);
//析构函数
void uncreate();
//clear
void destory();
//复合加法赋值运算符
void append(const char*, const size_type);
void append(const char);
void append(const Str_c&);
void prepend(const char*, const size_type);
//copy
size_type copy_characters(char*, size_type, size_type)const;
//操作函数
void* is_not_empty() const{ return size() > 0 ? d : 0;}
};
void Str_c::create(Str_c::size_type n, char c) {
d = alloc.allocate(n + 1);
limit = avail = d + n + 1;
std::uninitialized_fill(d, d + n, c);
// alloc.construct(data + n, '\0');
}
template <class In>
void Str_c::create(In b, In e) {
d = alloc.allocate(e - b + 1);//多分配一个长度存储空白字符
limit = avail = std::uninitialized_copy(b, e, d) + 1;//指向e的后面两个为止(后面还多一个空白字符)
}
void Str_c::uncreate() {
if(avail != 0){
iterator it = avail;
while(it != d){
alloc.destroy(--it);
}
alloc.deallocate(d, limit - d);
}
d = avail = limit = 0;
}
void Str_c::append(const char* str, const Str_c::size_type n) {
size_type new_length = n + size() + 1;//加入字符串后的长度
if(limit == avail || avail + n >= limit){
ptrdiff_t room = 2 * (limit - d);
while(size_type(room) < new_length){//直到分配的空间可以容纳加入后的字符串
room *= 2;
}
size_type new_size = std::max(room, std::ptrdiff_t(1));
iterator new_data = alloc.allocate(new_size);
std::uninitialized_copy(str, str + std::strlen(str),
std::uninitialized_copy(d, d + size(),new_data));
uncreate();
d = new_data;
avail = new_data + new_length;
limit = new_data + new_size;
}else{
std::uninitialized_copy(str, str + std::strlen(str),
d + size());
avail = d + new_length;
}
}
void Str_c::prepend(const char* str, const Str_c::size_type n) {
size_type new_length = n + size() + 1;//加入的字符串的长度
if(limit == avail || avail + n >= limit){
std::ptrdiff_t room = 2 * (limit - d);
while(size_type(room) < new_length){
room *= 2;
}
size_type new_size = std::max(room, std::ptrdiff_t(1));
iterator new_data = alloc.allocate(new_size);
std::uninitialized_copy(d, d + size(),
std::uninitialized_copy(str, str + std::strlen(str),new_data));
uncreate();
d = new_data;
avail = new_data + new_length;
limit = new_data + new_size;
}else{
std::uninitialized_copy(d, d + size(),
std::uninitialized_copy(str, str + std::strlen(str),d));
avail = d + new_length;
}
}
void Str_c::append(const char c) {
append(&c, 1);
}
void Str_c::append(const Str_c &str) {
append(str.d, str.size());
}
Str_c& Str_c::operator=(const Str_c &s) {
if(&s != this){
uncreate();
create(s.begin(),s.end());
}
return *this;
}
Str_c& Str_c::operator=(const char *s) {
uncreate();
create(s, s + strlen(s));
return *this;
}
std::istream& operator >>(std::istream& is, Str_c& s){
s.clear();
char c;
//按序读字符并忽略前面的空格字符
while(is.get(c) && isspace(c));
//读入非空白字符
if(is){
do{
s.append(c);
}while(is.get(c) && !isspace(c));
}
//如果遇到一空格字符,将它放在输入流的后面
if(is){
is.unget();
}
return is;
}
std::ostream& operator<<(std::ostream& os, Str_c& s){
std::copy(s.begin(), s.end(), std::ostream_iterator<char>(os));
return os;
}
Str_c operator+(const Str_c& s, const Str_c& t){
Str_c r = s;
r += t;
return r;
}
Str_c operator+(const Str_c& s, const char* t){
Str_c r = s;
r += t;
return r;
}
Str_c operator+(const char* t, const Str_c& s){
Str_c r = s;
r.prepend(t, strlen(t));
return r;
}
void Str_c::destory() {
uncreate();
create(0,'\0');
}
size_t Str_c::copy_characters(char* s, Str_c::size_type n, Str_c::size_type pos = 0) const {
size_type sz = size();
//其实位置超过字符串的长度,扔出错误
if(pos > size()) throw std::domain_error("Out of range!");
//保证复制的范围不会超过字符串的最大长度
size_type rlen = std::min(n, sz - pos);
std::copy(d+ pos, d+pos+rlen, s);
return rlen;
}
inline bool operator==(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) == 0;
}
inline bool operator!=(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) != 0;
}
inline bool operator>(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) > 0;
}
inline bool operator>=(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) >= 0;
}
inline bool operator<(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) < 0;
}
inline bool operator<=(const Str_c& l, const Str_c& r){
return std::strcmp(l.c_str(),r.c_str()) <= 0;
}
std::istream& getline(std::istream& is, Str_c& s){
s.uncreate();
s.create(0,'\0');
char c;
if(is){
while (is.get(c) && c != '\n'){
s.append(c);
}
}
return is;
}
void Str_c::insert(Str_c::const_iterator out, Str_c::const_iterator b, Str_c::const_iterator e) {
ptrdiff_t dis = e - b;
dis = size_type (dis);
ptrdiff_t pos = out - d;
pos = size_type (pos);
if(pos > size()) throw std::domain_error("");//插入位置非法
size_type new_length = dis + size() + 1;//加入字符串后的长度
// size_type container = size_type (limit - d);//容器长度包括未初始化的
if(limit == avail || avail + dis >= limit){
ptrdiff_t room = 2 * (limit - d);
while(size_type(room) < new_length){//直到分配的空间可以容纳加入后的字符串
room *= 2;
}
size_type new_size = std::max(room, std::ptrdiff_t(1));
iterator new_data = alloc.allocate(new_size);
std::uninitialized_copy(d + pos,d +size(),std::uninitialized_copy(b, e,
std::uninitialized_copy(d, d + pos,new_data)));
uncreate();
d = new_data;
avail = new_data + new_length;
limit = new_data + new_size;
}else{
//暂存插入位置后面的内容
char replica[size_type(avail - out)];
std::copy(d + pos,d + size(), replica);
std::uninitialized_copy(replica, replica + std::strlen(replica),std::uninitialized_copy(b, e, d + pos));
avail = d + new_length;
}
}
void Str_c::insert(Str_c::size_type pos, const Str_c &s) {
const_iterator p = d + pos;
insert(p, s.begin(),s.end());
}
#endif //ACM_STR_C_H