今天没写什么,主要想的是写点简单有用的算法,人均能看的懂的,一个对于裸数组的删除操作与动态数组的情况和有序序列的去重操作
template<typename T, size_t size> //普通数组版本删除元素,效率很低的方式,按照下标删除
void erase(T(&v)[size], int lo)
{
for (int i = lo; i < size - 1; i++)
{
v[i] = v[i + 1];
v[i + 1] = 0;
}
}
template<typename T> //提供一个动态数组版本
void earse(T*& p, int size, int lo)
{
T* temp = new T[size - 1];
for (int i = lo; i < size - 1; i++)
{
p[i] = p[i + 1];
p[i + 1] = 0;
}
std::copy_if(p, p + size, temp, [](T a) {return a != 0; });
delete[]p;
p = temp;
}
//去除有序序列重复项vector版本,低效方式,时间复杂度O(n^2)
template<typename T>
int uniquify(std::vector<T>& v) {
int oldSize = v.size(); int i = 0;
while (i < v.size() - 1) {
if (v[i] == v[i + 1]) {
v.erase(v.begin() + i);
}
else {
i++;
}
}
return oldSize - v.size();
}
//我们提供一个高明的O(n)的方式
template<typename T>
int uniquify2(std::vector<T>& v) {
int i = 0, j = 0;
while (++j < v.size())
if (v[i] != v[j])v[++i] = v[j];
v.resize(++i);
return j - i;
}
//裸数组版本,把重复的替换为0放到后面,动态数组另说
template<typename T, size_t size>
int uniquify2(T(&v)[size]) {
int i = 0, j = 0;
while (++j < size)
if (v[i] != v[j])v[++i] = v[j];
std::fill(std::begin(v) + i, std::end(v), 0);
return j - i - 1;
}
}
有兴趣的可以看看之前的文章,有一说一我觉得一般人是看不懂,先这样吧,明天对文件的命名空间增加更多操作,目前来说是下面这样的
amespace file_ {
//获取当前时间的字符串
std::string time_() {
time_t timep;
time(&timep);
char tmp[256];
strftime(tmp, sizeof(tmp), "%Y年%m月%d日_%H点%M分%S秒", localtime(&timep));
std::string s{ tmp };
return s;
}
//创建文件夹,默认在同级目录
std::string newFolder(std::string name = time_(), std::string path = "") {
std::string temp = "md ";
temp += path;
temp += name;
//std::cout << "创建文件夹 " << temp << std::endl;
system(temp.data());
return temp.substr(3);
}
//删除文件夹
std::string deleteFolber(std::string path) {
std::string s = "rd ";
system((s += path).data());
return s.substr(3);
}
//以追加模式打开写文件
std::string newWriteFile(std::string name = time_()+=".txt", std::string data = time_(), std::string path = "") {
path += name;
std::ofstream ofs;
ofs.open(path, std::ios::app);
ofs << data;
ofs.close();
return path;
}
//创建新的文件写入,一开始有就删除再创建
void newlyFile(std::string name = time_(), std::string data = time_(), std::string path = "") {
path += name;
std::ofstream ofs;
ofs.open(path, std::ios::trunc);
ofs << data;
ofs.close();
}
//删除文件的数据
void deleteData(std::string name ,std::string path = "") {
path += name;
std::ofstream ofs(path, std::ios::trunc);
ofs.close();
}
//删除文件
bool deleteFile(std::string path) {
if (remove(path.data()) == 0) {
//std::cout << "删除成功" << std::endl;
return true;
}
else {
std::cout << "删除失败" << std::endl;
return false;
}
}
//读取文件
std::string readFile(std::string path) {
std::ifstream ifs;
ifs.open(path, std::ios::in);
if (!ifs.is_open())
{
std::cout << "文件打开失败" << std::endl;
return "";
}
std::string data{};
while (ifs >> data);
ifs.close();
return data;
}
//打印输出
void print(std::string path) {
show_::print(readFile(path));
}
}
还有很多的改进空间,说起改进空间,不得不提到之前写的print,已经写到死了,已经无法再重载,匹配不到,如下
namespace show_ {
template<typename T,size_t i>
void print(const T(&n)[i], const std::string s=" ") {
std::copy(std::begin(n),std::end(n), std::ostream_iterator<T, char>(std::cout, s.data()));
std::cout << std::endl;
}
template<typename T,size_t size>
void print(const std::array<T,size> v, const std::string s = " ") {
std::copy(std::begin(v), std::end(v), std::ostream_iterator<T, char>(std::cout, s.data()));
std::cout << std::endl;
}
void print(const char* s) {
std::cout << s << std::endl; //重载特殊情况,字符串常量输出
}
template<typename T>
void print(const std::vector<T>n,const std::string s=" ") {
std::copy(std::begin(n), std::end(n), std::ostream_iterator<T, char>(std::cout, s.data()));
std::endl(std::cout);
}
template<typename T>
void print(T v) {
std::cout << v << std::endl;
}
template<typename T>
void print(const std::list<T>& L,std::string s=" ") {
for (auto it = L.begin(); it != L.end(); it++) { //list容器版本
std::cout << *it << s;
}
std::cout << std::endl;
}
template<typename _Type1, typename _Type2, typename... _Types>
void print(_Type1 _Value1, _Type2 _Value2, _Types... _Values)//c++17折叠表达式
requires (sizeof...(_Types) > 0 || (!std::is_same_v<char*, _Type2> && !std::is_same_v<const char*, _Type2>))//requires是c++20的
{
std::cout << _Value1 << ' ' << _Value2 << " ";
((std::cout << _Values ), ...);
}
namespace object { //这真是无奈之举,这个匹配,object命名空间内的除了遍历vector和array的数组外,标准数据类型直接打印也可行
template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& data)
{
for (auto& str : data)
{
os << str<<" ";
}
return os;
}
template<typename T, size_t size>
std::ostream& operator<<(std::ostream& os, const std::array<T, size>& data)
{
for (auto& str : data)
{
os << str<<",";
}
return os;
}
void print() {}
template<typename T, typename...Types>
void print(T first, Types...args) {
std::cout << first << '\n';
print(args...);
return;
}
}
namespace range { //没办法重载多了就是匹配问题,我能这里使用c++20的range
void print_impl(std::ostream& out, std::ranges::range auto&& r)
{
for (auto&& elem : r)
{
out << elem << " ";
}
std::cout << std::endl;
}
void print_impl(std::ostream& out, auto&& elem)
{
out << elem << " ";
std::cout << std::endl;
}
void print(auto&&...args)
{
(print_impl(std::cout, args), ...);
}
}
namespace rangeClass { //也可以写成一个类,主要是为了防止让print_impl暴露在外部接口,因为print同名的缘故所以我们无法写在一起
class print {
public:
void operator()(auto&&...args)
{
(print_impl(std::cout, args), ...);
}
private:
void print_impl(std::ostream& out, std::ranges::range auto&& r)
{
for (auto&& elem : r)
{
out << elem << " ";
}
std::cout << std::endl;
}
void print_impl(std::ostream& out, auto&& elem)
{
out << elem << " ";
std::cout << std::endl;
}
};
}
}
已经没有兴趣再去改它了,继续去增加别的库吧,纯当记录
开发环境:MSVC C++20 debug x64,使用了众多特性,各位可以去https://zh.cppreference.com/w/cpp/language查询