首页 > 编程语言 >【C++】vector的使用和模拟实现

【C++】vector的使用和模拟实现

时间:2024-06-19 22:57:50浏览次数:26  
标签:finish start pos C++ v1 vector 模拟 size

❤️欢迎来到我的博客❤️

前言

vector示可变大小数组的序列容器
就像数组一样,vector也采用的连续存储空间来存储元素

既然都是数组并且都可以动态增长那么vector能不能替代string呢?
答案是不能

原因如下:
string和vector在结构上有所不同
不同点:string要求末尾有’\0’(自动添加),而vector并不要求有’\0’(虽然可以手动添加,但并不是所有人都这么做,所以这个方法是不靠谱的)
string兼容C语言并且string的接口比vector更丰富,比如+=和比较大小,vector没有这些接口, vector也可以实现比较大小,但是vector的比较大小是没有意义的
所以string和vector都是有各自存在的价值的

万物皆可模板化(只要是确定的类型),所以vector可以存string

void test()
{
	//方法一
	vector<string> v;
	string name("十一");
	v.push_back(name);

	//方法二(匿名对象)
	v.push_back(string("十一"));

	//方法三(单参数的构造函数支持隐式类型转换)
	v.push_back("十一");
}

vector的使用

在这里插入图片描述

构造


构造并初始化n个val
在这里插入图片描述

void test2()
{
	//构造并初始化n个val
	vector<int> v1(10, 1);
	vector<string> v2(10, "xxx");

	for (auto a : v1)
	{
		cout << a << " ";
	}
	cout << endl;

	for (auto a : v2)
	{
		cout << a << " ";
	}
	cout << endl;
}

在这里插入图片描述


使用迭代器构造

void test2()
{
	//构造并初始化n个val
	vector<int> v1(10, 1);

	for (auto a : v1)
	{
		cout << a << " ";
	}
	cout << endl;

	//使用迭代器进行初始化构造
	//自己类型的迭代器
	vector<int> v2(v1.begin(), v1.end());
	for (auto a : v2)
	{
		cout << a << " ";
	}
	cout << endl;

	//其他容器的迭代器
	string str("xxxx xxxx");
	vector<char> v3(str.begin(), str.end());
	for (auto a : v3)
	{
		cout << a << " ";
	}
	cout << endl;

	//数组指针
	int a[] = { 1,2,3,4,5 };
	vector<int> v4(a, a + 5);
	for (auto a : v4)
	{
		cout << a << " ";
	}
	cout << endl;
}

在这里插入图片描述


排序

在这里插入图片描述

void test2()
{
	int a[] = { 2,123,5,12,83 };
	vector<int> v4(a, a + 5);
	for (auto a : v4)
	{
		cout << a << " ";
	}
	cout << endl;

	//排序(需要<algorithm>头文件)
	//默认升序 <
	sort(v4.begin(), v4.end());
	for (auto a : v4)
	{
		cout << a << " ";
	}
	cout << endl;
	
	//降序 > (需要传类对象,库里有一个greater)
	//也可以用反向迭代器
	sort(v4.begin(), v4.end(), greater<int>());
	for (auto a : v4)
	{
		cout << a << " ";
	}
	cout << endl;
}

在这里插入图片描述


其他类型也可以排序

void test2()
{
	//其他容器的迭代器
	string str("xxxx xxxx");
	vector<char> v3(str.begin(), str.end());

	//数组指针
	int a[] = { 5,2,1,3,4 };
	vector<int> v4(a, a + 5);
	
	//排序string
	sort(str.begin(), str.end());
	cout << str << endl;

	//排序数组
	sort(a, a + 5);
	for (auto e : a)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述


vector的空间

容量空间接口说明
size获取数据个数
capacity获取容量大小
empty判断是否为空
resize改变vector的size
reserve改变vector的capacity

reserve的错误用法:

void test3()
{
	vector<char> v1;
	v1.reserve(10);
	for (size_t i = 0; i < 10; i++)
	{
		v1[i] = i;
	}
}

运行结果:
在这里插入图片描述
可以看到代码报错了,错误是数组越界
这是因为 [] 会检查越界
在这里插入图片描述
所以我们这里不能直接使用[]进行访问,而是使用push_back代码就能正常的运行了

void test3()
{
	vector<int> v1;
	v1.reserve(10);
	for (size_t i = 0; i < 10; i++)
	{
		v1.push_back(i);
	}
}

或者是使用resize

void test3()
{
	vector<int> v1;
	v1.resize(10);
	for (size_t i = 0; i < 10; i++)
	{
		v1[i] = i;
	}
}

resize在开空间的同时还会进行初始化,影响size
reserve只是把空间开好了,是为了避免扩容(或减少扩容)提高效率
reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题(提高效率)

vector的扩容逻辑

//vector的扩容逻辑
void test()
{
	size_t sz;
	vector<int> v;
	sz = v.capacity();
	cout << "making v grow:\n";
	for (int i = 0; i < 100; ++i) 
	{
		v.push_back(i);
		if (sz != v.capacity()) 
		{
			sz = v.capacity();
			cout << "capacity: " << sz << '\n';
		}
	}
}

运行结果:

在这里插入图片描述

vs下capacity是按1.5倍增长的,g++是按2倍增长的


增删查改

vector接口说明
push_back尾插
pop_back尾删
find查找(注:这个是算法模块实现,不是vector的成员接口)
insert在position之前插入val
erase删除position位置的数据
swap交换两个vector的数据空间
operator[]像数组一样访问

使用方法演示:

void test3()
{
	vector<int> v1;
	v1.resize(10);
	for (size_t i = 0; i < 10; i++)
	{
		v1[i] = i;
	}

	//头删
	v1.erase(v1.begin());
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	//头插
	v1.insert(v1.begin(), 20);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	//删除第2个数据
	v1.erase(v1.begin() + 1);
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;

	//查找并删除
	//(如果找不到返回last(最后一个数据的下一个位置)
	vector<int>::iterator pos = find(v1.begin(), v1.end(), 9);
	if (pos != v1.end())
	{
		v1.erase(pos);
	}

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

这里的find是算法模块实现的,不是vector的成员接口:
在这里插入图片描述
如果我们有很多个相同的数据,并且都要删除,那应该怎么办呢

void test4()
{
	int a[] = { 1,2,3,3,3,3,3,3,3,10 };
	vector<int> v1(a, a + sizeof(a) / sizeof(int));
	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
	
	//删除所有的3
	auto pos = find(v1.begin(), v1.end(), 3);

	while (pos != v1.end())
	{
		v1.erase(pos);
		pos = find(pos + 1, v1.end(), 3);
	}

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

运行效果:
在这里插入图片描述
这种写法看起来没什么问题,但是为什么程序会崩溃呢?
因为这里的迭代器失效了,当我们把pos位置删除了之后,迭代器就会失效,迭代器失效了之后如果我们再进行使用就会出现问题
迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装,比如:vector的迭代器就是原生态指针T*。因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)

解决方法:
每次都从头查找,但效率会比较低

	auto pos = find(v1.begin(), v1.end(), 3);

	while (pos != v1.end())
	{
		v1.erase(pos);
		//pos = find(pos + 1, v1.end(), 3);
		//修改为:
		pos = find(v1.begin(), v1.end(), 3);
	}

vector存放其他对象

vector<vector< int >>

在这里插入图片描述

vector< string >

在这里插入图片描述


练习

了解了vector之后,我们来使用vector做两道练习题

在这里插入图片描述

比如我们输入"258",那么
2对应的字母就是: a b c
5对应的字母就是: j k l
8对应的字母就是: t u v
不难看出,这个结构很像一颗多叉树,那么我们可以使用递归来解决这道题

在这里插入图片描述

题目给我们的是一个数字串,那我们首先需要根据数字串找到他对应的字母串
可以定义一个数组,存放数字所对应的字母串,然后再取出数字对应的字母串进行排列组合

class Solution {
    string a[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
public:
    //i - 层数
    //combinestr - 组合成的字符串
    void Combine(string digits, int i, string combinestr, vector<string>& v)
    {
        //当层数i和size相等的时候,组合就结束了
        if(i == digits.size())
        {
            //组合成的字符串存放到vector中,退回到上一层
            v.push_back(combinestr);
            return;
        }

        //减去字符'0'才是我们需要的数字
        int num = digits[i] - '0';
        //取数字对应的字符串
        string str = a[num];
        //依次取所有的字母
        for(size_t j = 0;j < str.size();++j)
        {
            //跟下一层组合
            Combine(digits,i+1,combinestr + str[j],v);
        }
    }

    vector<string> letterCombinations(string digits) {
        vector<string> v;
        //判断digits是否为空,为空返回
        if(digits.empty())
        {
            return v;
        }
        Combine(digits,0,"",v);
        return v;
    }
};

假设digits为"258",递归图如下:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


vector的模拟实现

接下来我们要模拟实现vector的部分功能
在空间申请方面我们使用new delete实现
基本框架:
在这里插入图片描述

namespace Vector
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		
		//普通迭代器
		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}
		
		//const迭代器
		const_iterator begin() const
		{
			return _start;
		}

		const_iterator end() const
		{
			return _finish;
		}

		vector()
			:_start(nullptr)
			,_finish(nullptr)
			,_endofstorage(nullptr)
		{}

		~vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = nullptr;
				_finish = nullptr;
				_endofstorage = nullptr;
			}
		}

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				//保存旧空间
				size_t sz = size();
				//开n个空间
				T* tmp = new T[n];
				//原空间不为空,拷贝数据
				if (_start)
				{
					memcpy(tmp, _start, sizeof(T) * sz);
					//释放旧空间
					delete[] _start;
				}
				//指向新空间
				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

		void push_back(const T& x)
		{
			//判断是否满
			if (_finish == _endofstorage)
			{
				//扩容
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);
			}

			//赋值
			*_finish = x;
			++_finish;
		}

		//获取capacity的大小
		size_t capacity() const
		{
			return _endofstorage - _start;
		}

		//获取size大小
		size_t size() const
		{
			return _finish - _start;
		}

	private:
		iterator _start;
		iterator _finish;
		iterator _endofstorage;
	};

	void test1()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);
		v1.push_back(5);

		for (auto e : v1)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

现在我们的vector已经可以跑起来了,我们接着实现其他的功能

[]

T& operator[](size_t pos)
{
	assert(pos < size());
	//返回pos位置的值
	return _start[pos]; 
}

const T& operator[](size_t pos) const
{
	assert(pos < size());
	//返回pos位置的值
	return _start[pos];
}

insert

//注:vector的insert用的是迭代器,不是下标
void insert(iterator pos, const T& x)
{
	assert(pos >= _start && pos <= _finish);

	//判断容量
	if (_finish == _endofstorage)
	{
		//扩容
		size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
		reserve(newcapacity);
	}

	//挪动数据
	iterator end = _finish - 1;
	while (end >= pos)
	{
		*(end + 1) = *end;
		--end;
	}

	//pos位置插入数据
	*pos = x;
	++_finish;
}

我们来试着调用insert

void test()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);

	v1.insert(v1.begin(), 100);

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述
可以正常调用,但如果我们让vector的数字更多一点

void test()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	v1.push_back(5);
	v1.push_back(6);
	v1.push_back(7);
	v1.push_back(8);


	v1.insert(v1.begin(), 100);

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

在这里插入图片描述
可以看到,虽然我们的代码没有报错,但是我们需要的100并没有被添加进去,还多了一个随机值出来,引发这个问题的原因是因为迭代器失效了

迭代器失效

如果没有进行扩容操作,那么我们的insert是可以正常使用的,但是一旦有扩容迭代器就会失效
在这里插入图片描述

我们只需要在扩容的时候更新一下pos即可

//判断容量
if (_finish == _endofstorage)
{
	//计算pos相对位置
	size_t len = pos - _start;

	//扩容
	size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
	reserve(newcapacity);

	//更新pos
	pos = _start + len;
}

我们这只是解决了内部迭代器失效的问题,外部的迭代器在使用的时候一定要谨慎

void test()
{
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	
	vector<int>::iterator p = v1.begin() + 3;
	v1.insert(p, 300);
	//insert之后就不要使用这个形参迭代器了,因为他有可能已经失效了
	*p += 10;//危险!有可能失效了(扩容之后就会失效)

	for (auto e : v1)
	{
		cout << e << " ";
	}
	cout << endl;
}

并没有进行+=操作,因为迭代器已经失效了
在这里插入图片描述

erase

erase比较简单,只需要挪动数据就行了

iterator erase(iterator pos)
{
	assert(pos >= _start && pos < _finish);

	iterator it = pos + 1;
	while (it != _finish)
	{
		*(it - 1) = *it;
		++it;
	}
	--_finish;
	
	//返回删除前pos的后一个数据
	return pos;
}

vector在使用erase和insert迭代器对象后,不能再访问这个迭代器
我们认为他失效,访问结果是未定义

push_back和pop_back

这两个我们可以直接复用insert和erase

void push_back(const T& x)
{
	判断是否满
	//if (_finish == _endofstorage)
	//{
	//	//扩容
	//	size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
	//	reserve(newcapacity);
	//}

	赋值
	//*_finish = x;
	//++_finish;

	//直接复用insert
	insert(end(), x);
}

void pop_back()
{
	erase(--end());
}

resize

void resize(size_t n, const T& val = T())
{
	//1.resize小于原空间
	if (n < size())
	{
		_finish = _start + n;
	}
	else
	{
		//resize大于原空间
		resever(n);

		//添加数据
		while (_finish != _strat + n)
		{
			*_finish = val;
			++_finish;
		}
	}
}

拷贝构造

//深拷贝
vector(const vector<T>& v)
	:_start(nullptr)
	,_finish(nullptr)
	,_endofstorage(nullptr)
{
	_start = new T[v.capacity()];
	for (size_t i = 0; i < v.size(); i++)
	{
		_start[i] = v._start[i];
	}
	
	_finish = _start + v.size();
	_endofstorage = _start + v.capacity();
}

另一种写法:

vector(const vector<T>& v)
	:_start(nullptr)
	,_finish(nullptr)
	,_endofstorage(nullptr)
{
	reserve(v.capacity());
	for (auto e : v)
	{
		push_back(e);
	}
}

赋值:

void swap(vector<T>& v)
{
	std::swap(_start, v._start);
	std::swap(_finish, v._finish);
	std::swap(_endofstorage, v._endofstorage);
}

//赋值 - v1 = v2
vector<T>& operator=(vector<T> v)
{
	swap(v);
	return *this;
}

但是我们这里还会存在一个问题,虽然vector是深拷贝了,但是vector里的对象并不是深拷贝,比如vector< string >
vector是深拷贝
但是vector空间上存的对象是string的数组
使用memcpy导致string对象浅拷贝了,所以我们还需要对reserve进行修改

修改为:

void reserve(size_t n)
{
	if (n > capacity())
	{
		size_t sz = size();
		T* tmp = new T[n];
		if (_start)
		{
			//memcpy(tmp, _start, sizeof(T) * sz);
			//修改为
			for (size_t i = 0; i < sz; i++)
			{
				tmp[i] = _start[i];
			}

			delete[] _start;
		}

		_start = tmp;
		_finish = _start + sz;
		_endofstorage = _start + n;
	}
}

原理:如果T是string这样的深拷贝的类,调用的是string赋值重载,实现的string对象的深拷贝

n个val初始化

vector(size_t n, const T& val = T())
	:_start(nullptr)
	, _finish(nullptr)
	, _endofstorage(nullptr)
{
	resize(n, val);
}

vector(int n, const T& val = T())
	:_start(nullptr)
	, _finish(nullptr)
	, _endofstorage(nullptr)
{
	resize(n, val);
}

使用迭代器区间初始化:

//一个类模板还可以再套一个模板
//[first,last)
template<class InputIterator>
vector(InputIterator first, InputIterator last)
{
	while (first != last)
	{
		push_back(*first);
		++first;
	}
}

完整代码

#pragma once
#include<iostream>
#include<assert.h>

using namespace std;

namespace Vector
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;

		iterator begin()
		{
			return _start;
		}

		iterator end()
		{
			return _finish;
		}

		const_iterator begin() const
		{
			return _start;
		}

		const_iterator end() const
		{
			return _finish;
		}

		vector(size_t n, const T& val = T())
			:_start(nullptr)
			, _finish(nullptr)
			, _endofstorage(nullptr)
		{
			resize(n, val);
		}

		//一个类模板还可以再套一个模板
		//[first,last)
		template<class InputIterator>
		vector(InputIterator first, InputIterator last)
		{
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		vector()
			:_start(nullptr)
			,_finish(nullptr)
			,_endofstorage(nullptr)
		{}

		//深拷贝
		vector(const vector<T>& v)
			:_start(nullptr)
			,_finish(nullptr)
			,_endofstorage(nullptr)
		{
			reserve(v.capacity());
			for (auto e : v)
			{
				push_back(e);
			}
		}

		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_endofstorage, v._endofstorage);
		}

		//赋值 - v1 = v2
		vector<T>& operator=(vector<T> v)
		{
			swap(v);
			return *this;
		}

		~vector()
		{
			if (_start)
			{
				delete[] _start;
				_start = nullptr;
				_finish = nullptr;
				_endofstorage = nullptr;
			}
		}

		void reserve(size_t n)
		{
			if (n > capacity())
			{
				size_t sz = size();
				T* tmp = new T[n];
				if (_start)
				{
					//memcpy(tmp, _start, sizeof(T) * sz);
					//修改为
					for (size_t i = 0; i < sz; i++)
					{
						tmp[i] = _start[i];
					}

					delete[] _start;
				}

				_start = tmp;
				_finish = _start + sz;
				_endofstorage = _start + n;
			}
		}

		void resize(size_t n, const T& val = T())
		{
			//1.resize小于原空间
			if (n < size())
			{
				_finish = _start + n;
			}
			else
			{
				//resize大于原空间
				reserve(n);

				//添加数据
				while (_finish != _start + n)
				{
					*_finish = val;
					++_finish;
				}
			}
		}

		void push_back(const T& x)
		{
			判断是否满
			//if (_finish == _endofstorage)
			//{
			//	//扩容
			//	size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
			//	reserve(newcapacity);
			//}

			赋值
			//*_finish = x;
			//++_finish;

			//直接复用insert
			insert(end(), x);
		}

		void pop_back()
		{
			erase(--end());
		}

		//获取capacity的大小
		size_t capacity() const
		{
			return _endofstorage - _start;
		}

		//获取size大小
		size_t size() const
		{
			return _finish - _start;
		}

		T& operator[](size_t pos)
		{
			assert(pos < size());
			//返回pos位置的值
			return _start[pos]; 
		}

		const T& operator[](size_t pos) const
		{
			assert(pos < size());
			//返回pos位置的值
			return _start[pos];
		}

		//注:vector的insert用的是迭代器,不是下标
		iterator insert(iterator pos, const T& x)
		{
			assert(pos >= _start && pos <= _finish);

			//判断容量
			if (_finish == _endofstorage)
			{
				//计算pos相对位置
				size_t len = pos - _start;

				//扩容
				size_t newcapacity = capacity() == 0 ? 4 : capacity() * 2;
				reserve(newcapacity);

				//更新pos
				pos = _start + len;
			}

			//挪动数据
			iterator end = _finish - 1;
			while (end >= pos)
			{
				*(end + 1) = *end;
				--end;
			}

			//pos位置插入数据
			*pos = x;
			++_finish;

			return pos;
		}

		iterator erase(iterator pos)
		{
			assert(pos >= _start && pos < _finish);

			iterator it = pos + 1;
			while (it != _finish)
			{
				*(it - 1) = *it;
				++it;
			}
			--_finish;
			
			//返回删除前pos的后一个数据
			return pos;
		}


	private:
		iterator _start;
		iterator _finish;
		iterator _endofstorage;
	};


	void test()
	{
		vector<int> v1;
		v1.push_back(1);
		v1.push_back(2);
		v1.push_back(3);
		v1.push_back(4);

		vector<string> v2;
		v2.push_back("1111111111111111111111111111111111");
		v2.push_back("1111111111111111111111111111111111");
		v2.push_back("1111111111111111111111111111111111");
		v2.push_back("1111111111111111111111111111111111");
		v2.push_back("1111111111111111111111111111111111");

		vector<string> v3(v2);

		for (auto e : v3)
		{
			cout << e << " ";
		}
		cout << endl;
	}
}

总结

以上就是本篇文章的全部内容了,希望大家看完能有所收获

❤️创作不易,点个赞吧❤️

标签:finish,start,pos,C++,v1,vector,模拟,size
From: https://blog.csdn.net/2402_85096248/article/details/139815025

相关文章

  • C++ Windows Hook使用
    GitHub-microsoft/Detours:DetoursisasoftwarepackageformonitoringandinstrumentingAPIcallsonWindows.Itisdistributedinsourcecodeform./*挂载钩子setdll/d:C:\Users\g\source\repos\LotTest\Release\lotDll.dllC:\Users\g\source\repo......
  • 基于QT和C++实现的中国象棋
    一,源码board.h#ifndefBOARD_H#defineBOARD_H#include<QWidget>#include"Stone.h"classBoard:publicQWidget{Q_OBJECTpublic:explicitBoard(QWidget*parent=0);bool_bRedTurn;//红方先走int_currentPlayer;//当前玩......
  • 模拟集成电路设计系列博客——7.2.3 每阶段k-bit流水线ADC
    7.2.3每阶段k-bit流水线ADC通过增加中间级增益和每级的比较器可以在每级解析多于1比特。信号流图类似之前介绍的每次迭代2比特的逐次逼近型ADC。一个通用的k比特级如下图所示:k比特副ADC的非线性可以通过增加额外的比较器通过数字方式来校正,类似于每级1.5比特架构[Lewis,1992]......
  • C++学习(22)
    #学习自用#计时计时可以计算出执行代码时花费了多长时间,对于同样的目的,我们可以通过不同的代码实现,而执行时间长短是评价一串代码性能如何的指标。#include<iostream>#include<string>#include<chrono>#include<thread>usingnamespacestd;intmain(){ autostar......
  • C/C++ 对文件目录进行操作的常用函数
    在C语言中,对目录进行操作的常用函数主要包括但不限于以下几个:opendir(constchar*name):功能:打开指定路径的目录。返回值:成功时返回一个指向DIR结构体的指针,失败则返回NULL。头文件:<dirent.h>readdir(DIR*dirp):功能:从打开的目录中读取下一个目录条目。返回值:成......
  • 总公司与分公司跨区域互连,如何用Cisco Packet Tracer模拟实现呢?
    需求说明:某企业有公司总部和分公司且两个距离较远。公司总部及分公司的主机IP地址不在同一个网段,所有的信息端口连接在各自的的交换机上。因分公司要访问公司总部服务器的数据,这就要求公司总部与分公司之间要实现跨区域的互连互通,究竟如何才能实现呢?需求分析:如果是局域网中......
  • 使用VLAN,实现网络间的安全隔离,竟用Cisco Packet Tracer Student 6.2 模拟实现?
    需求说明:某企业网络未扩建前经常有网络不稳定的情况,想通过升级改造对网络在逻辑上进行安全隔离,来保证网络有效稳定运行。技术部和市场部各有计算机10台,所有计算机通过双绞线连接到交换机上,IP地址也在同一网段。企业负责人要求在不改变现有网络连接方式及IP地址的情况下,将两个......
  • YC303C [ 20240617 CQYC省选模拟赛 T3 ] Generals(generals)
    题意给定一张\(n\timesm\)的地图。对于第\(0\)列,第\(m+1\)列,第\(0\)行,第\(n+1\)行,有\(2n+2m\)个人,每个人面朝地图中心。每个人走到别人染过色的位置,或走出地图,将走过的地方染色。你需要求出共有多少种本质不同的染色方案。\(n,m\le10^6\)Sol直接......
  • centos7离线升级gcc , 报错:/lib64/libstdc++.so.6: version `CXXABI_1.3.8' not found
     因为需要依赖gcc高版本但是目前服务器版本是4.8.5的然后服务器又是内网所以只能离线升级gcc 分别下载https://ftp.gnu.org/gnu/gcc/gcc-8.3.0/gcc-8.3.0.tar.gzhttps://ftp.gnu.org/pub/gnu/gmp/gmp-6.1.0.tar.bz2https://ftp.gnu.org/gnu/mpc/mpc-1.0.3.tar.gzhttp:......
  • 解决《模拟山羊》游戏启动问题:缺失wxmsw28u_core_vc_custom.dll的终极指南
    在沉浸于《模拟山羊》那荒诞不经、充满乐趣的游戏世界之前,你可能遭遇了一个小小的障碍——游戏启动时弹出错误提示,指出系统缺少一个名为“wxmsw28u_core_vc_custom.dll”的关键文件。别担心,这并非罕见问题,而且解决起来比你想象的要简单。本文将手把手教你如何跨越这个小障碍,确......