C#编程入门13_String类及常用的工具类

String类

  • 字符串的特性 
    String类用来比较两个字符串、查找和抽取串中的字符或子串。 
    string可以看做是char的只读数组。 
    C#中字符串有一个重要的特性:不可变性,字符串一旦声明就不再可以改变。 
    注意:对该类对象的任何操作都将返回一个新的字符串对象 除了Clone Clone直接将该字符串的引用返回了

    示例: 
    String s1 = “a”; 
    String s2 = s1 + “b”; 
    Console.WriteLine(Object.ReferenceEquals (s1,s2));

    谁说字符串不可变?string s = “abc”;s=”123“;,s这不是变了吗 
    要区分变量名和变量指向的值的区别。程序中可以有很多字符串,然后由字符串变量指向他们,变量可以指向其他的字符串,但是字符串本身没有变化。字符串不可变性指的是内存中的字符串不可变,而不是变量不变。 
    string s10 = s;//s10指向s指向的字符串,而不是s10指向s,哪怕s以后指向了其他内存,那么s10还是指向从前s指向的字符串。

  • 字符串的构造 
    String s = “abc”; 
    String s = new String(“fgh”.ToCharArray()); 
    String copyS = String.Copy(s); 
    String newS = s.Clone() as String;

  • 字符串的遍历 
    字符串是一个字符数组 
    所以可以用遍历数组的方式遍历字符串的每一个位子的字符

    示例:

    String s1 = "123456";
    for (int i=0;i<s1.Length;i++)
    {
        Console.WriteLine(s1[i]);
    }
       
       
    • 1
    • 2
    • 3
    • 4
    • 5

    注意: 
    字符串中的字符位置和数组一样从下标0开始 
    字符串和数组一样有Length属性 
    字符串和数组一样可以按索引的方式访问

  • 字符串的大小写转换

static void Task()
{
    string str = "abcdefgh";
    //将字符串中的小写字母转化成大写字母
    str = str.ToUpper();
    Console.WriteLine(str);

    //将自服装中的大写字母转化成小写字母
    str = str.ToLower();
    Console.WriteLine(str);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 字符串的截取
static void Task()
{
    string no = "222023333";
   //从某个位置开始截取  以直接截取到字符串的末尾
   string retStr = no.Substring(5);
   Console.WriteLine(retStr);
   //从索引为0的位置开始截取5个长度的字符座位字符串返回
   retStr = no.Substring(0,5);
   Console.WriteLine(retStr);
}
//自己实现的方法:
static string MySubstring(string str, int startIndex, int len)
{
    string retStr = string.Empty;
    for (int i = startIndex; i < startIndex+len; i++)
    {
        retStr += str[i];
    }
    return retStr;
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 字符串的分割
static void Task()
{
    string str = "I have     a dream";
    //剔除结果中的空字符
    string[] strArr = str.Split(new char[] { ' '},StringSplitOptions.RemoveEmptyEntries);
    Console.WriteLine(strArr.Length);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 字符串的替换
static void Task()
{
    string str = "TMD,你玩呢?";
    //用"**"替换"TMD"
    str = str.Replace("TMD","**");
    Console.WriteLine(str);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 字符串的查询
static void Task()
{
    string str = "C#编程之道";
    int index = str.IndexOf('编');
    Console.WriteLine(index);
    //返回从索引0开始搜索到第一个字符串为"编程"的第一个字符'编'的索引
    index = str.IndexOf("编程");
    Console.WriteLine(index);
    //第一个字符串  表示目标字符串 
    //第二个参数表示 查找的开始位置的索引 
    //第三个参数表示 要检查的字符位置数
    index = str.IndexOf("编程",2,2);
    Console.WriteLine(index);
}
//自己实现
static int MyIndexOf(string str1,string str2)
{
    if (str1.Length<str2.Length)
    {
        return -1;
    }
    for (int i = 0; i < str1.Length-str2.Length+1; i++)
    {
        string temp = str1.Substring(i, str2.Length);
        if (temp==str2)
        {
            return i;
        }
    }

    return -1;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 字符串与ascii的转换
static void Task()
{
    string str = "abcde";
    byte[] byteArr = Encoding.ASCII.GetBytes(str);
    for (int i = 0; i < byteArr.Length; i++)
    {
        Console.Write(byteArr[i] +" ");
    }

    string retStr = Encoding.ASCII.GetString(byteArr);
    Console.WriteLine(retStr);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 字符串的格式化
static void Task()
{
  string name ="张三";
  int age = 19;
  string str = string.Format("姓名:{0},年龄:{1}",name,age);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 字符串比较
static void Task(string str1, string str2)
{
       //字符串在比较的时候相同索引的字符相互比较
       //如果字符串长度相等  所有的对应索引的字符也一样那么返回0 例如"bjd" 和 "bjd" 比较返回0
       //如果字符串长度不相等 具有相同索引值的字符比较,如果发现第一个字符串中的某个字符比第二个字符串相同索引的字符的ASCII大值返回1 否则如果小就返回-1 否则继续比较下一个 如果比较到两者中长度比较短的字符串末尾还没有分出大小  那么长度小字符串比较小 
       //由于第二个字符串是第一个字符串的子串 第一个字符串比四第二个要长  所以返回1
       Console.WriteLine(string.Compare("abcd", "abc"));
       //返回0 所有的字符都一样  及相等返回0
       Console.WriteLine(string.Compare("abcd", "abcd")); 
       //第一个字符串的第二个字符比第二个字符串的第二个字符的ASCII大所以返回1  
       Console.WriteLine(string.Compare("aec", "abcd"));
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

字符串比较的在早期博客中已经写过了,并且有程序优化过程及思路大家可以参考此博文字符串比较的逻辑

  • 去除空格
static string MyTrim(string str)
{
    str = "      张     三      ";
    //剔除字符串前缀空格和后缀空格
    str = str.Trim();
    Console.WriteLine(str);
    Console.WriteLine(str.Length);
    str = "      张     三      ";
    //剔除前缀空格
    str = str.TrimStart();
    Console.WriteLine(str.Length);
    //剔除后缀空格
    str = "      张     三      ";
    str = str.TrimEnd();
    Console.WriteLine(str.Length);
    str = "*******张  **  三*******";
    str = str.Trim('*');
    Console.WriteLine(str.Length);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

自己实现的逻辑

 static string MyTrim(string str)
{
    string retStr = string.Empty;
    int firstCh = -1;
    int lastCh = -1;
    for (int i = 0; i < str.Length; i++)
    {
        if (str[i]!=' ')
        {
            firstCh = i;

            break;
        }

    }

    for (int i = 0; i < str.Length; i++)
    {
        if (str[str.Length-1 - i] != ' ')
        {
            lastCh = str.Length - 1 - i;

            break;
        }
    }
    return str.Substring(firstCh,lastCh-firstCh+1);
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

StringBuilder学习

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StringBuilderDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            StringBuilder sb = new StringBuilder();
            //由于StringBuilder的Append参数是一个object类型的,所以可以添加很多 任意类型的数据
            //追加字符串
            sb.Append("12");
            //追加整型
            sb.Append(12);
            sb.Append(new Student());
            //以某种格式追加字符串
            sb.AppendFormat("{0}***{1}***{2}",12,13,45);
            //在下标为0的位置插入字符串"YY"
            sb.Insert(0, "YY");
            //从索引为0的位置移除2个长度的字符串
            sb.Remove(0,2);
            //将字符串"1991"替换成字符串"1998"
            sb.Replace("1991","1998");
            Console.WriteLine(sb);
            //从下标为4的位置开始找到长度为4的字符串中将字符串"19"替换成"2000"
            sb.Replace("19","2000",4,4);
            Console.WriteLine(sb);
            //sb的容量
            Console.WriteLine(sb.Capacity);


        }
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

String和StringBuilder的区别

using System;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace string和StringBuilder的性能比较
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            string ret = string.Empty;
            sw.Start();
            for (int i = 0; i < 100000; i++)
            {
                ret += i;
            }
            sw.Stop();
            Console.WriteLine("总时间是:{0}",sw.Elapsed);
        }
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

这里写图片描述 
上图为string进行100次拼接的时候耗时为:0.00064秒 
这里写图片描述 
上面的图为string进行100000次拼接时累计消耗的时间是22.57秒

using System;
using System.Collections.Generic;
using System.Collections;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace string和StringBuilder的性能比较
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            StringBuilder sb = new StringBuilder();
            sw.Start();
            for (int i = 0; i < 100000; i++)
            {
                sb.Append(i);
            }
            sw.Stop();
            Console.WriteLine("总时间是:{0}",sw.Elapsed);
        }
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

这里写图片描述 
上图为StringBuilder进行100次拼接时的耗时:0.00090秒 相对来说不如string操作的快。 
这里写图片描述 
上图为StringBuilder进行100000次拼接时的结果是0.025秒,结果是明显优于string的100000次拼接的

总结 
结果上面的图分析,我们在进行少量字符串的拼接的时候使用string来说比较优,但是我们在进行次数为万级的操作的时候我们可以所选用StringBuilder相对来说更优


DateTime结构

在项目开发中,经常会碰到日期处理。比如查询中,可能会经常遇到按时间段查询,有时会默认取出一个月的数据。当我们提交数据时,会需要记录当前日期,等等。下面就看看一些常用的方法。

首先,DateTime是一个struct。很多时候,会把它当成一个类。但它真的不是,MSDN上的描述如下:

DateTime结构:表示时间上的一刻,通常以日期和当天的时间表示。语法:

[SerializableAttribute]
public struct DateTime : IComparable, IFormattable, 
    IConvertible, ISerializable, IComparable<DateTime>, IEquatable<DateTime>

MSDN连接:MSDN DateTime结构

一、DateTime.Now属性

实例化一个DateTime对象,可以将指定的数字作为年月日得到一个DateTime对象。而DateTime.Now属性则可获得当前时间。如果你想按年、月、日分别统计数据,也可用DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day获取。同理,当前的时分秒也可以这样的方式获取。还可以在当前时间加上一个段时间等操作。

复制代码
        static void Main(string[] args)
        {
            DateTime newChina = new DateTime(1949, 10, 1);
            Console.WriteLine(newChina);
            Console.WriteLine("当前时间:");
            Console.WriteLine("{0}年,{1}月,{2}日",DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
            Console.WriteLine("{0}时,{1}分, {2}秒",DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second);
            Console.WriteLine("三天后:{0}",DateTime.Now.AddDays(3));
            Console.ReadLine();
        }
复制代码

结果:

二、ToString方法

 DateTime的ToString方法有四种重载方式。其中一个重载方式允许传入String,这就意味着你可以将当前DateTime对象转换成等效的字符串形式。比如我们将当前时间输出,日期按yyyy-mm-dd格式,时间按hh:mm:ss格式。

   Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd"));
   Console.WriteLine(DateTime.Now.ToString("hh:mm:ss"));

还有一个重载形式是需要提供IFormatProvider,使用指定的区域性特定格式信息将当前 DateTime 对象的值转换为它的等效字符串表示形式。

复制代码
  static void Main(string[] args)
        {
            CultureInfo jaJP = new CultureInfo("ja-JP");
            jaJP.DateTimeFormat.Calendar = new JapaneseCalendar();
            DateTime date1 = new DateTime(1867, 1, 1);
            DateTime date2 = new DateTime(1967, 1, 1);
            
            try
            {
                Console.WriteLine(date2.ToString(jaJP));
                Console.WriteLine(date1.ToString(jaJP));
            }
            catch (ArgumentOutOfRangeException)
            {
                Console.WriteLine("{0:d} is earlier than {1:d} or later than {2:d}",
                                  date1,
                                  jaJP.DateTimeFormat.Calendar.MinSupportedDateTime,
                                  jaJP.DateTimeFormat.Calendar.MaxSupportedDateTime);
            }
            Console.ReadLine();
        }
复制代码

结果:

没太明白,日本历史那么短?百度了一下1868年9月8日,明治维新以后了。

DateTimeFormatInfo类, 这里有比较全的时间日期格式对应的字符串。

三、DaysInMonth方法及IsLeapYear方法

 DaysInMonth方法需要两个Int32型参数,返回指定年份指定月份的天数。关于月份的天数,多数只有2月需要特殊照顾一下。剩余的月份,无论哪一年的天数都是固定的。而二月呢,不但不是其他月份的30天或31天,她还分个闰年非闰年。

复制代码
    static void Main(string[] args)
        {
            Console.WriteLine("2000年至2015年中二月的天数");
            for (int i = 2000; i < 2015; i++)
            {
                Console.WriteLine("{0}年2月有:{1}天", i, DateTime.DaysInMonth(i, 2));
            }
            Console.ReadLine();
        }
复制代码

输出结果:

从输出结果中可以看出,2月为29天的年份为闰年。但其实DateTime还提供了判断闰年的方法IsLeapYear,该方法只要一个Int32的参数,若输入的年份是闰年返回true,否则返回false。(.Net Framework就是这么贴心,你要的东西都给你封装好了,直接拿来用好了。)要是没这个方法呢,得自己去按照闰年的规则去写个小方法来判断。

复制代码
 static void Main(string[] args)
        {
            Console.WriteLine("2000年至2015年中二月的天数");
            for (int i = 2000; i < 2015; i++)
            {
                if (DateTime.IsLeapYear(i))
                    Console.WriteLine("{0}年是闰年,2月有{1}天", i, DateTime.DaysInMonth(i, 2));
                else
                    Console.WriteLine("{0}年是平年,2月有{1}天",i,DateTime.DaysInMonth(i,2));
            }
            Console.ReadLine();
        }
复制代码

微软现在已经将.NetFramework开源了,这意味着可以自己去查看源代码了。附上DateTime.cs的源码链接,以及IsLeapYear方法的源代码。虽然仅仅两三行代码,但在实际开发中,你可能一时间想不起闰年的计算公式,或者拿捏不准。封装好的方法为你节省大量时间。

DateTime.cs源码中IsLeapYear方法

复制代码
      // Checks whether a given year is a leap year. This method returns true if
        // year is a leap year, or false if not.
        //
        public static bool IsLeapYear(int year) {
            if (year < 1 || year > 9999) {
                throw new ArgumentOutOfRangeException("year", Environment.GetResourceString("ArgumentOutOfRange_Year"));
            }
            Contract.EndContractBlock();
            return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
        }
复制代码

 总结

介绍了几个算是比较常用的方法。在自己的项目中遇到日期操作的时候,多看看.NetFramework给我们提供了什么样的方法。很多时候用所提供的方法拼凑一下,就能轻易的获取到我们想要的日期或者时间。



Math类

Abs 返回指定数字的绝对值。

Acos 返回余弦值为指定数字的角度。

Asin 返回正弦值为指定数字的角度。

Atan 返回正切值为指定数字的角度。

Atan2 返回正切值为两个指定数字的商的角度。

BigMul 生成两个 32 位数字的完整乘积。

Ceiling 返回大于或等于指定数字的最小整数。

Cos 返回指定角度的余弦值。

Cosh 返回指定角度的双曲余弦值。

DivRem 计算两个数字的商,并在输出参数中返回余数。

Exp 返回 e 的指定次幂。

Floor 返回小于或等于指定数字的最大整数。

IEEERemainder 返回一指定数字被另一指定数字相除的余数。

Log 返回指定数字的对数。

Log10 返回指定数字以 10 为底的对数。

Max 返回两个指定数字中较大的一个。

Min 返回两个数字中较小的一个。

Pow 返回指定数字的指定次幂。

Round 将值舍入到最接近的整数或指定的小数位数。

Sign 返回表示数字符号的值。

Sin 返回指定角度的正弦值。

Sinh 返回指定角度的双曲正弦值。

Sqrt 返回指定数字的平方根。

Tan 返回指定角度的正切值。

Tanh 返回指定角度的双曲正切值。

Truncate 计算一个数字的整数部分。

E 表示自然对数的底,它由常数 e 指定。

PI 表示圆的周长与其直径的比值,它通过常数 n 指定。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值