(10)C#传智:命名空间、String/StringBuilder、指针、继承New(第10天)
内容开始多了,慢品慢尝才有滋味。
一、命名空间namespace
用于解决类重名问题,可以看作类的文件夹.
若代码与被使用的类,与当前的namespace相同,则不需要using.
若namespace不同时,调用的方法:
1.写出全称:命名空间.类名
2.先using引用命名空间,再直接调用
在vs2022中
若引用的方法提示有误,鼠标指向有误处停2秒,会有灯光提示。
点击灯光,有就多种更正方式,包括加入引用。
或者,直接在有误处Alt+Shift+F10,也可快速提示。
同一解决方案下,项目B要使用项目A中的类:
1.解决方案中项目B下,右击引用,弹出窗口默认就是本解决方案中的项目 。
选择要引用的项目A,即引用项目A到项目B中。
2.引用命名空间:在最上面 using 项目A的命名空间
这样在项目B中就可以使用项目A中定义的类。
注意:在使用另一个项目中的类时,要注意访问修饰符。
vs中默认为internal,故应改为public.否则无法访问.
二、值类型与引用类型
值类型:int double,float,bool,char,enum,结构等
引用类型:string,数组,类等
值类型存储在栈(stack)中,
引用类型存储在堆(heap)中
三、字符串
1.字符串的不可变性,
给字符串赋新值时,堆中老值并不消失,而是开辟新空间存储新值,并指向新值。
string s="abcd";s="cdgf";//堆中abcd不消失,栈中s更新指向堆中新开辟的空间,内有cdgf
故原abcd就没有联系,若大量更改字串,会有大量的原值无联系(内存垃圾)
当程序结束时,GC扫描整个内存,若发现有的空间没有被指向,立即销毁。
string s1="abc";stirng s2="abc";Console.ReadKey();//在此处下断点,
运行上面代码,中断后,打开即时窗口,输入&s1回车,显示s1的存储的指针
同时*&s1取得该指针指向堆中的地址。同理输入&s2加车,也可显示上面内容。
可以看到&s1与&s2是不同的,即在栈中两者存储位置不同。
但*&s1与*&s2是相同的,说明存储的是相同的地址(该地址指向同一堆地址)
2.可将字符串看作char类型的一个只读数组.
string s="abcdef";Console.WriteLine(s[0]);//as[1]=a;//错误,不可更改,只读 char[] c=s.ToCharArray;//转为char数组c[1]=a;//c为aacdef,但是s没有改变s=new string(c);//s改变,但不是原来存储空间,是新开的堆空间内存
注意:
ToCharArray:将字符串转为char数组。
new string(c):将字符数组char[]转为一个字符串。
三、StringBuilder
using System.Text;
表示可变字符字符串。 此类不能被继承。
不开辟空间,就在原空间更改,所以速度快。
Stopwatch :准确测量运行时间的类。构造函数 new Stopwatch
属性Elapsed :当前总运行时间。返回只读TimeSpan
ElapsedMilliseconds:返回总运行时间(毫秒),只读int64
isRunning:是否运行,返回bool
调用start或StartNew开始运行,Stop或Reset停止。
ElapsedTicks:已用时钟(周期/刻度)数,该数除Frequency得秒数
方法StartNew:初始化新的Stopwatch实例,将运行时间属性设置为零,
然后开始测量运行时间
Stop:停止计时。再Start时会继续计时,Reset才清除以前计时。
ReStart:停止测量,时间清零,重新开始测量运行时间。
Reset: 停止测量,时间清零。
GetTimestamp:获取计时器机制中的当前刻度数.
注意:时钟按周期/刻度进行计数,比如计数4000次,其Frequency表示1秒
中多少次,例如1秒1000次,那么上面时间4000/1000=4秒
静态时间字段Frequency可获只读频率,
StringBuilder创建实例时,会自动创建足够的内存空间来存储字串。
Capacity表示空间的大小,可以创建多少字符。当存储字符大于该容量时会
自动增大内存,增加Capacity。Length是当前字符串的长度。
默认Capacity为16,当需要更多空间时会翻倍。容量也可以人为指定。
但是,若人为指定MaxCapacity后,到达最大上限不会再扩而是引发异常。
构造函数:
StringBuilder() 初始化新实例,字符串值为String.Empty
StringBuilder(int32) 指定Capacity初始化实例
StringBuilder(String) 用指定字符串初始化
StringBuilder(Int32,Int32) 指定起始容量到最大容量
StringBuilder(String,Int32) 指定容量和字符串
StringBuilder(String,Int32,Int32,Int32) 指定子串(前三参数)和容量
value,startIndex,Length,capacity
属性:
capacity:容量,当前实例最大字符数
Length: 长度,当前字符实际长度
MaxCapacity:最大容量,一旦超限引发异常
Chars[]: 读写字符串某位置的字符。由于基于索引实例很大时会非常缓慢。
方法:
Append(byte/int/float/double/char/bool/decimal) 以字符串形式追加
Append(char,Int32) 追加Unicod字符的字符串重复数,后参数repeatCount
Append(char*,Int32) 不符合CLS,用下面替代。
Append(char[],Int32,In32)指定Unicode子数组追加
char[],startIndex,charCount
AppendLine() 将默认的行终止符追加到实例末尾。
AppendLine(String) 追加字串后加入行终止符。
默认的行终止符为Environment.NewLine,即回车换行
Clear:清除实例中所有字符。Length将变成0.
ToString() 将实例转换为String
ToString(Int32,Int32)将实例中子串转换为String。(starIndex,length)
CopyTo(Int32,Char[],Int32,Int32)源字串起始位置开始复制到目标Char指定位置
(int sourceIndex,char[] destination,int desIndex,int count)
Equals(StringBuilder) 是否与指定对象相等,返回bool
Remove(int startIndex,int length) 将指定范围字符移除
Insert(Int32,byte/int/single/double/decimal/char/string)指定位置插入
Insert(int index,string value,int count)将子串一个或多个插入指定位置
Insert(int index,char[] value,int startIndex,int charCount)
将指定Unicode字符的子串插入到指定位置
Replace(char,char)
Replace(string,string)
Replace(char oldChar,char newChar,int startIndex,int length)
将实例中子串范围的老字符,用新字符替换。
Repalce(string oldValue,string newValue,int startIndex,int Length)
同上,用新字串替换老字串
例:string与StringBuilder的效率.107ms VS 3ms 两者用时直接秒杀
string每次都要开辟堆空间浪费时间,StringBuilder不用直接更改即可
StringBuilder sb = new StringBuilder();string s = "";Stopwatch sw = Stopwatch.StartNew();for (int i = 0; i < 10000; i++){s += i;}sw.Stop();Console.WriteLine(sw.ElapsedMilliseconds);//107mssw.Restart();for (int i = 0; i < 10000; i++){sb.Append(i);}sw.Stop();Console.WriteLine(sw.ElapsedMilliseconds);//3ms
注意:一般最终会用ToString(),将StringBuilder转为stringw使用。
一切类型都可用ToString()将其转为字符串类型。
输出你输入字串的长度:
Console.WriteLine("随机输入你心中想到的一个名字:");//string s = Console.ReadLine();//两者都有Length属性StringBuilder s = new StringBuilder(Console.ReadLine());Console.WriteLine("你输入名字的长度是{0}", s.Length);
比较相等:
Console.WriteLine("A输入你喜欢的课程:");string s1 = Console.ReadLine();//aaConsole.WriteLine("B输入你喜欢的课程:");string s2 = Console.ReadLine();//aAif (s1.ToUpper() == s2.ToUpper())//大写只返回副本,并不更改原字串{ //s1.Equals(s2,StringComparison.OrdinalIgnoreCase);Console.WriteLine("相同" + s1);//aa}else { Console.WriteLine("不相同" + s1); }Console.WriteLine("C输入你喜欢的课程:");//ccStringBuilder s3 = new StringBuilder(Console.ReadLine().ToUpper());Console.WriteLine("D输入你喜欢的课程:");//cCStringBuilder s4 = new StringBuilder(Console.ReadLine().ToUpper());if (s3.Equals(s4)){Console.WriteLine("相同" + s3.ToString());//CC}else{Console.WriteLine("不相同" + s4.ToString());//CC}
splite分割并替换字串:
string s = "a b e_f,,,s'k i*j";char[] c = { ' ', '_', ',', '*' };string[] ss = s.Split(c);//替换成""//删除空串分割:string[] ss2 = s.Split(c, StringSplitOptions.RemoveEmptyEntries);string d = "2008-08-01";string[] dd = d.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);Console.WriteLine("{0,-6}年{1,-5}月{2:0}日", dd[0], dd[1], dd[2]);
四、输出中的复合格式字串
语法:{index[,alignment][:formatString]} 由"索引,对齐:格式字串"组成
index: 索引,由0开始,可多次引用。
alignment: 对齐,由当前位置向后期间位置间,为正右对齐,为负右对齐.
若不设置空白,紧接前面由本身长度决定后方起始位置.
formatString:格式化字串
时间自定义格式:
d 月中某天
dd 月中某天,不足两位,前面为0
ddd 一周中某天缩写,如周五Fri
dddd 一周中某天完整名称,如周五Friday
h 12小时制1-12
hh 12小时制01-12
H 24小时制0-23
HH 24小时制00-23
m 分钟0-59
mm 分钟00-59
M 月份1-12
MM 月份01-12
MMM 月份缩写,六月Jun
MMMM 月份全写,六月June
s 秒0-59
ss 秒00-59
t AM/PM中第一个
tt AM/PM
y 年0-99
yy 年00-99
yyy 年份000-999,最少三位数
yyyy
: 时间分隔 /日期分隔 \转义字符
数字:
0 占位,无该数字/0用0
# 占位,无该数字/0省略
. 小数点
, 三位(千位)分隔
% 数字乘以100,以百分位显示
%。 数字乘以1000,以千分位显示
E+0 结合上面
\
string 原样
; 仅一个,
两个,前面部分用于正值与零,后面用于负值。按最终四舍五入计入
三个,前面用于正值,第二部分用于负值,最后零
12.345 ("#0.0#;(#0.0#);-\0-") -> 12.35 //第一部分
0 ("#0.0#;(#0.0#);-\0-") -> -0- //最后部分
-12.345 ("#0.0#;(#0.0#);-\0-") -> (12.35) //第二部分
12.345 ("#0.0#;(#0.0#)") -> 12.35
0 ("#0.0#;(#0.0#)") -> 0.0
-12.345 ("#0.0#;(#0.0#)") -> (12.35)
五、string
定义:将文本表示为UTF-16代码单元的序列,String继承于Object.
也表示char对象的连续集合,一一对应char的实例,故可用
char数组来表示,唯一区别是String是只读(不可变)
string最多为10亿字符,约2GB
string s1="This is a string“;//直接赋字符串string s2=@"C:\a\b\c\d\e.txt“;//@取消转义char[] c={'w','o','r','d'};string s3=new string(c);//wordstring s4=new string('c',4);//ccccstring s5="abc"+"efg";//abcefgs5+="aa"; //abcefgaachar a=s5[1];//b 索引从0开始foreach(char b in s3){s+=b;}//wordword
区别:
Null :string已声明但未分配值,为Null,存储的指针为\0,空指针。
string在栈上空间内值没有指向,堆上没开辟空间,是一个空指针
String.Empty: 即"",已声明且在堆上已开辟空间,但空间内字串长度为0.
WhiteSpace:空白字符,肉眼无法辨别,如:空格 回车换行,Tab等.
unsafe 不安全
大部分C#是可验证的安全代码(由.Net工具可验证代码是否安全),一般安全代码不会
直接使用指针访问内存,也不会分配原始内存而是创建托管对象。
C#支持unsafe,它不一定是危险的,只是安全性由你自己掌握,不由.Net来管理验证。
语法:1.直接在类、方法等前面加入unsafe;
2.直接在代码块中使用unsafe.
public static unsafe void Main(){//须在项目属性中设置:允许不安全代码,否则报错char[] c = { 'a', 'b', 'c', '\0', 'A', 'B', 'C', '\0' };string s = null;//由长度指定fixed (char* cPtr = c) { s = new string(cPtr, 0, c.Length); }foreach (var ch in s) { Console.Write($"{(ushort)ch:x4} "); }Console.WriteLine();//0061 0062 0063 0000 0041 0042 0043 0000//不由长度指定,向后找结束符'\0',遇到就结束,若一直无,可能引发访问冲突fixed (char* cPtr = c) { s = new string(cPtr); }foreach (var ch in s) { Console.Write($"{(ushort)ch:x4} "); }//0061 0062 0063Console.ReadKey();}
CLS:Common Language Specification公共语言规范
CLR集成了多种语言,若要相互访问,须定义一个相互识别的规范,微软就定义了CLS
不同语言编写的对象就可彼此交互访问。
1、string的构造函数
String(Char*) (不符CLS)初始化指向Unicode字符数组的指定指针指示的值。
String(Char[]) 由指定字符数组初始化.
String(Sbyte*) 由指向8位有符号整数数组的指针指示的值来初始化
String(Char c,int Count) 指定重复次数的Unicode字符来初始化.为0则为Empty
String(Char* value,int startIndex,int length) 指定字符指针数组的范围来初始化
String(Char[] value,int startIndex,int length) 类似上面指定范围初始化
String(Sbyte* value,int startIndex,int length) 类似上面指定范围初始化
String(SByte* value,int startIndex,int length,System.Text.Encodeing enc)
类似上面,指定编码。若enc为null,则为ANSI编码
public static unsafe void Main(string[] args){char[] c = { 'a', 'b', 'c', '\u0000' };string s;fixed (char* cPtr = c) { s = new string(cPtr); }Console.WriteLine(s);//abcs = new string(c[1], 5);Console.WriteLine(s);//bbbbbConsole.ReadKey();}
2、属性
Char[] 字串中某索引的char值
length 字串的长度
string s = "abc";Console.WriteLine($"{s[0]},{s.Length}");//a,3
3、String运算符
== 是否相等,
!= 是否不相等
+ 连接,只要有一个是字串,按连接处理
string s1 = "abc", s2 = new string(new char[] { 'A', 'B', 'C' });Console.WriteLine("{0},{1}", string.Equals(s1, s2), s1 != s2);
4、换行
在字串输出中,可用转义符\n表示换行。
在代码输出中,只要不遇见分号或语块结束,默认是连续的。对字串可截取一部分回车后,
在下一行中用+,另起剩下的字串。
对逻辑符,可对逻辑表达式回车后,以运算符另起逻辑表达式
Console.WriteLine("abc\nABC");//两行输出string s = "abc" +"ABC";//字串另起if (s == "" &&s != string.Empty) //逻辑另起{ Console.WriteLine(s); }
5、方法
1)拆分
split(string[] separator,int count,StringSplitOptions options)
用指定分隔字串和可选项拆分为最大数量的子字串。
public static void Main(string[] args){string s1 = ",ONE,,TWO,,,THREE,,";string s2 = "[stop]ONE[stop][stop]TWO[stop][stop][stop]THREE[stop][stop]";char[] charSeparators = new char[] { ',' };string[] stringSeparators = new string[] { "[stop]" };string[] result;Show(s1.Split(charSeparators, StringSplitOptions.None));//.ONE..TWO...THREE... 用字符数组分隔,9个元素,null保留Show(s1.Split(charSeparators, StringSplitOptions.RemoveEmptyEntries));//ONE.TWO.THREE. 3个元素,null剔除Show(s2.Split(stringSeparators, StringSplitOptions.None));//.ONE..TWO...THREE... 用字串数组分隔,9个元素,null保留Show(s2.Split(stringSeparators, StringSplitOptions.RemoveEmptyEntries));//ONE.TWO.THREE. 3个元素,null剔除Show(s2.Split(stringSeparators, 2, StringSplitOptions.None));//.ONE[stop][stop]TWO[stop][stop][stop]THREE[stop][stop]. 2个元素,第一个空Show(s2.Split(stringSeparators, 2, StringSplitOptions.RemoveEmptyEntries));//ONE.TWO[stop][stop][stop]THREE[stop][stop]. 2个元素,剔除nullShow(s2.Split(stringSeparators, 7, StringSplitOptions.RemoveEmptyEntries));//ONE.TWO.THREE. 超个本身仍按本身最多元素算,3个元素,剔除nullConsole.ReadKey();}public static void Show(string[] strings){foreach (string s in strings) { Console.Write(s + "."); }Console.WriteLine();}
注:split方法忽略分割符为null和""的情况。
匹配规则:实例中遇到的子串优于分割元素的顺序。
即实例从头开始向后取子串,分割符从索引0开始匹配,不符合,索引增加;
符合继续子串后扩,直到完全匹配。
1.字串"abcdef",分割符{"ef","bcde"},结果{"a","f"}
后扩至abcde时,分割索引0不匹配,增加索引为1即bcde,匹配。结果a与f.
2.上例分割符为{"bcd","bc"},结果{"a","def"}
扩至ab时,索引0有b相同(索引1排不上号),继续abc,索引0仍有相同(索引1
仍然排不上号),继续abcd时,索引0完全匹配,结果a与ef
3.上例分割符为{"bc","bcd"},结果{"a","def"}
扩至ab,索引0有b相同(同理索引1吃灰),扩至abc时,索引0完全匹配,结果
为a和def。
4.上例分割符{"cd","c","bce"},结果{"ab","ef"}
扩至ab时,索引0与1吃灰,索引2有b上位,继续后扩abcd,索引2不符。回头
继续用索引0与1,两者都上位,但索引前位0优先,cd匹配,结果ab与ef
5.上例分割符{"c","cd","bce"},结果{"ab","def"}
继4分析,到abcd时,索引2吃灰,返回索引0上位,符合,结果ab与def
6.上例分割符{"d","cde","b","bcdd"} 结果为a,null,f
到ab时,索引2上位,匹配,分成a与cdef;继续匹配(a就不分析了),cdef从头
开始,c时只有索引1上位,继续cd,索引1仍然上位(子串优先索引所以索引0只
能干看),cde时索引1完全匹配,于是结果是a,null,f. 共三个元素。
总结:子串先上位则占位,不符时,再索引依次占位。索引优先级最低。
只要有符合部分,哪怕后面的索引也将占位.
public static void Main(string[] args){string s = "abcdef";string[] separator1 = { "b", "bcd" };//1string[] separator2 = { "bcd", "b" };//2string[] separator3 = { "bc", "bcd" };//3string[] separator4 = { "bcde", "bc" };//4string[] separator5 = { "d", "bcd" };//5string[] separator6 = { "bcd", "d" };//6string[] separator7 = { "c", "cd", "bce" };//7string[] separator8 = { "d", "cde", "bcdd", "b" };//8Console.WriteLine("------------1-2");Show(s.Split(separator1, StringSplitOptions.None));//a^cdef^2Show(s.Split(separator2, StringSplitOptions.None));//a^ef^2Console.WriteLine("------------3-4");Show(s.Split(separator3, StringSplitOptions.None));//a^def^2Show(s.Split(separator4, StringSplitOptions.None));//a^f^2Console.WriteLine("------------5-6");Show(s.Split(separator5, StringSplitOptions.None));//a^ef^2Show(s.Split(separator6, StringSplitOptions.None));//a^ef^2Console.WriteLine("------------7-8");Show(s.Split(separator7, StringSplitOptions.None));//ab^def^2Show(s.Split(separator8, StringSplitOptions.None));//a^^f^3Console.ReadKey();}public static void Show(string[] strings){foreach (string s in strings) { Console.Write(s + "^"); }Console.WriteLine(strings.Length);}
split(char[] separator,int count,StringSplitOptions options)
用指定分隔字符和可选项拆分最大数量count的子字符串
split(string[] separator,StringSplitOptions options)
split(char[] separator,StringSplitOptions options)
split(params char[] separator) 用指定分隔字符拆分
2)大小写副本
ToUpper() 返回字串转为大写的副本
ToLower() ............小........
3)判断开始或结尾
StartsWith(string value) 判断开始是否为指定字串,返回bool
EndsWith(string value) ....结尾..........
StartsWith(string value,StringComparison comparisonType)
判断开始,选项忽略大小写用得多OrdinallgnoreCase
EndsWith(string value,StringComparison comparisonType)
判断结尾,选项忽略大小写用得多OrdinallgnoreCase
4)删除前后匹配符
Trim() 删除前后空白符
TrimEnd() 删除末尾空白符
TimeStart() ....开始.....
Trim(parms char[] trimChars) 删除前后指定字符
TrimEnd(parms char[] trimChars) ....结尾..
TrimStart(parms char[] trimChars) ....开始..
5)子串,转换
Substring(int startIndex) 指定位置到字串末尾(索引从0开始)索引大于长度或小于零异常
Substring(int startIndex,int length) 指定位置开始到指定长度
string s="abcdef";s.Substring(2);//cdefs.Substring(2,2);//cd
ToCharArray() 将此实例的字符串复制到Unicode字符数组。返回Char[]
逆方法:若字符数组->字串:用构造函数String(Char[])
ToCharArray(int startIndex,int length) 类上,指定起始和长度复制到Char[]
string s="abcdef";char[] c=s.ToCharArray();//{'a','b','c','d','e','f'}char[] c1=s.ToCharArray(4,2);//{'e','f'}
ToString() 转换为String,不执行实际转换。引用类型一般返回类型
int a = 3; double b = 2.3;Stopwatch sw = new Stopwatch();Console.WriteLine($"{a.ToString()},{b.ToString()},{sw.ToString()}");//3,2.3,System.Diagnostics.Stopwatch 上面转换可省,会自动转string
6)替换
Replace(char oldChar,char newChar) 用新字符替换老字符,返回一新string
Replace(string oldValue,string newValue) 用新串替换老串,返回一新串
注:返回是新串,原串未发生改变;区分大小写。可连续调用链接一起,实现多次替换
string s = "abcdef";string s1 = s.Replace('a', 'b').Replace('d', 'w');//bbcwefstring s2 = s.Replace("d", "e").Replace("f", "g");//abceeg
7)删除
Remove(int startIndex,int count) 删除从起始到指定长度的字串,返回新串,原串未变.
Remove(int startIndex) 删除从起始到末尾的字串。
string s = "abcdef";string s1 = s.Remove(2);//abstring s2 = s.Remove(2, 2);//abef
8)填充
PadLeft(int totalWidth) 左侧填充空格,使新串总长为totalWidth,实现右对齐
PadLeft(int totalWidth,char paddingChar) 左侧用指定字符填充,实现右对齐
PadRight(int taotalWidth) 右侧填充空格.............................左对齐
PadRight(int totalWidth,char paddingChar) 右侧...
string s = "ab";string s1 = s.PadLeft(5); // abstring s2 = s.PadLeft(5, 'z');//zzzabstring s3 = s.PadRight(5); //ab
9)查找索引
IndexOf(string value,int startIndex,int count,StringComparison comparisonType)
value要搜索的字串,startIndex搜索起始位置,count起始往后长度,末参是否区别大小
IndexOf(string value,int startIndex,StringComparison comparisonType)
搜索起始到末尾
IndexOf(string value,int startIndex,int count) 指定起始、位置
IndexOf(char value,int startIdex,int count)
IndexOf(string value,StringComparison comparisonType) 是否区分大小写(字符不需要)
IndexOf(string value,int startIdex) 指定起始到末尾
IndexOf(char value,int starIdex)
IndexOf(string value) 搜索整个
IndexOf(char value)
string s = "abAbefgta"; int n;n = s.IndexOf("a", 1, 2, StringComparison.OrdinalIgnoreCase);//2n = s.IndexOf("a", 1, 2, StringComparison.Ordinal);//-1n = s.IndexOf('a', 4, 2);//-1n = s.IndexOf('a', 4, 5);//8 5改成6时会异常,索引超限
类似上面是找第一个匹配项,下面是搜索最后一个匹配项.
LastIndexOf(string value,int startIdex,int count,StringComparison comparisonType)
count是从startIndex从右往左的字符数,超限会异常
LastIndexOf(string value,int startIndex,Stringcomparison comparisonType)
指定起始从右往左到起始
LastIndexOf(string value,int startIndex,int count)
LastIndexOf(char value,int startIndex,int count)
LastIndexOf(string value,int startIndex)
LastIndexOf(char value,int startIdex)
LastIndexOf(string value)
LastIndexOf(char value)
LastIndexOf(string vlaue,StringComparison comparisonType)
string s = "abAabefagta"; int n = 0;//"a",1,3 时会异常,起始索引1从右往左3个字符超出数组限制n = s.LastIndexOf("a", 3, 3, StringComparison.OrdinalIgnoreCase);//3n = s.LastIndexOf("A", 3, 3, StringComparison.Ordinal);//2n = s.LastIndexOf('a', 10, 4);//10n = s.LastIndexOf('a', 9);//7n = s.LastIndexOf("a");//10
=========多个查找,多个字符数组去查找,返回第一个匹配项
IndexOfAyn(char[] anyof,int startIndex,int count) 指定起始、位置
IndexOfAny(char[] anyof,int startIndex)
IndexOfAny(char[] anyof) anyof数组中只要有一个匹配立即返回当前索引
LastIndexOfAny(char[] anyof,int startIndex,int count)
LastIndexOfAny(char[] anyof,int startIndex)
LastIndexOfAny(char[] anyof)
string s = "abcdeef";char[] c = { 'e', 'f', 'c' };Console.WriteLine(s.IndexOfAny(c));//2 其中c先匹配//4改成3,会因5向字串前面位置超限引发异常Console.WriteLine(s.LastIndexOfAny(c, 4, 5));//2 e先匹配
10)分割式连接
String.Join(string separator,System.collection.Generic.IEnumerable<string> values)
串连集合values各成员,仅在成员间用指定分隔符
String.Join(string separator,params object[] values) 所有元素
String.Join(string separator,params string[] value)
String.Join(string separator,string[] value,int startIndex,int count) 指定元素
String.Join<T>(string separator,System.Collections.Generic.IEnumerable<t> values)
string[] s = { "a", "b", "c", "d" };List<int> lst = new List<int>() { 1, 2, 3, 4 };//注意是成员之间,首部与末尾都没有分割符^Console.WriteLine(string.Join("^", s));//a^b^c^dConsole.WriteLine(string.Join("^", lst));//1^2^3^ 4Console.WriteLine(string.Join("^", 'a', 'b', 'c'));//a^b^cConsole.WriteLine(string.Join("^", s, 1, 2));//b^c
注意:1.被连接成员会隐式转为字符串;
2.若连接第一个成员为null时,将不会连接各成员。第一元素应处理成Empty方可执行;
3.若分隔符为null或除第一元素外其余为null,将以String.Empty代替。
11)连接(+)
String.Concat(System.Collections.Generic.IEnumerable<string> values)
各成员串联(不加分隔符),若成员为null则视为String.Empty处理
String.Concat(string str0,string str1,string str2,string str3) 四个相加
String.Concat(string str0,string str1,string str2) 三个相加
String.Concat(string str0,string str1)
String.Concat(object arg0,object arg1,object arg2,object arg3) 隐式转换成string相连
String.Concat(object arg0,object arg1,object arg2)
String.Concat(object arg0,object arg1)
String.Concat(params string[] values) 成员有null时自动用String.Empty替换
String.Concat(params object[] args)
String.Concat<T>(System.Collections.Generic.IEnumerable<T> values) 成员相连
String.Concat(object arg0) 实际调用ToString()
12)是否相等bool
Equals(string value,StringComparison comparisonType) 是否相等,返回bool、
String.Equals(string a,string b,StringComparison comparisonType)
String.Equals(string a,string b)
Equals(object obj) obj隐式可转字串
Equals(string value)
13)插入
Insert(int startIndex,string value) 指定索引位置插入指定字串,返回新字串.
指定索引最大可为原索引+1
string s = "abcd";Console.WriteLine(s.Insert(3, "z"));//abczdConsole.WriteLine(s.Insert(4, "z"));//abcdz 4改5异常
14)拘留池(暂存池、缓冲池、暂存池)the intern pool
因为字符串是不可变的,所以CLR(CLR是公共语言运行时,Common Language Runtime)可能会
将相同值的字符串用同一个实例。程序中大量使用字符串,有不少是重复性的,为了降低内存
占用,.Net将代码中声明的字符串放到字符串拘留池中,值相同的字符串共享同一个实例。字
符串是不变的。不是所有字符串都在拘留池中,.Net会判断哪些该放。
通用语言运行时通过维护一个被称为拘留池的表来节约字符串的存储,该表包含对程序中
以编程方式声明或创建的每个独特字面字符串的单一引用。因此,一个具有特定值的字面字
符串的实例在系统中只存在一次。故多个字面字符串会指向同一实例以节约内存。
当给一个变量分配字符串的时候,CLR先到驻留池里找,如果找到了,就将该字符串的引用
给这个变量,如果没有,就将该字符串创建到驻留池里,然后在将引用给该变量。
动态字符串默认是不在字符串拘留池中的。
string s1 = "拘留池", s2 = "拘留池";Console.WriteLine("{0},{1}", s1 == s2, ReferenceEquals(s1, s2));//T Tstring s3 = "abc", s4 = new string(s3.ToCharArray());Console.WriteLine("{0},{1}", s3 == s4, ReferenceEquals(s3, s4));//T Fstring s5 = "abc", s6 = "ab" + "c";//字面符,为静态,进入拘留池查找Console.WriteLine("{0},{1}", s5 == s6, ReferenceEquals(s5, s6));//T T//string s7 = Console.ReadLine();//输入abc 为动态不进入拘留池//Console.WriteLine("{0},{1}", s5 == s7, ReferenceEquals(s5, s7));//T Fstring s8 = new string("abc".ToCharArray());Console.WriteLine("{0},{1}", s5 == s8, ReferenceEquals(s5, s8));//T Fstring s9 = (new StringBuilder("abc")).ToString();Console.WriteLine("{0},{1}", s5 == s9, ReferenceEquals(s5, s9));//T Fstring a = "a", b = "b", c = "c", d = a + b + c;//d产生了ab与abc两个//+连接是新开辟空间,所以地址是不一样的Console.WriteLine("{0},{1}", s5 == d, ReferenceEquals(s5, d));//T F
15)添加拘留池
String.Intern(string str) 在拘留池搜索str,若有返回引用,若无添加入池再返回引用
String.IsIntern(string str) 检测str是否在池,在返回引用,无返回null.
string s1 = "MyTest";string s2 = new StringBuilder().Append("My").Append("Test").ToString();string s3 = string.Intern(s1);//检测s1,入池并返回引用. s1与s3同引用Console.WriteLine(ReferenceEquals(s1, s2));//FalseConsole.WriteLine(ReferenceEquals(s1, s3));//True
16)GetEnumerator取得
CharEnumerator GetEnumerator() String.GetEnumerator由字串构造字符枚举器
string s = "The Example Of String.GetEnumerator";CharEnumerator ce = s.GetEnumerator(); //取得字符枚举器对象while (ce.MoveNext())//索引起始位于第一个之前,移动成功True{//索引若超出最后一个字符,则不会更改索引,移动失败返回falseif (char.IsUpper(ce.Current)) Console.Write(ce.Current);else Console.Write(char.ToUpper(ce.Current));}
THE EXAMPLE OF STRING.GETENUMERATOR
17)字串比较
String.Compare(string strA,int indexA,string strB,int indexB,int length,
System.Globlization.CultureInfo culture,
System.Globlization.CompareOptions options)
字串strA与strB分别从各自的起始位置开始比较长度间字符。
culture为指定区域,若为null则使用当前区域。
CompareOptions指定比较项,如忽略大小写,符号
返回:<0,strA在strB前;0,相同或length=0;>0,strA在strB之后.
String.Compare(string strA,int indexA,string strB,int indexB,int length,
bool ignoreCase,
System.Globalization.CultureInfo culture)
String.Compare(string strA,int indexA,string strB,int indexB,int length,
StringComparison comparisonType)
String.Compare(string strA,int indexA,string strB,int indexB,int length,
bool ignoreCase)
String.Compare(string strA,int indexA,string strB,int indexB,int length)
String.Compare(string strA,string strB,
System.Globalization.CultureInfo culture,
System.Globalization.CompareOptions options)
String.Compare(string strA,string strB,bool ignorCase,
System.Globalization.CultureInfo culture)
String.Compare(string strA,string strB,StringComparision comparsionType)
String.Compare(string strA,string strB,bool ignoreCase)
String.Compare(string strA,string strB)
string s1 = "Jack Smith", s2 = "JAcn Doe";CompareOptions co=CompareOptoins.IgnoreCase;string.Compare(s1, 0, s2, 0, 1, new CultureInfo("en-Us"), co);//0string.Compare(s1, 0, s2, 0, 2, new CultureInfo("en-Us"), co);//0string.Compare(s1, 0, s2, 0, 3, new CultureInfo("en-Us"), co);//0string.Compare(s1, 0, s2, 0, 4, new CultureInfo("en-Us"), co);//-1
string a = "hello";string b = "h";b += "ello";Console.WriteLine(a == b);//true 值是否相等Console.WriteLine(string.ReferenceEquals(a, b));//false 实例是否相同
string s = "abdicdkadkeaekda";int index = 0, index1 = 0;while (index != -1){index = s.IndexOf("a", index1);if (index >= 0){Console.WriteLine(index);index1 = index + 1;}}
string p = @"C:\a\b\c\d\e\f\abc.mp3";int index = p.LastIndexOf("\\");//最后一个\Console.WriteLine(p.Substring(index + 1));Console.ReadKey();//取文件名
string[] s = { "我", "们", "是", "中", "国", "人" };string sNew = string.Join("|", s);Console.WriteLine(sNew);//我|们|是|中|国|人
string s = "abc";char[] c = s.ToCharArray();Array.Reverse(c);s = new string(c);Console.WriteLine(s);
Console.WriteLine("输入一段英文句子:");string s = Console.ReadLine();string[] s1 = s.Split(new char[] { ' ', '.', ',' }, StringSplitOptions.RemoveEmptyEntries);Array.Reverse(s1);Console.WriteLine(string.Join(" ", s1));
string s = "abc@163.com";int index = s.IndexOf('@');Console.WriteLine(s.Substring(0, index - 1));Console.WriteLine(s.Substring(index + 1));
六、指针
指针类型声明:
type* identifier;
void* identifier;//允许,但不推荐。因未说明具体指针类型
int* p1,p2,p3;//正确,三个指针int *p1,p2,p3;//错误,只能按语法int*
指针不能用于引用类型,一般用于值类型
int* p;//指向整数的指针--------*p表示由int中指针找到指向的值
int** p;//指向整数的指针的指针
int*[] p;//指向整数的指数的一维数组
char* p;//指向字符的指针
void* p;//指向未知类型的指针
指针运算:
* 执行指针间寻址 a=*&a
-> 通过指针访问结构的成员. x->y等同(*x).y
[] 为指针建立索引
& 获取变量的地址
++和-- 递增/减指针
+/- 执行指针算法
==,!=,>,>=,<,<= 比较指针
stackalloc 在堆栈上分配内存
fixed语句
防止GC重新定位可移动变量,并声明指向该变量的指针。固定变量的地址在语句的
持续时间内不会更改。
只能在相应的fixed语句中使用声明的指针。声明的指针是只读,不可修改。
只能在unsafe上下文中使用fixed语句。
fixed保证GC在语句主体执行期间不会重新定位或释放包含对象实例。
unsafe{int[] n = { 10, 20, 30 };int* p;fixed (int* first = &n[0], last = &n[2]){//连续8字节,即2个int32(4字节)Console.WriteLine((int)last - (int)first);//8p = first + 1;//指针移动1个int,即4位,指向n[1]Console.WriteLine(*last - *p);//10}//fixed内定义的指针不可更改}
七、继承
开发中,每一个类应单独写在一个文件中,不能混合.
把多个类中重复的成员封装成单独的一个类,作为这些类的父类或基类,以解决代码冗余。
这几类称为父类的子类或派生类。
子类继承于父类public的属性与方法。不继续私有成员private.
C#中,所有类直接或间接继承了object类。若没写继承,那它就继承object。
子类有没有继承父类的构造函数????
子类不能继承父类的构造函数。但是,父类必须要有无参的构造函数,因为子类构造之前
先要构造父类(即创建子类对象之前,其内部先要创建一个父类对象,以便子类继承它的成员)
当父类创建有参构造函数后,无参构造函数消失。子类默认调用父类的无参函数来创建父
类对象,以便子类继承父类中的成员。此时,若父类消失了无参构造函数,会引发子类错误。
解决办法:
1)在父类中手动重新写一个无参的构造函数,以便子类调用。
2)在子类的构造函数中显式调用父类的构造函数。
在子类构造函数的后面用:base(参数表) 来调用父类的构造函数
八、继承的特性
1.继承的单根性:一个子类只能有一个父类(基类)。
2.继承的传递性:
九、New关键字
1)创建新对象;
2)隐藏从父类那里继承过来的成员。
若子类有成员与父类成员相同,子类会隐藏父类的这个成员,即只能调用同名的子类成员。
此时vs会提示警告,若是故意隐藏,添加new表示意图后,警告消失。
public class Person //基类{private string _name; private int _age; private char _gender;public string Name{ get { return _name; } set { _name = value; } }public int Age{ get { return _age; } set { _age = value; } }public char Gender{ get { return _gender; } set { _gender = value; } }public Person(string name, int age, char gender){ Name = name; Age = age; Gender = gender; }public void SayHello(){ Console.WriteLine("基类同名时,被子类隐藏"); }}public class Student : Person //继承{private double _worktime;public double Worktime{ get { return _worktime; } set { _worktime = value; } }public Student(double worktime, string name, int age, char gender) : base(name, age, gender){ Worktime = worktime; }//用base调用基类构造函数public new void SayHello() //不加new不出错,但会有警告{ Console.WriteLine("我叫{0},我年龄是{1},我是一名{2}生,工作年限{3}。", Name, Age, Gender, Worktime); }}
根据上面,Studendt继承于Person:
Student s = new Student(3, "孙全", 33, '男');s.SayHello();
相关文章:
(10)C#传智:命名空间、String/StringBuilder、指针、继承New(第10天)
内容开始多了,慢品慢尝才有滋味。 一、命名空间namespace 用于解决类重名问题,可以看作类的文件夹. 若代码与被使用的类,与当前的namespace相同,则不需要using. 若namespace不同时,调用的方法:…...
基于Jetson Tx2 Nx的Qt、树莓派等ARM64架构的Ptorch及torchvision的安装
前提 已经安装好了python、pip及最基本的依赖库 若未安装好点击python及pip安装请参考这篇博文 https://blog.csdn.net/m0_51683386/article/details/129320492?spm1001.2014.3001.5502 特别提醒 一定要先根据自己板子情况,找好python、torch、torchvision的安…...
MySQL存储引擎详解及对比和选择
什么是存储引擎? MySQL中的数据用各种不同的技术存储在文件(或者内存)中。这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力。通过选择不同的技术,你能够获得额外的速度或者功能,从而改善…...
【推拉框-手风琴】vue3实现手风琴效果的组件
简言 在工作时有时会用到竖形手风琴效果的组件。 在此记录下实现代码和实现思路。 手风琴实现 结构搭建 搭建结构主要实现盒子间的排列效果。 用flex布局或者其他布局方式将内容在一行排列把每一项的内容和项头用盒子包裹, 内容就是这一项要展示的内容…...
滑动窗口最大值:单调队列
239. 滑动窗口最大值 难度困难2154收藏分享切换为英文接收动态反馈 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例…...
负载均衡算法
静态负载均衡 轮询 将请求按顺序轮流地分配到每个节点上,不关心每个节点实际的连接数和当前的系统负载。 优点:简单高效,易于水平扩展,每个节点满足字面意义上的均衡; 缺点:没有考虑机器的性能问题&…...
C语言数组二维数组
C 语言支持数组数据结构,它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据,但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量,比如 runoob0、runoob1、…、runoob99,而是…...
7年测试工程师,裸辞掉17K的工作,想跳槽找更好的,还是太高估自己了....
14年大学毕业后,在老师和朋友的推荐下,进了软件测试行业,这一干就是7年时间,当时大学本来就是计算机专业,虽然专业学的一塌糊涂,但是当年的软件测试属于新兴行业,人才缺口比较大,而且…...
企业为什么需要做APP安全评估?
近几年新型信息基础设施建设和移动互联网技术的不断发展,移动APP数量也呈现爆发式增长,进而APP自身的“脆弱性”也日益彰显,这对移动用户的个人信息及财产安全带来巨大威胁和挑战。在此背景下,国家出台了多部法律法规,…...
重回利润增长,涪陵榨菜为何能跑赢周期?
2022年消费市场持续低迷,疫情寒冬之下,不少食品快消企业均遭遇严重的业绩下滑,但一年里不断遭遇利空打击的“榨菜茅”涪陵榨菜,不仅安然躲过“酸菜劫”、走出“钠”争议,而且顺利将产品价格提起来,并在寒冬…...
这6个高清图片素材库,马住,马住~
网上找的图片素材清晰度不够,版权不明确怎么办。看看这几个可商用图片素材网站,解决你的所有图片需求,高清无水印,赶紧马住! 1、菜鸟图库 美女图片|手机壁纸|风景图片大全|高清图片素材下载网 - 菜鸟图库 网站素材…...
绝对零基础的C语言科班作业(期末模拟考试)
编程题(共10题; 共100.0分)模拟1(输出m到n的素数)从键盘输入两个整数[m,n], 输出m和n之间的所有素数。 输入样例:3,20输出样例:3 5 7 11 13 17 19 (输出数据之间用空格间…...
注解开发定义bean
注解开发定义bean 使用Component定义bean在核心配置文件中通过组件扫描加载bean,需要指定扫描包的范围 当然也可以使用Component的衍生注解,可以更加形象的表示 纯注解的开发模式 使用java类来代替了以前的 配置文件,在java类中ÿ…...
剑指 Offer 19. 正则表达式匹配
摘要 剑指 Offer 19. 正则表达式匹配 请实现一个函数用来匹配包含. 和*的正则表达式。模式中的字符.表示任意一个字符,而*表示它前面的字符可以出现任意次(含0次)。在本题中,匹配是指字符串的所有字符匹配整个模式。例如&#x…...
CSS——学成在线案例
🍓个人主页:bit.. 🍒系列专栏:Linux(Ubuntu)入门必看 C语言刷题 数据结构与算法 HTML和CSS3 目录 1.案例准备工作 2.CSS属性书写顺序(重点) 3.页面布局整体思路 4.头部的制作编辑 5.banner制作…...
元数据的类型
元数据通常分为三种类型:业务元数据、技术元数据和操作元数据。这些类别使人们能够理解属于元数据总体框架下的信息范围,以及元数据的产生过程。也就是说,这些类别也可能导致混淆,特别是当人们对一组元数据属于哪个类别或应该由谁…...
LEAP模型的能源环境发展、碳排放建模预测及不确定性分析
LEAP(Long Range Energy Alternatives Planning System/ Low emission analysis platform,长期能源可替代规划模型)是一种自下而上的能源-环境核算工具,由斯德哥尔摩环境研究所和美国波士顿大学联合研发。该模型与情景分析法紧密结…...
C# Task详解
1、Task产生背景 Task出现之前,微软的多线程处理方式有:Thread→ThreadPool→委托的异步调用,虽然也可以基本业务需要的多线程场景,但它们在多个线程的等待处理方面、资源占用方面、线程延续和阻塞方面、线程的取消方面等都显得比…...
Blob分析+特征
Blob分析特征0 前言1 概念2 方法2.1 图像采集2.2 图像分割2.3 特征提取3 主要应用场景:0 前言 在缺陷检测领域,halcon通常有6种处理方法,包括Blob分析特征、Blob分析特征差分、频域空间域、光度立体法、特征训练、测量拟合,本篇博…...
4EVERLAND 的 IPFS Pinning 服务:4EVER Pin
我们很高兴地宣布 4EVERLAND Storage 的一个令人兴奋的补充,即 4EVER Pin。什么是 4EVER Pin?您可能已经知道星际文件系统或IPFS是一个分布式存储网络,来自世界各地的计算机组成节点共享数据。通常,在IPFS中获取一条数据时&#x…...
activiti整合springBoot其他操作
如果单纯使用activiti进行流程的自动控制,是可以实现的。但是通常我们都需要结合自定义的表,便于在流程执行中更加清晰的看到每一个流程实例节点的具体信息。关联自定义表与activiti表才能完成真正的业务 BusinessKey关联 // 定义businessKey Test pub…...
深度探索C++预编译头机制
深度详见预编译头,以vs编译器实现的预编译头管理为例 预编译头是为了节省庞大的编译时间,采取的一种方法;C标准并没有规定如何实现预编译头机制;因此其具体实现方式由编译器供应商自行决定。 下面就以VS中观测的结果为例进行说明…...
Leaflet基础入门教程(一)
leaflet是一个前端的轻量的gis框架,为什么说它轻量呢。因为相比于传统的“庞大的”GIS框架比如openlayers和mapbox,leaflet不仅代码体积小,而且API构成也极为简单。是GIS行业小白入门级别学习的最好的框架,没有之一。 那么话不多说我们首先来学习一下如何使用leaflet搭建一…...
《强化学习导论》之6.5 Q-Learning
Q-Learning:Off-Policy TD Control强化学习的早期突破之一是开发了一种称为Q学习的非策略TD控制算法(Watkins,1989)。其最简单的形式,定义为(6.8)在这种情况下,学习的动作-值函数Q直接近似于最优动作-值函数࿰…...
5年软测,女朋友跑了俩,2年外包感觉自己废了一半,怎么办?
17年毕业,校招毕业就进入一家软件公司,干了2年的点工,随后进入一家外包公司工作至今,安逸使人堕落不知进取,加之随着近年的环境不景气,谈了多年将要结婚的女朋友也因为我的心态和工资要跟我闹分手我想改变现…...
【JavaWeb】HTML常用标签
HTML标签结构 HTML语言主要都是由标签构成的。 标签名 在 <> 中 如<body> 标签大部分成对出现,代表开始和结束 如 <body>标签中的内容</body> 少部分单个出现,叫单标签 </br> 代表换行 标签中可以加属性,多个…...
python编程:查找某个文件夹下所有的文件,包括子文件加下的所有文件,读取指定类型的文件
目录 一、实现要求 二、代码实现 三、效果测试 一、实现要求 1、在电脑上有一个文件夹,该文件夹下面还有子文件夹,具体层级不清楚,需要实现将该文件夹下所有的文件路径读取出来; 2、在1的基础上,只需读取指定类型的文…...
测试外包干了5年,感觉自己已经废了····
前两天有读者想我资讯: 我是一名软件测试工程师,工作已经四年多快五年了。现在正在找工作,由于一直做的都是外包的项目。技术方面都不是很深入,现在找工作都是会问一些,测试框架,自动化测试,感…...
C++17 文件与目录操作 <filesystem>
目录 路径操作 目录遍历 文件检查和操作 总结 每次写C进行目录操作时,我一般都是调平台的SDK,尤其是win32 api 非常难记,于是查一下文档看看有没有和Python中os模块一样好用的库。 于是发现 filesystem,从来没用过࿰…...
Python 如何安装 MySQLdb ?
人生苦短 我用python Python 标准数据库接口为 Python DB-API, Python DB-API为开发人员提供了数据库应用编程接口。 Python 数据库接口支持非常多的数据库, 你可以选择适合你项目的数据库: GadFlymSQLMySQLPostgreSQLMicrosoft SQL Serve…...
重庆食品商城网站设计/今日头条新闻大事件
在前端日常开发中,我们经常git来当做代码版本管理工具,使用中基本都是一个项目一个Git仓库的形式,那么当我们的代码中碰到了业务级别的需要复用的代码,我们一般怎么做呢? 我们大致的考虑一下,一般有两种方案:抽象成NPM包进行复用使用Git的子仓库对代码进行复用在涂鸦的小程序业…...
怎么做可以看外国视频网站/最近的新闻大事
Docker-compose overview 文章目录Docker-compose overview1. 简介2. 使用步骤3. 生命周期4. 特色1. 简介 docker-ompose 是一个用于定义和运行多容器 Docker 应用程序的工具。使用 docker-compose,您可以使用 YAML 文件来配置应用程序的服务。然后,使用…...
建设电商网站/高端企业建站公司
linux shell命令下我们可以通过相关命令关闭和重启计算机,下面由学习啦小编为大家搜集整理了linux shell的关机命令是什么的相关知识,希望对大家有帮助!linux shell的关机命令问题描述对于Linux系统而言,许多时候是用于服务器之类的ÿ…...
上海市工商网站官网/免费拓客软件
使用范围: OA、MIS、ERP等信息管理类的项目,暂时不考虑网站。 遇到的问题: 完成一个项目,往往需要引用很多js文件,比如jQuery.js、easyUI等。还有自己写的一些列js文件,那么这些文件如何方便的加载…...
呼市网站建设/网络推广服务合同
readonly在代码中只能在字段初始化器和构造函数中赋值,并不是说readonly只能赋值一次,超出这个范围以后readonly就不能通过代码修改了,但是还是可以用反射来修改,readonly仅仅是提示编译器在其他地方赋值的时候编译错误而已 来源&…...
阿里云网站公安备案系统/挖掘关键词的工具
文章目录vmplayer介绍1.下载和安装2.下载虚拟机镜像3.创建新的虚拟机创建虚拟机运行附件vmplayer介绍 VMware Player (现已更名为VMware Workstation Player)是一款桌面虚拟化应用,无需重新启动即可在同一计算机上运行一个或多个操作系统。凭…...