【c++】——类和对象(中)——实现完整的日期类(优化)万字详细解疑答惑

2023-12-02 11:20

本文主要是介绍【c++】——类和对象(中)——实现完整的日期类(优化)万字详细解疑答惑,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者:chlorine

专栏:c++专栏

赋值运算符重载(+)(+=)(++):实现完整的日期类(上)

我走的很慢,但我从不后退。

【学习目标】

  • 日期(- -= --)天数重载运算符
  • 日期-日期 返回天数
  • 对日期类函数进行优化(不符合常理的日期,负数,const成员)
  • c++中重载输入cin和输出cout运算符
  • const成员

首先我要对上面一篇类和对象(上)进行补充,上一篇主要内容

  • '=' 赋值运算符重载
  • '<'  '='  '>'  '<='  '>='  '!=' 重载运算符
  • '前置++' '后置++’ 重载运算符

相信大家对于operator的运用以及重载运算符有了一定的了解。本次博客我会继续深化赋值运算符重载的内容,并对各函数进行优化处理。


目录

🔑'—' '-='重载运算符

🔑前置--,后置-- 

 🔑日期-日期=天数

🔑+=(-=)负数 (优化)

🔑C++中重载输入cin和输出cout运算符

🌈重载输入cin运算符>> 

🌈重载输入cout运算符<<

🔑不符合常理的日期(优化)

🔑const成员(优化)

🌈const对于+=和+ 

🌈const对于d1<d2?和d1>d2

🕶️完整代码

🚩Date.h

🚩Date.cpp

🚩test.cpp


🔑'—' '-='重载运算符

我们不只局限于对未来的计算,虽然以前的日子已经一去不复返。如果我们想知道100天是哪一天?该如何操作呢?上面的图片今天是2023年11月18日,一百天前是2023年8月10日,这是该如何计算呢?

11月已经被-100了,这里要+上的是10月份的天数。

计算过程如图所示。我们可以根据上面思路进行写代码。

主要思路:先将日-100,然后如果是负数就进入循环 ,月份-1,就可以得到在此基础上的上一个月的天数,然后我们还要考虑一个情况,就是如果月份=0,我们就要追溯到上一年的12月开始。代码如下:

Date &Date::operator-=(int day)
{_day-=day;while(_day<=0){--_month;if(_month==0){_month=12;--_year;}    _day+=GetMonthDay(_year,_month);}return *this;
}

 那么-重载运算符和+重载运算符一个道理,不能改变原来的值,就创建一个临时变量tmp,保留d1原来的值,然后返回tmp.

依旧使用-复用-=的方法.

Date Date::operator-(int day)
{Date tmp(*this);tmp -=day;return tmp;
}

🔑前置--,后置-- 

前置--后置--和前置++后置++的用法是一样的

  • 前置--:返回的减之后的值。
  • 后置--:返回的减之前的值,需要用拷贝构造创建 一个临时变量tmp来保存原来的值。并且后置--重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递  。
//前置--返回的是减之后的值
Date& Date::operator--()
{*this -= 1;return *this;
}//后置--返回的是减之前的值
Date Date::operator--(int)
{Date tmp = *this;*this -= 1;return tmp;
}

 🔑日期-日期=天数

我想计算一下自己的生日和今天相差多少天?我该如何用代码实现呢?

 第一种思路:

  • 我们可以与小的日期和大的日期的年份设置成一样的,然后就可以利用 《月和日对齐,利用年判断润平年,闰年一年多少天,平年一年的多少天,相加)
  • 然后算出了2003-10-29~~~2023-10-29相差多少天,然后 《年对齐,利用获得每个月的天数进行相加》

思路的俩个步骤,比较于直接减方便多了。

第二种思路:

  • d1-d2   我们先假设d1是小min日期,d2是大max日期,如果我的猜测不对,就将min赋值给d2,max赋值给d1。我们要用flag=1或-1来记录,如果(小-大就得乘以-1)(大-小就得乘以1)
  • 小的数如果一直++是可以与大的数持平的,我们就进行一个循环直到min=max的时候结束,过程中min一直++,用n来记下min一直+的次数,n的值就是天数。

代码如下:

int Date::operator-(const Date& d)
{Date max = *this;Date min = d;int flag = 1;if (*this<d){min = *this;max = d;flag = -1;}int n = 0;while (min != max){++min;++n;}return n*flag;
}

计算机的效率是可以完成循环多次的。 


🔑+=(-=)负数 (优化)

图中不管是+还是-都是成立的对于day是正是负都是可以计算的。 

day+= -100;

 大家有没有想过如果day是负数呢?上面的代码运行的结果是什么呢?

这时候我们该如何优化呢?

 d1+= -day 是不是相当于 d1-=day?   那么就可以复用-=重载运算符。

这样对嘛,d1+= -100,本来是看以前的日子的,怎么算到2024了?这里我们就要考虑到数学的知识了。 *this是d1 ,d1-=day ,day是-100,那么负负得正, 就成了d1+=day,所以我们需要在day前面加个负号,即d1-= -day。 -day=100,所以 d1-=100 与 d1+=-100 等式成立。

Date& Date::operator+=(int day)
{if (day < 0){return *this -= day;}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);++_month;if (_month >= 13){++_year;_month = 1;}}return *this;
}

​ 

同理:d1-= -100,看100天后的日期,那么就相当于负负得正,d1+=100,那么用到-=函数里就是  d1+=-day.

Date& Date::operator-=(int day)
{if (day < 0){return *this += -day;}_day -= day;while (_day <= 0){--_month;if (_month== 0){_month = 12;--_year;}_day+= GetMonthDay(_year, _month);}return *this;
}

 


🔑C++中重载输入cin和输出cout运算符

c++系统实现了一个庞大的类的库,如下图所示。其中ios为基类,其他类都直接或间接派生自ios类.

  • cin和cout可以直接输入和输出内置类型(如int、double等)和部分标准自定义类型(如string等),原因是标准库已经将所有这些类型的输入和输出重载了,直接使用即可。

  •  对于我们自定义的类型,如果想直接使用cin、cout来输入输出,需要自己重载>>和<<,否则不能直接使用。

在C++中,标准库本身已经对左移运算符<<和右移运算符>>分别进行了重载,使其能够用于不同数据的输入输出,但是输入输出的对象只能是 C++内置的数据类型(例如 bool、int、double 等)和标准库所包含的类类型(例如 string、complex、ofstream、ifstream 等)。如果自己定义了一种新的数据类型,需要用输入输出运算符去处理,那么就必须对它们进行重载。本节以Date类为例来演示输入输出运算符的重载。

cout << _year << "-" << _month << "-" << _day << endl;//输出形式
cin>>_year>>_month>>_day; //输入形式

cout是ostream类的对象,cin是istream类的对象,要想达到这个目标,就必须以全局函数(友元函数)的形式重载<<和>>,否则就要修改标准库中的类,这显然不是我们所期望的。

🌈重载输入cin运算符>> 

全局函数的形式重载>>,

//cin重载
istream& operator>>(istream& _in, Date& d)
{_in >> d._year >> d._month >> d._day;return _in;
}

注意:运算符重载函数中用到了Date类的private 成员变量,必须在Date类中将该函数声明为友元函数,如下例所示:

friend istream & operator>> (istream &_in,Date &d);


🌈重载输入cout运算符<<

同样地,也可以模仿上面的形式对输入运算符>>进行重载,让它能够输出,请看下面的代码:

//cout重载
ostream& operator<<(ostream& _out, const Date& d)
{_out << d._year << "-" << d._month << "-" << d._day << endl;return _out;
}

ostream表示输出流,cout是ostream类的对象。由于采用了引用的方式进行参数传递,并且也返回了对象的引用,所以重载后的运算符可以实现连续输出。

为了能够直接访问Date类的private成员变量,同样需要将该函数声明为complex类的友元函数
friend ostream & operator<< (ostream &out, complex &A);


友元函数的声明:


我们有没有观察到

​ 

​ 

为什么输入重载里面的参数不加,而输出相反。

——输入年月日,如果输入流不能修改,那么就没办法进行输入了,输出在输入之后了,它保留着日期,是不能被修改的。

在这之前加coonst也是编译不过的,因为流入和流出的过程取它们其中的值也是需要改变它的状态值,所以输出输入都是不能加const的。 提取完了之后要改变其中内部的状态值的。

输入输出重载运算符代码如下:

//cin重载
istream& operator>>(istream& _in, Date& d)
{_in >> d._year >> d._month >> d._day;return _in;
}//cout重载
ostream& operator<<(ostream& _out, const Date& d)
{_out << d._year << "-" << d._month << "-" << d._day << endl;return _out;
}


 我们继续优化吧~


🔑不符合常理的日期(优化)

这个日期符合常理嘛?显然是不符合的。所有的对象是构造出来的,所以我们再构造的时候加一些检查~

  • 第一种:直接打印出“非法日期”
  • 第二种:直接断言报错(暴力法)

既然输出流对于不合理的日期进行了检查,那么输入呢?

输入非法日期之后,是可以直接通过的,那我们就得给流输入进行检查。

//cin重载
istream& operator>>(istream& _in, Date& d)
{//第一种写法_in >> d._year >> d._month >> d._day;if (d._month > 0 && d._month < 13&& d._day>0 && d._day <= d.GetMonthDay(d._year, d._month)){}else{//cout << "非法日期" << endl;assert(false);}return _in;//第二种写法:int year, month, day;_in >> year >> month >> day;if (month > 0 && month < 13&& day>0 && day <= d.GetMonthDay(year, month)){d._year = year;d._month = month;d._day = day;}else{//cout << "非法日期" << endl;assert(false);}
}

一共俩种写法,第二种更灵活。


🔑const成员(优化)

const 修饰的 成员函数 称之为 const 成员函数 const 修饰类成员函数,实际修饰该成员函数 隐含的 this 指针 ,表明在该成员函数中 不能对类的任何成员进行修改。

如何让权限平移或者缩小呢?我们只需要给Date*this改成const Date*this就可以了。

我们不能动this的类型,因为它是隐含的是无法动的,那么如何将类型改成const使权限不放大呢?所以祖师爷就直接再函数后面加个const就可以了。

这里加个const 修饰的是*this。const Date* this我们之前就复习了const,这里const修饰的类型是Date,修饰的内容是*this。

重点:成员函数后面加const以后,普通和const对象都可以调用(权限的平移和权限的缩小)。


🌈const对于+=和+ 

那我们所写的所有成员函数都能加个const嘛?

——当然不是,要修改的对象成员变量函数不能加

比如+=成员函数后面加个const。

_day===》this->day,const修饰的是this指向的内容,指向的内容都不能修改如何+=呢?——肯定不行。那么+呢?

+不会改变我自己,我们上面说了成员函数后面加const以后,普通和const对象都可以调用(权限的平移和权限的缩小)。(只要不改变成员变量都可以加)

所以我们看看还有什么可以加const?


🌈const对于d1<d2和d1>d2?

 

为什么d1<d2可以,d2<d1不可以呢?

这里就考虑到了权限的放大缩小平移问题了,d2是const显然传过去就是权限的放大,当然是不可以的。所以最好的方式就是给这些成员函数都加const。

结论:只要成员函数内部不修改成员变量,就应该加const,这样const对象和普通对象都可以调用。

这些成员函数都可以后面加const,因为按上面的结论,就是不修改内部成员变量。


 🔑const成员

在C语言中,习惯使用#define来定义常量,例如#define PI 3.14,C++提供了一种更灵活、更安全的方式来定义常量,即使用const修饰符来定义常量。例如const float PI = 3.14;

const可以与指针一起使用,它们的组合情况复杂,可归纳为3种:指向常量的指针、常指针和指向常量的常指针。

在此之前我就讲述了const修饰的什么类型,修饰的是什么内容,复制粘贴那一章的内容。

我们这来复习一下const* / *const 的区别——c语言回顾

const:修饰离const最近的第一个成形类型。

区分:const int* p2=&a ; int const*p3=&a 这俩者的修饰的类型和修饰的内容都是一样的,修饰的内容是无法修改的(简单记成const在*前面修饰的类型(int,float,double),而不是(int*,float*,double*...)

 区分:int *const p4=&b; const在*之后修饰的类型(int*,float*,double*),,是不可以修改constt之后的内容。

  • *在const之前,修饰的类型一定是 int*类型。 int *const p4;表示修饰的内容是p4,修饰的类型是int。 p4是不可以修改的。
  • *在const之后,修饰的类型一定是 int类型. int const *p4//const int *p4;表示修饰的内容是*p4,修饰的类型是int. *p4是不可以修改的。修饰的内容是无法改变的

我们复习了const的内容,我们知道const修饰的内容是不可以修改的,所以是在后面Date *const this ,而不能 const Date *this或者Date const *this ,这样修饰的内容是*this ,这里就表示*this是不可以修改的

  • 指向常量的指针:一个指向常量的指针变量。

这里的const char*pc 修饰的类型是char 修饰的内容是*pc。所以指针指向的内容是不可以改变的

const char* pc = "abcd";
该方法不允许改变指针所指的变量,即pc[3] = 'x';   是错误的,
但是,由于pc是一个指向常量的普通指针变量,不是常指针,因此可以改变pc所指的地址,例如pc = "ervfs";
该语句付给了指针另一个字符串的地址,改变了pc的值。
  • 常指针:将指针变量所指的地址声明为常量

char*const pc 修饰的类型是char* 修饰的内容是pc,所以pc所指向的内容也就是解引用后的是可以改变的,但是不能改变pc的地址。

char* const pc = "abcd";
创建一个常指针,一个不能移动的固定指针,可更改内容,如pc[3] = 'x';
但不能改变地址,如pc = 'dsff';  不合法
  •  指向常量的常指针:这个指针所指的地址不能改变,它所指向的地址中的内容也不能改变。
const char* const pc = "abcd";
内容和地址均不能改变

const修饰的成员函数称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

#include<iostream>
using namespace std;
class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << "Print()" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}void Print() const{cout << "Print()const" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}
private:int _year; // 年int _month; // 月int _day; // 日
};int main()
{Date d1(2022, 1, 13);d1.Print();const Date d2(2022, 1, 13);d2.Print();return 0;
}

接下来大家来思考几个问题?

1. const对象可以调用非const成员函数吗?

这里用const对象调用非const成员函数是权限的放大,在权限放大情况下是不可以的。

const对象是可读但是不可写的。调用非const对象是可读可写,那么对于对象来说是权限的放大,编译器是不能给const对象进行写的能力。我们在调用一个成员函数的时候需要传递this指针,const Date*this,如果调用非const函数,那么就无法将this指针从const Date类型转换成Date&。如上报错。

2. 非const对象可以调用const成员函数吗?

显然是可以,为什么呢?因为这就考虑到权限的缩小问题了,权限缩小是可以的。我们不可以给const类型赋值,可以给const类型赋值,因为const类型是不可以修改的。

3. const成员函数内可以调用其它的非const成员函数吗?

4. 非const成员函数内可以调用其它的const成员函数吗?

这些都涉及权限放大缩小的问题。

对于权限放大缩小平移的应用场景总结:

权限的放大缩小平移只对引用/指针

🚩取地址及const取地址操作符重载

这两个默认成员函数一般不用重新定义 ,编译器默认会生成

不需要太关注这个成员函数,我们只要关注下面四个默认成员函数即可。


🕶️完整代码

🚩Date.h

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
class Date
{//友元函数的声明friend ostream& operator<<(ostream& _out, const Date& d);friend istream& operator>>(istream& _in, Date& d);
public:int GetMonthDay(int year, int month){int array[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){return 29;}else{return array[month];}}void print() const{cout << _year << "-" << _month << "-" << _day << endl;}Date(int year = 2003, int month = 10, int day = 5);Date& operator=(const Date& d);bool operator==(const Date& d)const;bool operator>(const Date& d)const;bool operator>=(const Date& d)const;bool operator<(const Date& d)const;bool operator<=(const Date& d)const;bool operator!=(const Date& d)const;//日期+天数Date operator+(int day) const;Date& operator+=(int day);// 日期-天数Date operator-(int day)const;//自己不能改变。但是返回之后的结果Date& operator-=(int day);//前置++Date&operator++();//后置++Date operator++(int);//前置--Date& operator--();//后置--Date operator--(int);//日期-日期int operator-(const Date& d)const;private:int _year;int _month;int _day;
};

🚩Date.cpp

#include<iostream>
using namespace std;#include"Date.h"Date::Date(int year, int month, int day)
{if (month>0&&month<13&&day>0&&day<=GetMonthDay(year,month)){_year = year;_month = month;_day = day;}else{//cout << "非法日期" << endl;assert(false);}
}//赋值运算符重载
Date& Date::operator=(const Date& d)
{_year = d._year;_month = d._month;_day = d._day;return (*this);
}bool Date::operator==(const Date& d)const
{return _year == d._year&& _month == d._month&& _day == d._day;
}bool Date::operator>(const Date& d)const
{if (_year > d._year){return true;}else if (_year == d._year && _month > d._month){return true;}else if (_year == d._year && _month == d._month && _day >d._day){return true;}else{return false;}
}bool Date::operator>=(const Date& d)const
{return *this > d || *this == d;
}bool Date::operator<(const Date& d)const
{return !(*this>=d);
}bool Date::operator<=(const Date& d)const
{return !(*this > d);
}bool Date::operator!=(const Date& d)const
{return !(*this == d);
}+=复用+
//Date& Date::operator+=(int day)
//{
//	*this = *this + day;
//	return *this;
//}
//
//Date Date::operator+(int day)
//{
//	Date tmp(*this);
//	tmp._day += day;
//	while (tmp._day > GetMonthDay(tmp._year, tmp._month))
//	{
//		tmp._day -= GetMonthDay(tmp._year, tmp._month);
//		++tmp._month;
//		if (tmp._month >= 13)
//		{
//			++tmp._year;
//			tmp._month = 1;
//		}
//	}
//	return tmp;
//}//+复用+=
Date Date::operator+(int day)const
{Date tmp(*this);tmp += day;return tmp;
}//d1+=100
Date& Date::operator+=(int day)
{if (day < 0){return *this -= -day;}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);++_month;if (_month >= 13){++_year;_month = 1;}}return *this;
}//前置++返回的是加之后的值
Date &Date::operator++()
{*this += 1;return *this;
}//后置++返回的是加之前的值
Date Date::operator++(int)
{Date tmp = *this;*this += 1;return tmp;
}//前置--返回的是减之后的值
Date& Date::operator--()
{*this -= 1;return *this;
}//后置--返回的是减之前的值
Date Date::operator--(int)
{Date tmp = *this;*this -= 1;return tmp;
}Date Date::operator-(int day)const
{Date tmp(*this);tmp -=day;return tmp;
}Date& Date::operator-=(int day)
{if (day < 0){return *this += -day;}_day -= day;while (_day <= 0){--_month;if (_month== 0){_month = 12;--_year;}_day+= GetMonthDay(_year, _month);}return *this;
}int Date::operator-(const Date& d)const
{Date max = *this;Date min = d;int flag = 1;if (*this<d){min = *this;max = d;flag = -1;}int n = 0;while (min != max){++min;++n;}return n*flag;
}//cin重载
istream& operator>>(istream& _in, Date& d)
{//第一种写法_in >> d._year >> d._month >> d._day;if (d._month > 0 && d._month < 13&& d._day>0 && d._day <= d.GetMonthDay(d._year, d._month)){}else{//cout << "非法日期" << endl;assert(false);}return _in;//第二种写法:int year, month, day;_in >> year >> month >> day;if (month > 0 && month < 13&& day>0 && day <= d.GetMonthDay(year, month)){d._year = year;d._month = month;d._day = day;}else{//cout << "非法日期" << endl;assert(false);}
}//cout重载
ostream& operator<<(ostream& _out, const Date& d)
{_out << d._year << "-" << d._month << "-" << d._day << endl;return _out;
}

🚩test.cpp

#include"Date.h"void TestDate1()
{Date d1(2003, 10, 5);Date d2(2003, 11, 5);int ret=d1 > d2;int ret2 = d1 == d2;int ret3 = d1 < d2;int ret4 = d1 >= d2;cout << ret3 << endl;
}void TestDate2()
{Date d1(2003, 11, 14);Date d2=d1 +100;//运用拷贝构造创建一个临时变量tmp,将*this的值给tmp,*this的值不改变,tmp值改变,//从而导致了d1+day,d1不变,tmp改变。返回d1原来的值。//d1 +=100;//d1 += 100;d2.print();/*d1++;d1.print();++d1;d1.print();*/
}void TestDate3()
{Date d1(2023, 11, 17);Date d2=d1 -100;d2.print();
}void TestDate4()
{Date d1(2023, 11, 17);//d1--;//后置--返回的是之前的值、--d1;//前置--返回的是之后的值d1.print();
}void TestDate5()
{Date d1(2023, 11, 17);Date d2(2003, 10, 29);cout << d1-d2<< endl;cout << d2 - d1<< endl;
}void TestDate6()
{Date d1(2023, 11, 17);d1.print();/*d1 += -100;d1.print();*/d1 -= -100;d1.print();
}void TestDate7()
{//Date d1(2023, 11, 17);//d1 += 100;流插入//cout << d1;//operator<<(cout, d1);Date d1(2023, 11, 17);Date d2(2003, 10, 29);cin >> d1 >> d2;cout << d1 << d2;/*Date d4(2023, 13, 1);cout << d4;*/}void TestDate8()
{Date d4(2023,13,1);cin>>d4;cout << d4;
}void TestDate9()
{Date d1(2023, 11, 17);const Date d2(2023, 11, 17);d1 < d2;d2 < d1;//d1 + 100;//d1普通对象//d2 + 100;//const对象
}int main()
{//TestDate1();//TestDate2();//TestDate3();//TestDate4();//TestDate5();//TestDate6();//TestDate7();//TestDate8();TestDate9();return 0;
}

我走的很慢,但我从不后退。

这篇关于【c++】——类和对象(中)——实现完整的日期类(优化)万字详细解疑答惑的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/445148

相关文章

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Python脚本实现自动删除C盘临时文件夹

《Python脚本实现自动删除C盘临时文件夹》在日常使用电脑的过程中,临时文件夹往往会积累大量的无用数据,占用宝贵的磁盘空间,下面我们就来看看Python如何通过脚本实现自动删除C盘临时文件夹吧... 目录一、准备工作二、python脚本编写三、脚本解析四、运行脚本五、案例演示六、注意事项七、总结在日常使用

Java实现Excel与HTML互转

《Java实现Excel与HTML互转》Excel是一种电子表格格式,而HTM则是一种用于创建网页的标记语言,虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,下面我们就来看看... Excel是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言。虽然两

Java中Springboot集成Kafka实现消息发送和接收功能

《Java中Springboot集成Kafka实现消息发送和接收功能》Kafka是一个高吞吐量的分布式发布-订阅消息系统,主要用于处理大规模数据流,它由生产者、消费者、主题、分区和代理等组件构成,Ka... 目录一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者一、Kaf

使用Python实现在Word中添加或删除超链接

《使用Python实现在Word中添加或删除超链接》在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能,本文将为大家介绍一下Python如何实现在Word中添加或... 在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能。通过添加超

C#使用HttpClient进行Post请求出现超时问题的解决及优化

《C#使用HttpClient进行Post请求出现超时问题的解决及优化》最近我的控制台程序发现有时候总是出现请求超时等问题,通常好几分钟最多只有3-4个请求,在使用apipost发现并发10个5分钟也... 目录优化结论单例HttpClient连接池耗尽和并发并发异步最终优化后优化结论我直接上优化结论吧,

windos server2022里的DFS配置的实现

《windosserver2022里的DFS配置的实现》DFS是WindowsServer操作系统提供的一种功能,用于在多台服务器上集中管理共享文件夹和文件的分布式存储解决方案,本文就来介绍一下wi... 目录什么是DFS?优势:应用场景:DFS配置步骤什么是DFS?DFS指的是分布式文件系统(Distr

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭