零基础自学C#——Part2:C#中的运算符、语句、类型转换、数据结构

前面学习了C#和.NET渊源、U3D中创建C#脚本,介绍了C#中的变量,下面继续进行C#的学习。

一、运算符

运算符可将简单的操作(加法乘法等)应用于操作数,他们通常返回一个新值,作为分配给变量的操作结果。

大多数运算符是二元的,也就是说,可以同时操作两个操作数,而有些运算符是一元的,只能作用于一个操作数,并且可以在操作数前后应用。除此之外还有三元运算符。

1:一元运算符

有两个常用运算符,分别是++(递增)和- -(递减),他们还有位置的区别

int a=3;
int b=a++;

此时输出结果a为4,b为3

++在变量之后,则运算符在赋值后执行,称为后缀运算符。

int a=3;
int b=++a;

此时输出结果为a=4,b=4

++在变量之前,则运算符在赋值前执行,称为前缀运算符。

2:二元运算符

+,-,*,/运算符

%:取模运算符,B%A后,取得的小数部分,比如A=10,B=20,则B%A=0;

3:赋值运算符

赋值运算符

=     简单赋值运算符,将右边的数赋值给左边

+=,加且赋值运算符,将右边的数加上左边的数,然后赋值给左边

-=,*=,/=,%=,同理如上。

<<=:左移且赋值运算符(乘以2的多少次),>>=:右移且赋值运算符(除以2的多少次方);

4:关系运算符

==:检查两个操作数的值是否相等,如果相等则条件为真。

!=:检查两个操作数的值是否相等,如果不相等则为真。

<、>、<=、>=,同理

5:逻辑运算符

&&:与门,同时满足才为真。

||:或门,有一个真即为真。

!:非门,真→假;加→真。

6:位运算符(在二进制层面对数字进行逻辑运算)

&:与运算符

|:或运算符

^:异或运算符

~:取反运算符

int a=10;
int b=6;
Debug.Log(a&b);
Debug.Log(a|b);
Debug.Log(a^b);

10的二进制数为0001 0010

6的二进制 为0000 0110;

进行&操作时:将对应位置的0和1做&逻辑,即相同为该数,不同为0

          对应数:0000 0010    转化为数字2

进行|操作时:将对应位置0和1做|逻辑,即有一个1为1,两个均为0为0

          对应数:0001 0110    转化为数字14

进行^操作时:将对应位置0和1做^逻辑,上下两行不一样,返回1,如果相同则返回0.

         对应数:0001 0100   转化为数字12

7:三目运算符(条件运算符,它是唯一有3个操作数的运算符,所以有时又称为三元运算符)

如果a>b则返回a,否则返回b

a>b ? a : b

 int a,b,c;
 a=7;
 b=6;
 c=(a>b)?a:b;

则返回c=7

二、选择语句

每个应用程序都需要从选项中进行选择,而C#中的两个选择语句是if和switch

1:if语句

if语句通过计算布尔表达式来确定要执行哪个分支,如果为true,则执行If语句块,否则执行else语句块,if语句可以嵌套。

if (expression1)
{}
else if(expression2)
{}
else if(expression3)
{}
else
{}

2:switch语句

switch (value)
        case 1:
            Debug.Log("1.起床");
          break;
        case 2:
            Debug.Log("2.洗漱");
          break;  
        case 3:
            Debug.Log("3.吃饭");
          break;
        default:
            Debug.Log("不知道要做什么");
         break;

在switch括号中输入变量,case则可对每个变量的值进行分类讨论。

三、迭代语句

当条件为真时,迭代语句会重复执行语句块,或为每个集合中的每项重复执行语句块。

1:while循环

while循环语句会对布尔表达式求值,并在布尔表达式为true时继续循环。

int a= 0;
while (a<10)
{
   Debug.Log(a);
   a++; 
}

则输出的值为0,1,2,3,4,5,6,7,8,9.

2:do循环语句

do循环语句与while语句类似,只不过布尔表达式是在语句块的底部,而不是顶部进行检查,这意味着语句块总是至少执行一次。

do
{
  Write("Enter Your Password");
  Passwprd=ReadLine();
}
while("Password != Pa$$word");
WriteLine("Correct!");

此代码下,无论如何,do内代码都会被首先执行一次,再判断while语句的正确性,直到输入正确的password。

3:for循环语句

for循环语句通常与计数器一起使用;

for(int a=1; a<=10; a++)
{
  WriteLine(a);
}

 

for (int i = 0; i <= 100; i++)
      if(i==50)
        continue;
       Debug.Log(i);,//则输出结果中没有50;

Continue 跳过     需求:如果值=50,跳过,但是循环体继续执行

Break   打断      需求:如果值=51,终止循环语句

4:foreach语句(C# 独有的遍历方式)

foreach语句用于对序列(数组或集合)中的每一项执行语句块,序列中的每一项通常是只读的,因此foreach循环也叫做只读循环,如果在循环期间修改序列结构,如添加或删除项,会报错。

foreach(数据类型 变量 in 数组或集合

{

       循环体

}

string[] names={"a","ab","abc"};

foreach (string name in names)
{
  WriteLine("{name} has {name.Length} characters.")
}

四、数据结构

链表和数组作为算法中的两个基本数据结构,在程序设计过程中经常用到。尽管两种结构都可以用来存储一系列的数据,但又各有各的特点。

链表  list  数组

链表的查找效率比较低,只能用first,next,previous等指令查找,不可以直接定位

list和数组是顺序存储,链表的存储是离散的,在删除插入时的效率比较高

1:静态数组:

数组是有序相同的数据类型元素组成的有限集合,内存是线性连续的。

一维数组:当数组中的每个元素都只带一个下标时

二维数组:当数组中每个元素都带两个下标时

....

N维数组:当数组中的每个元素带有N个下标时

①:一维数组

数组必须先定义,后使用。且只能逐个引用数组元素,不能一次引用整个数组。

初始化的几种方式  

第①种

int[]array3=new int[4];    //声明为int类型的数组,名称为array3,初始化容量为5
array[0]=10;
array[1]=20;
array[2]=30;
array[3]=40;

第②种

int[]array2=new int[4]{10,20,30,40};

第③种

int[]array1={10,20,30,40};

②:二维数组

初始化的几种方式:

第①种

int[,]array5=new int[2,2];
array5[0,0]=0;
array5[0,1]=1;
array5[1,0]=2;
array5[1,1]=3;
Debug.Log("第一行第二列的元素"+array5[0,1]);

第②种

int[,]array8=new int[2,2];
{
  {10,20},

  {30,40},
};

第③种:调用指令

Debug.Log("代码的长度(容量)"+array8.Length);
Debug.Log("代码的行数"+array8.Get.Length(0));
Debug.Log("代码的列数"+array8.Get.Length(1));

③:三维数组使用+存储和读取数据;

三维数组可以理解为层+行+列。

int[,,]array10=new int[3,3,3];  //x,y,z

       array10[0,0,0]=1;

       array10[0,1,0]=2;

       array10[0,2,0]=3;

       array10[1,0,0]=4;

       array10[1,1,0]=5;

       array10[1,2,0]=6;

       array10[2,0,0]=7;

       array10[2,1,0]=8;

       array10[2,2,0]=9;

       array10[0,0,1]=11;

       array10[0,1,1]=21;

       array10[0,2,1]=31;

       array10[1,0,1]=41;

       array10[1,1,1]=51;

       array10[1,2,1]=61;

       array10[2,0,1]=71;

       array10[2,1,1]=81;

       array10[2,2,1]=91;

       array10[0,0,2]=310;

       array10[0,1,2]=320;

       array10[0,2,2]=330;

       array10[1,0,2]=340;

       array10[1,1,2]=350;

       array10[1,2,2]=360;

       array10[2,0,2]=370;

       array10[2,1,2]=380;

       array10[2,2,2]=390;

       Debug.Log("访问第二层第一行第二列的元素(1,2,1):"+array10[1,2,1]);

       Debug.Log("获取array10的数组长度(容量)"+array10.Length);

       array10[2,2,1]=910;//修改数据

       Debug.Log("访问第二层第二行第二列的元素(2,2,1):"+array10[2,2,1]);

五、动态数组ArrayList和泛型类List

2:动态数组

最初我们使用的都是静态数组,但是,静态数组有着自己难以改变的缺点——数组长度固定。

一般在静态数组定义后,系统就会为其分配对应长度的连续的专有内存空间,可是,我们都知道,

不同的运行样例,所需要的数组长度是不一样的,为了所有样例都可以执行,一般我们会将数组长

度设置为一个很大的值,但是这种方式,满足了一般运行的要求,但是它极大的浪费了内存。

因此我们引入动态数组的概念:

动态数组为对象的有序集合

动态数组会自动调整它的大小

可以使用索引在指定位置添加和移除项目,它也允许在列表中进行动态内存分配。

①第一种构建和打印动态数组的方法

初始化+Add

public class addition : MonoBehaviour
{
    ArrayList arrayList1=new ArrayList();      //构建动态数组的第一种方法,对数组进行实例化
    void Start()
    {
        arrayList1.Add(45);                     //通过add给构建的数组添加元素
        arrayList1.Add(25);
        arrayList1.Add(12);
        Debug.Log(arrayList1[0]);                //打印出动态数组的第一,二,三的值
        Debug.Log(arrayList1[1]);
        Debug.Log(arrayList1[2]);
    }

②第二种添加动态数组的方法

AddRange

public class ArrayList1: MonoBehaviour
{
  ArrayList arrayList1=new ArrayList();      //构建动态数组的第一种方法,对数组进行实例化 
  int [] array1 = new int[4] {1,2,3,4};
}

void Start()
{
        arrayList1.Add(45);                     //通过add给构建的数组添加元素
        arrayList1.Add(25);
        arrayList1.Add(12);
        arrayList1.AddRange(array1);            
  //AddRange:向已有数组的末尾添加数组,它可以让我们要加入的东西一次性加入,而不要每次都加一次
        foreach(var v in arrayList1)  //此处使用了var,在不确定数据类型的前提下,可以进行使用
        {
            Debug.Log(v);
        }
}

③:动态数组的常用指令

清空指令:

arrayList1.Clear(); 

包含指令:

if (arrayList1.Contains(12));   //使用contains,返回bool类型,判断是否数组中含有12,
        {
           Debug.Log("包含元素"+12);
        }

判断元素位置指令:

arrayList1.IndexOf(12);   
//indexof是用来判断元素在数组中的位置,如上数组,则返回3,如果不包含,则返回为-1;

原始赋值指令:

arrayList1[0]=1;    //一号位赋值1

插值指令:

arrayList1.Insert(3,66);   
//insert方法是在数组的指定位置之后插入某个元素,比如此时是在第三个位置之后插入66

移除指令:

arrayList1.Remove(12);    //对元素12进行删除,如果有多个12,则删除第一个

逆转排序指令:元素倒序排序

arrayList1.Reverse();   //逆转元素,把原数组的顺序从后向前了

大小排序指令:

 arrayList1.Sort();      //将数组的元素从小到大进行排列

3:泛型类List

作用与功能近似arraylist

无需装箱拆箱,类型转换

类型安全

自行开发时候使用List更多

public class List : MonoBehaviour

{
    List list1=new List();       //List1的声明和初始化
    void Start()
    {
        list1.Add(1);
        list1.Add(2);
        list1.Add(3);
        list1.Count;   //此指令来测List的长度
        list1.Contains/remove/....ArrayList中的方法List基本都能用;
        
}

4:链表

数组的优势,在于可以方便的遍历查找需要的数据。在查询数组指定位置(如查询数组中的第4个数据)的操作中,只需要进行1次操作即可。但是,这种时间上的便利性,是因为数组在内存中占用了连续的空间,在进行类似的查找或者遍历时会变得很复杂。

链表的特性使其在某些操作上比数组更加高效。例如当进行插入和删除操作时,链表操作的时间复杂度仅为O(1)。另外,因为链表在内存中不是连续存储的,所以可以充分利用内存中的碎片空间。除此之外,链表还是很多算法的基础,最常见的哈希表就是基于链表来实现的。

链表基础知识总结_zql_3393089的博客-CSDN博客_链表

public class 链表 : MonoBehaviour
{
    LinkedList linList=new LinkedList();   //双向链表的定义和实例化
    LinkedListNodenode;

    void Start()
    {
        node = linList.AddFirst(1);
        linList.AddAfter(node,2);      //在node后面添加一个值
        linList.AddBefore(node,0);     //在node前面添加一个值

        Debug.Log(linList.Count);       //打印出链表的元素数量

        Debug.Log(linList.First.Value);  //打印出第一个值(value)

        Debug.Log(linList.Last.Value);  //打印出最后一个值

        if(node.Previous !=null)          //node之前的值
        {
            Debug.Log(node.Previous.Value);
        }
        if(node.Previous !=null)           //node之后的值
        {
            Debug.Log(node.Next.Value);
        }

 

六、类型转换

我们常常需要在不同类型之间转换变量的值,例如数据通常在控制台以文本形式输出,最初他们是以字符串类型的变量,但是随后需要将他们转化为日期/事件、数字或其他类型的数据。又比如有时需要在整数和浮点数之间进行转换等。

转换也称为强制类型转换,分为隐式和显式两种,隐式是自动进行的,并且安全,显式必须要手动执行,可能会丢失信息,比如精度等。

1:隐式和显式地转换数值

①将int变量隐式转换为double变量是安全的,不会丢失任何信息,但是不能隐式的将double变量转为int变量,这是不安全的。

//隐式将int转为double
int a=10;
double b=a;

//不能隐式将double转为int,此处会丢失精度
double c=9.8;
int d=c;

②使用System.Convert类型进行转换

double a=9.8;
int b=ToInt32(a);
//此处输出的b是10

系统默认的圆整规则是当>=0.5,向上取整;如果<0.5则向下取整,当然也可以使用Round方法进行控制圆整规则。

③:从任何类型转换为字符串

这是最常见的转换,因此所有类型都提供转换为ToString的方法

int a=10;
Debug.Log(a.ToString());

int boolean=true;
Debug.Log(boolean.ToString());

DateTime now=DateTime.Now;
Debug.Log(now.ToString());

object me=new object();
Debug.Log(me.ToString());

④:将字符串转换为数值或日期事件

这是另一种常用的转换,作用与ToString相反,它叫Parse,只有少数类型有Parse方法,它包含所有的数值类型和DateTime。

Int num01 =int.Parse(strNumber);
DateTime birthday =DateTime.Parse(strNumber)
Float num02= float.Parse(strNumber);

你可能感兴趣的:(c#,开发语言)