C++ string类和常用接口的实现

目录

 

                  C++ string类

string类的常用接口说明

         string类(实现常用接口)


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);输入运算符重载, 输入字符串
getlineistream& 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;
}

 

  • 8
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
string_view和string都是C++ STL中的字符串型,但它们有着不同的特点和用途。 stringC++常用的字符串型,它是一个可变长的字符串容器,可以动态增加或删除字符。它存储的字符串是一个连续的字符数组,可以通过下标或迭代器进行访问和修改。string支持很多字符串操作,如查找、替换、插入、删除、子串等。 string_view是C++17新增的型,它是一个不可变的字符串视图。它本质上是一个只包含指向原始字符串的指针和长度信息的结构体,它不拥有原始字符串的内存空间,也不会对原始字符串进行修改。它主要用于读取和处理字符串,可以提高程序的效率和安全性。string_view可以用于任何可以转换为const char*的型,如string、字符数组、字面量等。 下面是string_view和string的区别和联系: 1. 内存管理方式不同:string拥有自己的内存空间,而string_view不拥有内存空间,只是指向原始字符串的一个视图。 2. 可变性不同:string是可变的,可以修改字符串内容;而string_view是不可变的,只能读取字符串内容。 3. 使用场景不同:string_view主要用于只读操作,可以提高程序效率和安全性,特别是在处理大量字符串时。而string则适用于需要频繁修改字符串的场景。 4. 接口相似:string_view和string都支持似的操作,如查找、比较、子串等。 总之,string_view和string都是C++常用的字符串型,它们各有优点和适用场景。在实际编程中,可以根据需要选择合适的字符串型。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值