新号别搞:string


1. string 使用


1.1 string 头文件+链接

  • #include头文件以及using namespace std

https://cplusplus.com/reference/string/string/?kw=stringhttps://cplusplus.com/reference/string/string/?kw=string


1.2 auto和范围for


1.2.1 auto

auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器, auto声明的变量必须由编译器在编译时期推导而得。

  • 用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&
  • 当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个进行推导,然后用推导出来的类型定义其他变量
  • auto不能作为函数的参数,可以做返回值,但是建议谨慎使用
  • auto不能直接用来声明数组

1.2.2 范围for

for循环后的括号由冒号" :"分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围,自动迭代,自动取数据,自动判断结束

  • 可以作用到数组和容器对象上进行遍历
  • 底层很简单,容器遍历实际就是替换为迭代器,从汇编层也可以看到。

1.3 string类的常用接口


1.3.1 对象的常见构造


1.3.2 对象的容量操作


1.3.4 对象的访问及遍历操作


1.3.5 对象的修改操作


1.3.6 非成员函数


2. 模拟实现


2.1 string.h

cpp 复制代码
class string {
public:
	//迭代器
	typedef char* iterator;
	typedef const char* const_iterator;

	iterator begin() { return _str; }
	iterator end() { return _str + _size; }

	const_iterator begin()const { return _str; }
	const_iterator end()const { return _str + _size; }

	string();//默认构造
	string(const char* str);//字符串构造
	string(const string& s);//拷贝构造(深拷贝)
	string& operator=(const string& s);//拷贝赋值
	~string();
	//reverse 反转
	//resize(size,可能连capacity一起改)
	void reserve(size_t n);//扩容(capacity)
	void push_back(char ch);//尾插
	void append(const char* str);//追加
	string& operator+=(char ch);//单字符+=
	string& operator+=(const char* str);//字符串+=
	void insert(size_t pos, char ch);//插入(挪动数据)
	void insert(size_t pos, const char* str);
	void erase(size_t pos = 0, size_t len = string::npos);//删除(挪动数据)
	size_t find(char ch, size_t pos = 0)const;//(内容)查找位置
	size_t find(const char* s, size_t pos = 0)const;
	string substr(size_t pos = 0,size_t len=npos)const;//(位置)查找内容
	void swap(string& s);

	const char* c_str()const { return _str; }//将string对象转换成const char*
	size_t size() const { return _size; }
	size_t capacity() const { return _capacity; }
	//下标
	char& operator[](size_t pos) {
		assert(pos < _size);
		return _str[pos];
	}
	const char& operator[](size_t pos)const {
		assert(pos < _size);
		return _str[pos];
	}
	static const size_t npos = -1;
	//string & operator<(char ch);
	//string& operator<(const char* str);
private:
	char* _str;
	size_t _size;
	size_t _capacity;//存储有效字符空间大小,不包含最后\0(实际空间>capacity 1个bite)
};
cpp 复制代码
string operator+(const string& lhs, const string& rhs);
string operator+(const string& lhs, const char* rhs);
string operator+(const char* lhs, const string& rhs);

bool operator==(const string& lhs, const string& rhs);
bool operator!=(const string& lhs, const string& rhs);
bool operator>(const string& lhs, const string& rhs);
bool operator<(const string& lhs, const string& rhs);
bool operator>=(const string& lhs, const string& rhs);
bool operator<=(const string& lhs, const string& rhs);

ostream& operator<<(ostream& out, const string& s);
istream& operator>>(istream& in, string& s);
istream& getline(istream& in, string& s);
	
void swap(zyl::string& s1, zyl::string& s2);


2.2 接口实现


构造

cpp 复制代码
string::string()//默认构造
	:_str(new char[1])
	, _size(0)
	, _capacity(0) {
	_str[0] = '\0';
}
string::string(const char* str)//字符串构造
	:_size(strlen(str)) {
	_str = new char[_size + 1];
	_capacity = _size;
	strcpy(_str, str);
}
string::string(const string& s)//拷贝构造(深拷贝)
	:_str(new char[s._capacity + 1])
	, _size(s._size)
	, _capacity(s._capacity) {
	strcpy(_str, s._str);
}

operator= / 析构

cpp 复制代码
string& string::operator=(const string& s) {
	if (this != &s) {
		delete[]_str;
		_str = new char[s._capacity + 1];
		strcpy(_str, s._str);
		_size = s._size;
		_capacity = s._capacity;
	}
	return *this;
}
string::~string() {
	delete[]_str;
	_str = nullptr;
	_size = _capacity = 0;
}

operator+=

cpp 复制代码
string& string::operator+=(char ch) {
	push_back(ch);
	return *this;
}
string& string::operator+=(const char* str) {
	append(str);
	return *this;
}

reserve

cpp 复制代码
void string::reserve(size_t n) {//扩容(capacity)
	if (n > _capacity) {
		// 每次开空间多开一个,因为_capacity不包含\0
		char* tmp = new char[n + 1];
		strcpy(tmp, _str);
		delete[] _str;
		_str = tmp;
		_capacity = n;
	}
}

push_back

cpp 复制代码
void string::push_back(char ch) {
	// 扩容
	if (_size == _capacity) {
		reserve(_capacity == 0 ? 4 : _capacity * 2);
	}

	_str[_size] = ch;
	++_size;
	_str[_size] = '\0';
}

append

cpp 复制代码
void string::append(const char* str) {//追加
	size_t len = strlen(str);

	// 扩容
	if (_size + len > _capacity) {
		reserve(_size + len);
	}

	strcpy(_str + _size, str);
	_size += len;
}

insert

cpp 复制代码
void string::insert(size_t pos, const char* str) {
	assert(pos <= _size);
	size_t len = strlen(str);

	// 扩容
	if (_size + len > _capacity) {
		reserve(_size + len);
	}
	//挪动数据
	//int end = _size;
	//while (end >= (int)pos) {
	//	_str[end + len] = _str[end];
	//	--end;
	//}
	size_t end = _size + len;
	while (end > pos) {
		_str[end] = _str[end - len];
		--end;
	}
	for (size_t i = 0; i < len; i++) {
		_str[pos + i] = str[i];
	}
	_size += len;
}

void string::insert(size_t pos, char ch) {  //插入(挪动数据)
	assert(pos <= _size);
	if (_size == _capacity) {//扩容
		reserve(_capacity == 0 ? 4 : _capacity * 2);
	}
	//挪动数据
	//int end = _size;
	//while (end >= (int)pos) {
	//	_str[end + 1] = _str[end];
	//	--end;
	//}
	size_t end = _size + 1;
	while (end > pos) {
		_str[end] = _str[end - 1];
		--end;
	}
	_str[pos] = ch;
	_size++;
}

erase

cpp 复制代码
void string::erase(size_t pos, size_t len) {//删除(挪动数据)
	if (pos > _size) pos = _size;
	if (len == string::npos || len >= _size - pos) {
		_str[pos] = '\0';
		_size = pos;
	}
	else {
		for (size_t i = pos + len; i < _size; ++i) {
			_str[pos++] = _str[i];
		}
		_size -= len;
	}
}

find

cpp 复制代码
size_t string::find(char ch, size_t pos)const {//(内容)查找位置
	assert(pos < _size);
	for (size_t i = pos; i < _size; i++) {
		if (_str[i] == ch)
			return i;
	}
	return npos;
}
size_t string::find(const char* s, size_t pos)const {
	const char* ptr = strstr(_str + pos, s);
	if (ptr == nullptr)
		return npos;
	else
		return ptr - _str;
}

substr / swap

cpp 复制代码
string string::substr(size_t pos, size_t len)const {//(位置)查找内容,构造返回
	if (pos > _size) pos = _size;
	if (len == string::npos || len >= _size - pos)
		len = _size - pos;
	string sub;
	sub.reserve(len);
	for (size_t i = 0; i < len; ++i) {
		sub += _str[pos + i];
	}
	return sub;
}
void string::swap(string& s) {
	std::swap(_str, s._str);
	std::swap(_size, s._size);
	std::swap(_capacity, s._capacity);
}

++operator + / == / != / > / < / >= / <=++

cpp 复制代码
string operator+(const string& lhs, const string& rhs) {
	string ret(lhs);//复制lhs
	ret += rhs.c_str();//再追加转换成const char*的rhs
	return ret;
}
string operator+(const string& lhs, const char* rhs) {
	string ret(lhs);
	ret += rhs;
	return ret;
}
string operator+(const char* lhs, const string& rhs) {
	string ret(lhs);
	ret += rhs.c_str();
	return ret;
}
bool operator==(const string& lhs, const string& rhs) {
	return strcmp(lhs.c_str(), rhs.c_str()) == 0;
}
bool operator!=(const string& lhs, const string& rhs) {
	return !(lhs == rhs);
}
bool operator>(const string& lhs, const string& rhs) {
	return strcmp(lhs.c_str(), rhs.c_str()) > 0;
}
bool operator<(const string& lhs, const string& rhs) {
	return strcmp(lhs.c_str(), rhs.c_str()) < 0;
}
bool operator>=(const string& lhs, const string& rhs) {
	return !(lhs < rhs);
}
bool operator<=(const string& lhs, const string& rhs) {
	return !(lhs > rhs);
}

operator << / >>

cpp 复制代码
ostream& operator<<(ostream& out, const string& s) {
	for (auto ch : s) {
		out << ch;
	}
	return out;
}
istream& operator>>(istream& in, string& s) {
	//char ch;
	//ch = in.get();//读取单个字符
	//while (ch != ' ' && ch != '\n') {
	//	s += ch;
	//	ch = in.get();
	//}
	//return in;
	s.erase();
	char ch;
	ch = in.get();
	char buff[128];
	int i = 0;
	while (ch != ' ' && ch != '\n') {
		buff[i++] = ch;
		if (i == 127) {
			buff[i] = '\0';
			s += buff;
			i = 0;
		}
		ch = in.get();
	}
	if (i > 0) {
			buff[i] = '\0';
			s += buff;
	}
	return in;
}

getline

cpp 复制代码
istream& getline(istream& in, string& s) {
	char ch;
	ch = in.get();
	while (ch != '\n') {
		s += ch;
		ch = in.get();
	}
	return in;
}

swap

cpp 复制代码
void swap(zyl::string& s1, zyl::string& s2) {
	s1.swap(s2);
}

相关推荐
xh didida1 小时前
Linux -- 进程概念
linux·服务器·开发语言·c++
凉茶钱1 小时前
【C++】string 常用函数详解
开发语言·c++·string
(Charon)2 小时前
【C++面试】程序崩溃如何定位:从Segmentation fault到GDB、Core Dump与ASan
开发语言·c++
汉克老师2 小时前
GESP2026年9月认证C++七级( 第三部分编程题(1、必经之路))精讲
c++·gesp·小学生·学c++编程
ebiobiz2 小时前
Zig 嵌入式底层库选择与 build.zig 组织指南
c语言·c++·嵌入式硬件·mcu
漂流瓶jz3 小时前
UVA-11491 奖品的价值 题解答案代码 算法竞赛入门经典第二版
c++·算法·图论·题解·aoapc·算法竞赛入门经典·uva
weixin_307779137 小时前
C++代码实现MATLAB中的dlarray函数功能
开发语言·c++·算法·matlab
Frank_refuel11 小时前
C++11之一场名为“搬家”的 C++ 之旅
开发语言·c++
hetao173383713 小时前
2026-10-03~04 hetao1733837 的刷题记录
c++·算法