C++第十九弹---string模拟实现(下)

个人主页: 熬夜学编程的小林

💗系列专栏: 【C语言详解】 【数据结构详解】【C++详解】

目录

1、修改操作

2、迭代器操作

3、字符串操作 

4、非成员函数重载操作

总结


1、修改操作

1、string& operator+= (const char* s);

//尾部插入字符串s
2、string& operator+= (char c);

//尾部插入字符c
3、void push_back (char c);

//尾部插入字符c
4、string& append (const char* s);

//尾部插入(追加)字符串s
5、void insert(size_t pos, char ch);

//在pos位置插入字符c
6、void insert(size_t pos, const char* str);

//在pos位置插入字符串str
7、void erase(size_t pos, size_t len = npos);

//从pos位置删除n个字符
8、void swap(string& s);

//把字符串数据进行交换

void push_back(char c)
{
	// 扩容 容量为0则固定为4 其他则*2
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : 2 * _capacity);
	}
	_str[_size] = c;//_size下标插入字符c
	++_size;//将大小+1
	_str[_size] = '\0';//字符串最后位置给标志结束的\0
}
void append(const char* s)
{
	//追加字符串首先得判断空间是否足够
	size_t len = strlen(s);
	if (len > _capacity - _size)//空间不够则扩容
	{
		reserve(_size + len);//大小为原大小+插入字符串长度
	}

	strcpy(_str + _size, s);//将要追加的数据拷贝到原数据尾
	_size += len;//更新字符串大小
}
string& operator+=(char c)
{
	push_back(c);//调用尾插字符函数

	return *this;
}
string& operator+=(const char* str)
{
	append(str);
	return *this;
}
void insert(size_t pos, char ch)
{
	assert(pos <= _size);//断言,小于字符串大小才能进行插入操作

	// 扩容
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : 2 * _capacity);
	}
	// end=_size会有无符号与有符号比较问题,因为pos恒大于等于0,end回到-1
	// 无符号与有符号比较 会提升至无符号比较 即end = -1 还会大于pos
	size_t end = _size + 1;
	while (end > pos)//end==pos则循环停止
	{
		_str[end] = _str[end - 1];//将前面的元素往后面一个位置移动
		--end;
	}
	_str[pos] = ch;//pos位置赋值字符ch
	++_size;//更新大小
}

void insert(size_t pos, const char* str)
{
	assert(pos <= _size);//pos小于字符串大小才能进行插入操作

	size_t len = strlen(str);
	if (len > _capacity - _size)//容量不够则扩容
	{
		reserve(_size + len);
	}
	size_t end = _size + len;
	while (end > pos + len - 1)
	{
		_str[end] = _str[end - len];//将原数据向后移动len位置
		--end;
	}
	strncpy(_str + pos, str, len);//不需要拷贝\0因此使用strncpy拷贝len长度到原串
	_size += len;//更新大小
}
void erase(size_t pos, size_t len = npos)
{
	assert(pos < _size);

	if (len == npos || len >= _size - pos)//长度为npos或者大于等于字符串大小-pos即删除整个字符串
	{
		_str[pos] = '\0';//直接在pos位置给\0即可
		_size = pos;//pos为\0下标,刚还为字符串大小
	}
	else//将pos+len位置后的数据拷贝到pos为止
	{
		strcpy(_str + pos, _str + pos + len);
		_size -= len;//更新长度
	}
}
void swap(string& s)//交换类的成员变量即可,
{
	std::swap(_str, s._str);//调用库函数的swap模板函数
	std::swap(_size, s._size);
	std::swap(_capacity, s._capacity);
}

2、迭代器操作

注意:暂时我们理解的迭代器实质为指针,但不完全是指针,此处就通过指针来模拟实现。

typedef char* iterator;//将迭代器定义成char*类型
typedef const char* const_iterator;将迭代器定义成const char*类型


1、const char* begin() const;

//获取指向首元素的const迭代器
2、const char* end() const;

//获取指向尾元素的const迭代器
3、char* begin();

//获取指向首元素的迭代器
4、char* end();

//获取指向尾元素的迭代器

typedef char* iterator;
typedef const char* const_iterator;

const char* begin() const
{
	return (const char*)_str;//返回首元素地址,const修饰因此强转类型
}
const char* end() const
{
	return (const char*)_str + _size;//尾元素下一个位置地址,即\0位置地址
}
char* begin()
{
	return _str;
}
char* end()
{
	return _str + _size;
}

3、字符串操作 

1、const char* c_str() const;

//获取C字符串首元素地址

2、size_t find(char ch, size_t pos = 0) const;

//从pos位置(默认从0位置)找字符ch,找到则返回下标,否则返回npos
3、size_t find(const char* sub, size_t pos = 0) const;

//从字符串sub的pos位置找是否有匹配的字符串,找到则返回第一个元素下标,否则返回npos
4、string substr(size_t pos = 0, size_t len = npos);

//从pos位置截取len长度(默认截取整个字符串)的子串

const char* c_str() const
{
	return _str;//返回首地址
}
size_t find(char ch, size_t pos = 0) const
{
	assert(pos < _size);//小于字符串大小才能进行查找
	for (size_t i = 0; i < _size; i++)//遍历字符串
	{
		if (_str[i] == ch)
			return i;//找到字符则返回下标
	}
	return npos;
}
size_t find(const char* sub, size_t pos = 0) const
{
	assert(pos < _size);
	const char* p = strstr(sub + pos, _str);//从sub+pos位置找,调用C语言库的找子串函数,找到则返回该值的地址,否则返回NULL
	if (p)//不为空则返回下标,指针相减即为相差个数,即下标
	{
		return p - _str;
	}
	else//为空返回npos
	{
		return npos;
	}
}
string substr(size_t pos = 0, size_t len = npos)
{
	assert(pos < _size);
	string sub;
	if (len >= _size - pos)//长度大于_size-pos即将整个字符串截取,也包括len==npos
	{
		for (size_t i = pos; i < _size; i++)
		{
			sub += _str[i];//追加给sub
		}
	}
	else//否则截取len长度
	{
		for (size_t i = pos; i < len + pos; i++)
		{
			sub += _str[i];
		}
	}
	return sub;
}

4、非成员函数重载操作

1、void swap(string& s1, string& s2);

//将类s1数据与类s2数据交换
2、bool operator==(const string& s1, const string& s2);

//比较s1与s2是否相等
3、bool operator<(const string& s1, const string& s2);

//比较s1是否小于s2
4、ostream& operator<<(ostream& out, const string& s);

//流插入,即打印字符串s
5、istream& operator>>(istream& in, string& s);

//流提取,即将输入的内容给s
6、istream& getline(istream& in, string& s);

//获取一行信息,即将输入中回车之前的信息给s

void swap(string& s1, string& s2)
{
	s1.swap(s2);//调用类成员交换函数,跟库函数中交换函数重载,先调用类成员函数
}
bool operator==(const string& s1, const string& s2)
{
	int ret = strcmp(s1.c_str(), s2.c_str());//调用C语言比较字符串函数,等于0则相等
	return ret == 0;
}
bool operator<(const string& s1, const string& s2)
{
	int ret = strcmp(s1.c_str(), s2.c_str());
	return ret < 0;
}

ostream& operator<<(ostream& out, const string& s)
{
	for (auto ch : s)
	{
		out << ch;//用范围for变量类
	}
	return out;
}

istream& operator>>(istream& in, string& s)
{
	s.clear();//清空串s
	char ch = in.get();//C++库中输入函数,读取一个字符给ch
	char buff[128];//先开辟一个128字节空间,减少频繁扩容
	size_t i = 0;
	while (ch != '\n' && ch != ' ')//流提取不识别空格回车
	{
		buff[i++] = ch;//将字符赋值给buff数组
		if (i == 127)//字符串满了则追加给串s
		{
			buff[127] = '\0';//末尾追加标志符\0
			s += buff;
			i = 0;//再重新赋值字符给buff数组
		}
		ch = in.get();
	}
	if (i > 0)//i>0则再追加数据给s
	{
		buff[i] = '\0';
		s += buff;
	}
	return in;
}
istream& getline(istream& in, string& s)
{
	s.clear();
	char ch = in.get();
	char buff[128];
	size_t i = 0;
	while (ch != '\n')//不识别回车,其他原理同流插入
	{
		buff[i++] = ch;
		if (i == 127)
		{
			buff[127] = '\0';
			s += buff;
			i = 0;
		}
		ch = in.get();
	}
	if (i > 0)
	{
		buff[i] = '\0';
		s += buff;
	}
	return in;
}

总结


本篇博客就结束啦,谢谢大家的观看,如果公主少年们有好的建议可以留言喔,谢谢大家啦!

  • 180
    点赞
  • 164
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 153
    评论
好的,以下是一个简单的 C++ 程序,用于模拟实现 Go-back-N 协议: ```c++ #include <iostream> #include <vector> using namespace std; // 数据包结构体 struct Packet { int seq; // 序号 string data; // 数据 }; // 发送方发送数据 void sender(vector<Packet>& packets, int window_size, int timeout) { int next_seq = 0; // 下一个要发送的序号 int base = 0; // 窗口起始位置 int unacked = 0; // 已发送但未确认的数据包数量 // 模拟循环发送数据包 while (true) { // 发送窗口内的未确认数据包 while (unacked < window_size && next_seq < packets.size()) { cout << "发送数据包 " << next_seq << endl; // 模拟发送数据包 // send_packet(packets[next_seq]); next_seq++; unacked++; } // 等待确认或超时 // receive_ack(timeout); // 检查是否有确认 if (unacked > 0) { cout << "等待确认..." << endl; // 模拟接收确认 bool received_ack = true; if (received_ack) { cout << "接收到确认 " << base << endl; base++; unacked--; } else { cout << "未接收到确认,超时重传" << endl; next_seq = base; unacked = 0; } } // 检查是否已发送完毕 if (base == packets.size()) { break; } } } // 接收方接收数据 void receiver(vector<Packet>& packets, int window_size, int timeout) { int expected_seq = 0; // 期望接收的序号 int base = 0; // 窗口起始位置 // 模拟循环接收数据包 while (true) { // 模拟接收数据包 Packet packet; // 接收到的数据包 // receive_packet(packet); // 如果接收到的数据包的序号等于期望接收的序号 if (packet.seq == expected_seq) { cout << "接收到数据包 " << expected_seq << ",并发送确认" << endl; // 模拟发送确认 // send_ack(expected_seq); expected_seq++; base++; // 将窗口向前滑动,以便接收更多数据包 while (packets[base].seq < expected_seq && base < packets.size()) { base++; } } else { cout << "接收到数据包 " << packet.seq << ",但不是期望接收的序号" << endl; // 模拟发送确认 // send_ack(expected_seq - 1); } // 检查是否已接收完毕 if (base == packets.size()) { break; } } } int main() { // 创建数据包 vector<Packet> packets; packets.push_back({0, "Hello"}); packets.push_back({1, "World"}); packets.push_back({2, "Go-back-N"}); packets.push_back({3, "Protocol"}); packets.push_back({4, "Simulation"}); packets.push_back({5, "Example"}); // 设置窗口大小和超时时间 int window_size = 3; int timeout = 500; // 启动发送方和接收方 sender(packets, window_size, timeout); receiver(packets, window_size, timeout); return 0; } ``` 上述程序实现了一个简单的 Go-back-N 协议模拟。在程序中,发送方和接收方都使用了一个循环来模拟数据包的发送和接收过程。在发送过程中,发送方会根据窗口大小和超时时间来控制发送的数据包数量,并等待接收到确认或超时后重传。在接收过程中,接收方会等待接收到数据包后发送确认,并将窗口向前滑动以便接收更多的数据包。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小林熬夜学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值