string类(一)

news2024/11/17 11:03:16

目录

一、 string类对象的常见构造

二、string类对象的容量操作

 2.1 size(返回字符串有效字符长度)

2.2 capacity(返回空间总大小) 

 2.3 reserve扩空间​编辑

2.4 resize初始化不会覆盖本来的空间​编辑

2.5 对于test_string7中每一句代码进行调试运行

三、string类对象的访问及遍历操作

 3.1 operator[]

 3.2 迭代器

四、笔试题

1.关于代码输出正确的结果是( )

 2.关于代码输出正确的结果是( )

3.关于代码输出正确的结果是( )

4. 把字符串转换成整数_牛客题霸_牛客网 (nowcoder.com)

5.917. 仅仅反转字母 - 力扣(Leetcode)

6.541. 反转字符串 II - 力扣(Leetcode)

7.125. 验证回文串 - 力扣(Leetcode)  

一、 string类对象的常见构造

 string初始化:

#define _CRT_SECURE_NO_WARNINGS 1
#include<string>

#include<iostream>
using namespace std;

//string管理动态增长的字符数组,这个字符串以\0结尾
int main()
{
	std::string s;
	//string初始化
	string s1;//构造空的string类对象s1
	cout << "s1: " << s1 << endl;
	string s2("hello world");
	s2 += "!!!!";
	cout << "s2: " << s2 << endl;
	string s3(s2);
	cout << "s3: " << s3 << endl;
	string s4 = s2;//拷贝构造
	cout << "s4: " << s4 << endl;
	string s5("https://blog.csdn.net/weixin_57604904?spm=1000.2115.3001.5343", 4);
	cout << "s5: " << s5 << endl;
	string s6(6, 'C');
	cout << "s6: " << s6 << endl;
	string s7(s2, 6, 5);//第6个字符往后,不包括第6个,5个字符进行初始化
	cout << "s7: " << s7 << endl;
	string s8(s2, 6, 4);
	cout << "s8: " << s8 << endl;
	string s9(s2, 1, 100);//不会报错,会到\0截止
	cout << "s9: " << s9 << endl;
	string s10(s2, 6);//从s2的第六个字符往后直接到\0
	cout << "s10: " << s10 << endl;
	string s11(s2, 1);
	cout << "s11: " << s11 << endl;
	string s12(s2, 10);
	cout << "s12: " << s12 << endl;
	return 0;
}

 s1可修改:

void test_string()
{
	string s1("hello");
	string s2("xxxx");
	s1 = s2;
	s1 = "xxx";
	s1 = 'y';
	cout << s1 << endl;
	cout << s2 << endl;
}
int main()
{
	test_string();
	return 0;
}

二、string类对象的容量操作

 2.1 size(返回字符串有效字符长度)

 

1. size()与length()方法底层实现原理完全相同,
引入size()的原因是为了与其他容器的接口保持一致,
一般情况下基本都是用size()。

2.2 capacity(返回空间总大小) 

void test_string6()
{
	string s("helloworld");
	size_t sz = s.capacity();//空间总大小
	cout << sz << endl;
	//s.reserve(1000);//扩空间
	//s.resize(1000, 'x');//扩空间+初始化
	for (int i = 0; i < 1000; i++)
	{
		s.push_back('c');//尾插
		if (sz != s.capacity())//尾插后,容量如果满了,容量会变
		{
			sz = s.capacity();//变了后就有新的sz
			cout << "capacity changed: " << sz << "\n";
		}
	}
}
int main()
{
	test_string6();
	return 0;
}

初始size与capacity:

字符串有效字符长度与空间总大小:

 

 

 尾插push_back,空间满了就扩容:

 第一次扩容:

 运行结果:

 2.3 reserve扩空间

2.4 resize初始化不会覆盖本来的空间

 注意:观察如下代码:

void test_string7()
{
	string s("hello");
	s.reserve(100);
	s.resize(100, 'x');//注意不会改变hello,只是让size=100,后面补x
	s.reserve(10);//说明reserve会扩不会缩
//s[9] = 'y'//会报断言错误
	s.resize(10, 'x');//但是resize使得size= 10//s[9] = 'x'
	s[9] = 'y';//不会报错
}
int main()
{
	test_string7();
	return 0;
}

2.5 对于test_string7中每一句代码进行调试运行

1.capacity变为111

 2.size变为100,补x

 3. capacity没有变(reserve不会缩只会扩)

 4.resize会改变size,从100->10

 5.改变s[9],不会报错

3. resize(size_t n) 与 resize(size_t n, char c)都是将字符串中有效字符个数改变到n个,
不同的是当字符个数增多时:
    resize(n)用0来填充多出的元素空间,
    resize(size_t n, char c)用字符c来填充多出的元素空间。
    注意:resize在改变元素个数时,如果是将元素个数增多,可能会改变底层容量的大小,如果是将元素个数减少,底层空间总大小不变。
4. reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,
   当reserve的参数小于string的底层空间总大小时,reserve不会改变容量大小。

三、string类对象的访问及遍历操作

 3.1 operator[]

返回位于字符串中指定位置的字符:

1. 对于operator[],字符串中的第一个字符用值0(而不是1)表示,
    s1.operator[](i)//返回位于字符串中指定位置i的字符。
    如果字符串对象是const限定的,则该函数返回const char&。否则,它返回char&。
    char& operator[] (size_t pos);const char& operator[] (size_t pos) const;

2. 为什么不能返回char?
    1).返回的是位于字符串指定位置pos的字符,return str[pos]
    其因为是在堆区开辟的,出了作用域还在,所以按常规操作肯定是返回char&别名更合适,减少拷贝;
    2).这样引用返回可以使得返回值可修改,因为如果是char返回,返回是先创建临时变量,返回的是临时变量,而临时变量具有常性,const权限放大,不能赋值和修改,而char&不会,可以修改。

void test_string2()
{
	string s1("hello");//初始化
	s1.at(1) = 'x';
	//s1[6];//会报错assert判断的
	cout << s1.size() << endl;//s1.size()返回有效字符个数,不包含\0
	for (size_t i = 0; i < s1.size(); i++)
	{
		cout << s1[i] << " ";
	}
	cout << endl;
}
int main()
{
	test_string2();
	return 0;
}

 3.2 迭代器

reverse_iterator rbegin();

const_reverse_iterator rbegin() const;

void test_string4()
{
	string s = "helloworld";
	string::reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit << " ";
		rit++;
	}
	cout << endl;
}
void test_string5()
{
	const string s = "helloworld";
	string::const_reverse_iterator rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit << " ";
		rit++;
	}
	cout << endl;

}
int main()
{
    test_string4();
    test_string5();
    return 0;
}

四、笔试题

1.关于代码输出正确的结果是( )

关于代码输出正确的结果是( )

int main(int argc, char *argv[])
{
string a="hello world";
string b=a;
if (a.c_str()==b.c_str())
{
    cout<<"true"<<endl;
}
else 
    cout<<"false"<<endl;
string c=b;
c="";
if (a.c_str()==b.c_str())
{
    cout<<"true"<<endl;
}
else
    cout<<"false"<<endl;
a="";
if (a.c_str()==b.c_str())
{
    cout<<"true"<<endl;
}
else 
    cout<<"false"<<endl;
return 0;
}



A.false false false
B.true false false
C.true true true
D.true true false
分析:a 和 b的值虽然相同,
但是a.c_str()==b.c_str()比较的是存储字符串位置的地址,
a和b是两个不同的对象,内部数据存储的位置也不相同,因此不相等,
后面c="",a=""与b对象都没有任何的影响,所以都不相等
故答案为:A

 2.关于代码输出正确的结果是( )

下面程序的输出结果正确的是( )
int main()
{
string str("Hello Bit.");
str.reserve(111);
str.resize(5);
str.reserve(50);
cout<<str.size()<<":"<<str.capacity()<<endl;
return 0;
}


A.10 50
B.5 50
C.5 111
D.10 111
分析:

str.reserve(111); //调整容量为 111

str.resize(5);   //调整元素个数为 5

str.reserve(50);  //调整容量为 50,由于调整的容量小于已有空间容量,故容量不会减小

所以size=5 capacity=111

故答案为: C

3.关于代码输出正确的结果是( )

下面程序的输出结果正确的是( )
int main(int argc, char *argv[])
{
string strText = "How are you?";
string strSeparator = " ";
string strResult;
int size_pos = 0;
int size_prev_pos = 0;
while((size_pos=strText.find_first_of(strSeparator, size_pos)) != string::npos)
{
strResult = strText.substr(size_prev_pos, size_pos-size_prev_pos);
cout<<strResult<<" ";
size_prev_pos = ++size_pos;
}
if(size_prev_pos != strText.size())
{
strResult = strText.substr(size_prev_pos, size_pos-size_prev_pos);
cout<<strResult<<" ";
}
cout<<endl;
return 0;
}

A.Howareyou?
B.How Are You?
C.How are
D.How are you?
分析:程序的目的是以字符串strSeparator = " "作为分隔符,
对字符串string strText = "How are you?";进行分割,每分割出一个单词就进行一次打印

故答案为 D

实际的 find_first_of函数的作用是:
        在一个字符串中进行查找,返回值是第一个与指定字符串中任何字符匹配的字符位置;
如果没有找到匹配的内容,就返回 string::npos。
 

注意与find的区别:发现find是返回-1,说明找不到。

 find:

substr:

substr(size_type _Off = 0,size_type _Count = npos)
参数:
_Off——所需的子字符串的起始位置。字符串中第一个字符的索引为 0,默认值为0。
_Count——复制的字符数目
返回值——一个子字符串,从其指定的位置开始
假设string s(“student12”);
string x=s.substr()                 //默认时的长度为从开始位置到尾
string y=s.substr(5)               //获得字符串s中 从第5位开始到尾的字符串
string z=s.substr(5,3);         //获得字符串s中 从第5位开始的长度为3的字符串

 具体解析:

int main()
{
	string strText = "How are you?";
	string strSeparator = " ";
	string strResult;
	int size_pos = 0;
	int size_prev_pos = 0;
	//找不到就返回npos
	//在strText中找空格,返回位置为3,因为是从0开始。
	//找不到就返回string::pos
	//只要strText.find_first_of(strSeparator, size_pos)) != string::npos就说明
	//找到了空格,找到了空格就返回所在位置或者说是下标size_pos
	while ((size_pos = strText.find_first_of(strSeparator, size_pos)) != string::npos)
		//在strText的第0开始找strSeparator也就是空格,返回的位置只要不是-1,就进入循环,
		//如果在一个字符串strText中查找另一个字符串strSeparator,
		//如果strText1中含有strSeparator中的任何字符,则就会查找成功
	{
		//从0开始找(3-0)个元素,找到How
		strResult = strText.substr(size_prev_pos, size_pos - size_prev_pos);
		cout << strResult << " ";//再输出一个空格
		size_prev_pos = ++size_pos;//然后同时++,都变成4
		//之后size_pos = 4,从位置4开始找空格,到了位置7,7-4=3
		//size_prev_pos = size_pos = 8
		//之后就找不到空格了,跳出循环,size_pos = -1,size_prev_pos = 8
	}
	if (size_prev_pos != strText.size())//已知size = 12,8!=12进入if
		//只要不和size相等就进入循环
	{
		strResult = strText.substr(size_prev_pos, size_pos - size_prev_pos);
		//从8开始找到-9,就相当于找到底
		cout << strResult << " ";
	}
	cout << endl;
	return 0;
}

4. 把字符串转换成整数_牛客题霸_牛客网 (nowcoder.com)

描述

将一个字符串转换成一个整数,要求不能使用字符串转换整数的库函数。 数值为 0 或者字符串不是一个合法的数值则返回 0

class Solution
{
  public:
    int StrToInt(string str)
    {
        if (str == "")//如果没有字符串返回0
            return 0;//输入一个字符串,包括数字字母符号,可以为空
        int ret = 0;
        int flag = 1;
        if (str[0] == '-')
        {
            str[0] = '0';
            flag = -flag;
        }
        if (str[0] == '+') 
        {
            str[0] = '0';
        }
        for (int i = 0; i < str.size(); ++i) 
        {
            if (str[i] < '0' || str[i] > '9') 
            //注意:字符串中可能出现任意符号,出现除 +/- 以外符号时直接输出 0
            {
                return 0;
            }
            if (str[i] >= '0' && str[i] <= '9')
            //比如str是0123,str[1] = 1,ret = 0+1
            //str[2] = 2,ret = 1*10+2=12
            //str[3] = 3,ret = 12*10+3=123
            {
                ret = ret*10 + str[i] - '0';//‘0’ascii码值是48
                //字符'1'的ascii码值是49,49-48 =1,从字符1变成整数1
            }
        }
        if (flag == -1)
        {
            ret *= -1;//如果flag等于-1,那么ret就要乘上-1
        }
        return ret;
    }
};

5.917. 仅仅反转字母 - 力扣(Leetcode)

给你一个字符串 s ,根据下述规则反转字符串:

  • 所有非英文字母保留在原有位置。
  • 所有英文字母(小写或大写)位置反转。

返回反转后的 s 。

class Solution {
public:
    bool isLetter(char ch)
    {
        if(ch >= 'A' && ch <= 'Z')
        {
            return true;
        }
        else if(ch >= 'a' && ch <= 'z')
        {
            return true;
        }
        else
        {
            return false;
        }
    }
    string reverseOnlyLetters(string s) 
    {
        string::iterator left = s.begin();
        string::iterator right = s.end()-1;
        while(left < right)
        {
            while(left<right && !isLetter(*left))
        //是字母就为true,取反为0
        //不是字母就返回false,取反为1
                left++;//说明不是字母就++
            while(left<right && !isLetter(*right))
                right--;
            swap(*left,*right);//是字母就进行交换
            left++;
            right--;
        }
        return s;
    }
};

6.541. 反转字符串 II - 力扣(Leetcode)

给定一个字符串 s 和一个整数 k,从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。

如果剩余字符少于 k 个,则将剩余字符全部反转。
如果剩余字符小于 2k 但大于或等于 k 个,则反转前 k 个字符,其余字符保持原样。

class Solution {
public:
	void reverse(string& s, int left, int right) 
	{
		while (left < right)
		{
			swap(s[left], s[right]);
			left++;
			right--;
		}
	}

	string reverseStr(string s, int k) 
	{
		//从字符串开头算起,每计数至 2k 个字符,就反转这 2k 字符中的前 k 个字符。
		//每次i向前移动2k个字符
		for (int i = 0; i < s.size(); i += 2 * k) 
		{
			//x为走了2k步后的剩余字符,如果k<= x <2k,那么反转前k个数
			//那么s.size()>=(k+2k),就反转前k个数
			if (s.size() >= (i + k))
			{
				reverse(s, i, i + k - 1);
				continue;//反转前k个数后,调到for循环,继续向后走2k步,如果还大于,接着反转前k个数
			}
			//如果x<k,反转剩下的字符,剩下的就是i到s.size()-1
			reverse(s, i, s.size() - 1);
		}
		return s;
	}
};

7.125. 验证回文串 - 力扣(Leetcode)  

如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后,短语正着读和反着读都一样。则可以认为该短语是一个 回文串 。

字母和数字都属于字母数字字符。

给你一个字符串 s,如果它是 回文串 ,返回 true ;否则,返回 false 

class Solution {
public:
	char func(char c)
	{
		if (('0' <= c && c <= '9') || ('a' <= c && c <= 'z'))
			return c;//数字0~9或a~z无需转换
		else if ('A' <= c && c <= 'Z')
			return c + 'a' - 'A';   //所有大写转小写,A~Z转化为对应a~z
		else
		{
			return ' ';    //其他字符转换为空格符' '
		}
	}
	bool isPalindrome(string s)
	{
		if (s.size() == 0 || s.size() == 1) 
			return true;//空字符和一个字符都是回文结构
		string::iterator left = s.begin();
		string::iterator right = s.end() - 1;
		char c1, c2;
		while (left < right)
		{
			c1 = func(*left); //调用转化函数
			c2 = func(*right);  //调用转化函数
			if (c1 == ' ')
			{
				left++;
			}
			if (c2 == ' ')
			{
				right--;
			}
			//c1和c2如果是空格,说明是别的字符且已经转换了
			if (c1 != ' ' && c2 != ' ')
			{
				if (c1 != c2)
				{
					return false;
				}	
				left++; right--;
			}
		}
		return true;
	}	
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/30234.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

云中网络的隔离:GRE、VXLAN

对于云平台中的隔离问题&#xff0c;前面咱们用的策略一直都是 VLAN&#xff0c;但是我们也说过这种策略的问题&#xff0c;VLAN 只有 12 位&#xff0c;共 4096 个。当时设计的时候&#xff0c;看起来是够了&#xff0c;但是现在绝对不够用&#xff0c;怎么办呢&#xff1f; …

真的,Java并发编程基础入门看这个就够了

Java并发编程学习之02Java并发编程入门指南 真的&#xff0c;Java并发编程入门看这个就够了1. Java天生多线程2. Java启动多线程实现方式2.1 实现代码2.2 Thread和Runnable的区别2.3 start和run方法的区别3. Java如何停止线程呢3.1 已弃用方法3.2 推荐使用4. 守护线程5. 优先级…

JVM的GC算法CMS和G1

GC算法 -XX:UseSerialGC 新生代和老年代都使用串行收集器 串行收集器使用单线程并且是独占式的垃圾回收 -XX:UseParNewGC 新生代使用ParNew垃圾回收器&#xff0c;老年代使用串行收集器 ParNew是串行收集器的多线程版本&#xff0c;只工作在新生代&#xff08;可以见名知…

jmeter逻辑控制器和定时器

常用逻辑控制器和定时器一、认识逻辑控制器一、作用&#xff1a;⼀个事务会包含并请求二、常见逻辑控制器介绍1、simple controller2、recorder controller3、loop controller4、random controller5、if controller6、module/include controller7、transaction controller三、J…

A Survey on Bias and Fairness in Machine Learning 阅读笔记

论文链接 Section 1 引言 1. In the context of decision-making, fairness is the absence of any prejudice or favoritism toward an individual or group based on their inherent or acquired characteristics. 公平是指基于个人或群体的固有或后天特征而对其没有任何偏…

【sfu】rtc 入口

rtc 入口 入口是 rtc adpter 类。 准备 call模块的所有资源 通过call模块使用webrtc内置 各类 rtcadpter的创建类rtcadpterfactory 是外部创建的 创建adapterfactory的外部类是peerconnection adapter_factory_ = std::move(std::make_unique

融云全球社交泛娱乐洞察,互联网社交换挡期的「社区产品」机遇

一切应用都将社交化。关注【融云全球互联网通信云】回复【融云】抽取高颜值大容量高端可乐保温杯哦~ 融入社交能力&#xff0c;创造增长奇迹。激活用户在不同场景的社交需求&#xff0c;让应用焕发新的生命力&#xff0c;也让“社交X”成为出海最大的浪。 《2022 社交泛娱乐出…

编译原理--基本块的划分

基本块的划分原则有4条 初始语句作为第一个基本块的入口遇到标号类语句&#xff0c;结束当前基本块&#xff0c;标号作为新基本块的入口&#xff08;标号不在当前基本块中&#xff0c;而是划到下一个基本块&#xff09;遇到转移类语句时&#xff0c;结束当前当前基本块&#x…

Java反序列化之CommonsCollections(CC1)分析篇

文章目录前言一、过程分析 1.入口点---危险方法InvokerTransformer.transform() 2.触发危险函数TransformedMap.checkSetValue() 3.AnnotationInvocationHandler类 4.ChainedTransformer类 5.ChainedTransformer类前言 本文包括&#xff1a;Java反序列化之CommonsCol…

3DMAX一键生成螺母和螺栓插件使用教程

插件介绍 3DMAX一键生成螺母和螺栓插件&#xff0c;用于创建精缰化的螺母和螺栓模型。这些模型是逼真的&#xff0c;只需单击一下即可生成。有许多参数可以定制模型的外观或尺寸。 主要功能 单击创建螺母、螺栓和垫圈在螺栓顶部创建文本标记&#xff08;商标&#xff09;直径…

关于不同长度PEG的丙炔:Pyrene-PEG2/PEG3/PEG4/PEG5-propargyl,1817735-33-3

Pyrene-PEG2-Propargyl中芘用于蛋白质构象和相互作用研究中的荧光探针&#xff0c;降冰片烯很容易与叠氮化物和四嗪反应&#xff0c;可用于用荧光团和功能分子标记细胞&#xff0c;亲水性 PEG 间隔臂可以增加水溶性。包括PEG2、PEG3、PEG4、PEG5等不同长度的PEG。 1、Pyrene-PE…

大数据:Shell的操作

文章目录HDFS常用命令一、创建目录1、创建单层目录2、创建多层目录查看目录三、上传本地文件到HDFS四、查看文件内容五、下载HDFS文件到本地六、删除HDFS文件七、删除HDFS目录HDFS常用命令 启动Hadoop集群命令&#xff1a;start-all.sh 一、创建目录 1、创建单层目录 命令…

Spring Boot Auto-Configuration

Spring 自定义Auto-Configuration Spring Boot 可以根据classpath中依赖关系自动装配应用程序。通过自动装配机制&#xff0c;可以使开发更快、更简单。今天&#xff0c;学习下如何在Spring Boot 中创建自定义 auto-configuration。 代码运行环境 JDK17MYSQL8源码地址 Mave…

[附源码]Python计算机毕业设计大学生心理健康管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

VSCODE编译阿里云HaaS程序时遇到Win32file找不到错误怎么办?

摘要&#xff1a;本文介绍DLL load failed while importing win32file&#xff1a;找不到指定的程序&#xff0c;这个错误的解决方法。使用vscode拉取阿里云HaaS物联网开发案例代码时&#xff0c;可能会遇到编译出错的情况&#xff0c;可能会遇到一些意外的问题&#xff0c;并非…

通过Native Memory Tracking查JVM的线程内存使用(线上JVM排障之九)

很多时候会面对线上内存使用很多,特别是本地内存怎么用的说不太清,就是每一块内存总和和总的Java线程占用内存不匹配。 很多时候如果dump出来内存也没有太大的作用,因为本地内存是看不到。本地内存有很多是线程占用的空间。 以下图为例,这是一个线上的服务的JVM各块内存使…

YOLOV5在deepstream6.1.1上应用

目录 0.前言 1.Yolov5模型 1.1模型生成 1.2模型转换 1.2.1 yolov5模型转换为onnx 1.2.2 onnx模型转换为engine 2.deepstream介绍 2.1简介 2.2安装 2.2.1 dGpu 2.2.2 Jetson 2.3使用方法 3.Yolov5模型在deepstream6.1.1上应用 3.1Yolov5输出与deepstream对接 3.1…

[附源码]java毕业设计学生信息管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

论文阅读:Fast Color Segementation

Fast Color Segementation 发表于CVPR 2020&#xff0c;主要是对之前的一篇图像软分割的论文&#xff08;参见&#xff1a;论文回顾&#xff1a;Unmixing-Based Soft Color Segmentation for Image Manipulation&#xff0c;Aksoy 2017&#xff09;进行改进。 一、论文简介 […

【Mac】Mac与PlayCover、Mac关闭sip

文章目录Mac笔记本使用PlayCover游玩Ipad游戏1.1 Mac 安装 PlayCover1.2 Mac 安装 原神/明日方舟1.3 注意事项Mac笔记本关闭sip2.1 查看sip状态2.2 关闭sip为什么要关闭SIP&#xff0c;关闭SIP的利与弊&#xff0c;请看&#xff1a;3.1 什么时候要关闭sip3.2 sip是什么3.3 关闭…