上节介绍了数组的基本知识,本节继续介绍使用数组的相关方法。本节内容包括数组元素的访问、数组的遍历、排序、同步以及复制等常见操作。
Array类提供了数组的创建、搜索、排序和查找等功能。一般情况下,开发人员不需要使用Array类创建数组,直接使用上节中介绍的方法即可。但Array类也提供了创建数组的方法。下面通过一个实例介绍这种方法的使用。
创建一个Windows控制台应用程序,使用Array类创建数组。
(1)创建一个名为ArrayCreate的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
//创建数组
Array a = Array.CreateInstance(typeof(int), 5);
a.SetValue(1, 0);
a.SetValue(2, 1);
a.SetValue(3, 2);
a.SetValue(4, 3);
a.SetValue(5, 4);
//显示数组内容
Console.WriteLine(a.GetValue(0));
Console.WriteLine(a.GetValue(1));
Console.WriteLine(a.GetValue(2));
Console.WriteLine(a.GetValue(3));
Console.WriteLine(a.GetValue(4));
}
按Ctrl+F5组合键运行程序,运行结果如图4-7所示。
图4-7 运行结果
从运行结果可以看到,采用Array类创建数组比较烦琐。首先要使用CreateInstance方法创建数组,然后使用SetValue方法对数组中的元素进行赋值。当需要访问数组中元素时,则必须使用GetValue方法。
访问数组的元素比较简单,只需知道数组元素的下标即可。普通数组元素的访问方法前面已经介绍过,此处不再赘述。本小节采用一个实例介绍多维数组的访问方法。
创建一个Windows控制台应用程序,创建并访问一个多维数组。
(1)创建一个名为AccessArray的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
//声明一个多维数组
int[,] a = new int[,]
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
//输出其值
Console.WriteLine(a[0,0]);
Console.WriteLine(a[0,1]);
Console.WriteLine(a[0,2]);
Console.WriteLine(a[1,0]);
Console.WriteLine(a[1,1]);
Console.WriteLine(a[1,2]);
Console.WriteLine(a[2,0]);
Console.WriteLine(a[2,1]);
Console.WriteLine(a[2,2]);
}
按Ctrl+F5组合键运行程序,运行结果如图4-8所示。
代码中创建的是一个二维数组,大小为3×3。通过下标[0,0]到[2,2]即可访问数组中的全部元素。
图4-8 运行结果
在前文的实例中,已经对数组进行了若干次的访问,可以发现,访问时,写出数组每一个元素的下标效率较低。本小节介绍一种更简便的方式,用于遍历数组中的所有元素。
下面通过实例说明遍历数组的方法。
创建一个Windows控制台应用程序,创建并访问一个多维数组。
(1)创建一个名为AccessAll1的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
//声明一个多维数组
int[,] a = new int[,]
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
//使用两层for循环遍历访问数组中的所有元素
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Console.WriteLine(a[i, j]);
}
}
}
按Ctrl+F5组合键运行程序,运行结果如图4-9所示。
图4-9 运行结果
代码中第一层for循环表示的是数组的第一维,第二层for循环表示的是数组的第二维。通过两次for循环即可遍历数组中所有的元素,这时输出语句Console.WriteLine只需一句即可。
下面通过while循环访问数组中的元素。
创建一个Windows控制台应用程序,创建并访问一个多维数组。
(1)创建一个名为AccessAll2的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
//声明一个多维数组
int[,] a = new int[,]
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
//使用两层while循环遍历访问数组中的所有元素
int i = 0;
int j = 0;
while (i < 3)
{
while (j < 3)
{
//输出
Console.WriteLine(a[i,j]);
//j递增
j++;
}
//i递增
i++;
//j清零
j = 0;
}
}
按Ctrl+F5组合键运行程序,运行结果如图4-10所示。
图4-10 运行结果
可以看到,while循环的本质和for循环基本相同。但由于其控制遍历i和j需要开发人员自行控制,显得略微有些不便。因此while循环与for循环相比,使用for循环比较合理。
下面介绍另外一种遍历数组的方法,即foreach语句。foreach语句用于循环访问数组或集合以获取所需信息。本节只介绍如何使用foreach语句访问数组,如下的实例所示。
创建一个Windows控制台应用程序,创建并访问一个多维数组。
(1)创建一个名为AccessAll3的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
//声明一个多维数组
int[,] a = new int[,]
{
{ 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 }
};
//使用foreach遍历访问数组中的所有元素
foreach (int i in a)
{
//输出
Console.WriteLine(i);
}
}
按Ctrl+F5组合键运行程序,运行结果如图4-11所示。
图4-11 运行结果
可以看到foreach语句的代码量最少,这里只介绍一点,即foreach语句中的in关键字。foreach语句一般后接一个括号,括号中的内容以in关键字为界分为两部分。后半部分是数组或集合,前半部分则声明一个与该数组元素类型相同的遍历。
上述实例中的foreach语句部分可以用一句话来理解,即“对于数组a中的每一个整型元素i,都将其输出至控制台”。
数组的排序是一个经典的问题,但C#为开发人员提供了直接的排序方法。本小节首先回顾传统的数组排序方法,然后介绍C#中提供的排序方法。
传统的排序方法中有一种称为冒泡法排序,冒泡算法的思想是从数组中索引号为0的元素开始依次比较相邻的元素,使其小的元素在前,大的元素在后。对于个数为n的数组,只需n-1次操作即可使最大的元素位于数组的最后位置;然后重复操作,同样需n-2次比较可以使次大的元素位于数组倒数第二的位置;依次类推,可以实现数组的排序。
下面通过一个实例说明。
创建一个Windows控制台应用程序,对数组中的元素进行排序。
(1)创建一个名为ClassicSort的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
int[] myArray = new int[5] { 23, 5, 62, 12, 7 };
int a = 0;
Console.WriteLine("排序前:");
//创建一个循环语句,从0开始,每次加1,并输出数组的相应元素,跳出条件为大于等于5
for (int i = 0; i < 5; i++)
{
Console.WriteLine("myArray[{0}]的值为{1}。", i, myArray[i]);
}
//采用冒泡法对数组进行排序
for (int i = 1; i < 5; i++)
{
for (int j = 0; j < 5 - i; j++)
{
if (myArray[j] > myArray[j + 1])
{
a = myArray[j];
myArray[j] = myArray[j + 1];
myArray[j + 1] = a;
}
}
}
Console.WriteLine("排序后:");
//创建一个循环语句,从0开始,每次加1,并输出数组的相应元素,跳出条件为大于等于5
for (int i = 0; i < 5; i++)
{
Console.WriteLine("myArray[{0}]的值为{1}。", i, myArray[i]);
}
}
按Ctrl+F5组合键运行程序,运行结果如图4-12所示。
图4-12 运行结果
可以看到,排序后,数组的元素按由大到小的顺序排列。本例关于算法的代码中存在两个for循环。内层for循环的作用是比较相邻两个整数的大小,并根据需要决定是否交换两个整数的位置。
外层的for循环确定了比较的范围。由于第一次循环可以确定数组中最大的整数,进入下一次循环时,则可以只比较其他的整数,而无需全部比较。依此类推,需要比较的元素逐次减少。直到最后跳出循环,则说明算法结束。
其他的排序方法还有插入法排序,快速排序等。
C#中提供了一个便捷的数组排序方法,即Array.Sort。使用此方法时,开发人员无需编写排序方法的代码,只需简单调用即可。下面通过一个实例介绍此种方法的使用。
创建一个Windows控制台应用程序,对数组中的元素进行排序。
(1)创建一个名为ArraySort的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
int[] a = new int[5] { 23, 5, 62, 12, 7 };
Console.WriteLine("排序前:");
//创建一个循环语句,从0开始,每次加1,并输出数组的相应元素,跳出条件为大于等于5
for (int i = 0; i < 5; i++)
{
Console.WriteLine("a[{0}]的值为{1}。", i, a[i]);
}
Array.Sort(a);
Console.WriteLine("排序后:");
//创建一个循环语句,从0开始,每次加1,并输出数组的相应元素,跳出条件为大于等于5
for (int i = 0; i < 5; i++)
{
Console.WriteLine("a[{0}]的值为{1}。", i, a[i]);
}
}
按Ctrl+F5组合键运行程序,运行结果如图4-13所示。
图4-13 运行结果
可以看到,程序运行的结果仍然是相同的,即数组中的元素按照从大到小的方式被重新排列。在本实例中,进行排序的代码只有一行,即Array.Sort(a)。
使用数组时,有时需要快速地知道数组中是否含有某个元素,并且获得该元素的位置,这时就需要对数组中的元素进行查找。如果C#本身不提供此类方法,则需实现自己的查找算法。C#所提供的查找数组元素的方法分别为IndexOf和LastIndexOf。下面,分别通过实例演示这两个方法的使用。
创建一个Windows控制台应用程序,对数组中的元素进行查找。
(1)创建一个名为ArraySearch1的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
int[] a = { 1, 2, 3, 4 ,5 ,4, 3, 2, 1 };
for (int i = 0; i < 9; i++)
{
Console.WriteLine("位置{0}:{1}", i, a[i]);
}
int b = Array.IndexOf(a, 5);
Console.WriteLine("5的位置为:{0}", b);
int c = Array.IndexOf(a, 3);
Console.WriteLine("3的位置为:{0}", c);
}
按Ctrl+F5组合键运行程序,运行结果如图4-14所示。
数值5在数组a中只有一个,其位置为4,而数值3在数组a中有两个,分别位于下标为2和6的位置。Array.IndexOf的作用就是找到在数组中首次出现的元素,因此查找数值3时返回的位置为2。
图4-14 运行结果
在数组中查找元素最后一次出现的位置时用Array.LastIndexOf方法,其具体使用方法见下面的实例。
创建一个Windows控制台应用程序,对数组中的元素进行查找。
(1)创建一个名为ArraySearch2的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
int[] a = { 1, 2, 3, 4 ,5 ,4, 3, 2, 1 };
for (int i = 0; i < 9; i++)
{
Console.WriteLine("位置{0}:{1}", i, a[i]);
}
int b = Array.LastIndexOf(a, 5);
Console.WriteLine("5的位置为:{0}", b);
int c = Array. LastIndexOf (a, 3);
Console.WriteLine("3的位置为:{0}", c);
}
按Ctrl+F5组合键运行程序,运行结果如图4-15所示。
图4-15 运行结果
数值5在数组a中只有一个,其位置为4。而数值3在数组a中有两个,分别位于下标为2和6的位置。Array.LastIndexOf的作用就是找到在数组中元素最后一次出现的位置,因此查找数值3时返回的位置为6。
数组的常见操作中有一类操作称为逆序,即将数组中元素排列的顺序逆转。最容易想的方法是将数组中的元素首尾倒置,然后次首元素和次尾元素倒置,一直进行下去。如果数组的长度为偶数,则可一直运行至所有元素都交换了位置。如果数组长度为奇数,则最后一个元素无需交换位置。
C#为了简化操作,提供了Array.Reverse方法,该方法可以直接实现逆序功能。下面介绍一个实例,以演示其用法。
创建一个Windows控制台应用程序,对数组中的元素进行逆序操作。
(1)创建一个名为ArrayReverse的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
int[] a = new int[9] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine("原数组:");
foreach (int i in a)
{
Console.Write(i);
Console.Write(" ");
}
Console.WriteLine("\n");
//对数组种所有的元素进行逆序操作
Array.Reverse(a);
Console.WriteLine("结果数组:");
foreach (int i in a)
{
Console.Write(i);
Console.Write(" ");
}
Console.WriteLine("\n");
}
按Ctrl+F5组合键运行程序,运行结果如图4-16所示。
图4-16 运行结果
可以看到,数组中元素的排列顺序由1~9变为9~1。
复制数组是一类常见的操作,即将一个数组中的内容复制到另一个数组中。如果C#中不提供此类操作,那么最简单的方法是采用循环将数组1中的元素赋值到数组2中相应的元素中。C#考虑了此类操作的常见性,提供了Array.Copy方法。下面介绍的实例演示了Array.Copy方法的使用。
创建一个Windows控制台应用程序,对数组进行复制。
(1)创建一个名为ArrayCopy的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
int[] a = new int[9] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Console.WriteLine("原数组:");
foreach (int i in a)
{
Console.Write(i);
Console.Write(" ");
}
Console.WriteLine("\n");
int[] b = new int[a.Length];
Array.Copy(a, b, a.Length);
Console.WriteLine("结果数组:");
foreach (int i in b)
{
Console.Write(i);
Console.Write(" ");
}
Console.WriteLine("\n");
}
按Ctrl+F5组合键运行程序,运行结果如图4-17所示。
图4-17 运行结果
可以看到,复制的数组中元素与原数组完全相同。
前面介绍的数组大多是在声明时同时初始化,但在有些时候需要动态地创建数组,即在编写代码时并不知道数组的长度和元素的内容。这时,一般是根据程序中某个变量动态地生成数组,下面介绍的实例就采用了这种方法。
创建一个Windows控制台应用程序,根据用户的输入创建数组。
(1)创建一个名为DynamicArray的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
Console.WriteLine("请输入一个整数:");
int a = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("请再输入一个整数:");
int b = Convert.ToInt32(Console.ReadLine());
//求和
int c = a + b;
//创建数组
int[] d = new int[c];
for (int i = 0; i < c; i++)
{
d[i] = c * i;
}
//输出元素值
Console.WriteLine("数组为:");
foreach (int j in d)
{
Console.WriteLine(j);
}
}
按Ctrl+F5组合键运行程序,运行结果如图4-18所示。
运行程序时,输入了3和4,因此创建了一个长度为7的数组。可见,如果输入其他的值,程序每次创建的数组可能不同。
图4-18 运行结果
C#中提供了一种清除数组元素的方法,这里的“清除”是指将数组中的元素变为默认值。如果数组是一个整型数组,那么清除后数组的元素值为0。C#中清除数组元素的方法为Array.Clear。下面通过一个实例介绍清除数组元素的方法。
创建一个Windows控制台应用程序,清除数组中的元素。
(1)创建一个名为ArrayClear的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
int[] a = new int[5] { 1, 2, 3, 4, 5 };
Console.WriteLine("原数组:");
foreach (int j in a)
{
Console.WriteLine(j);
}
Array.Clear(a, 0, 5);
Console.WriteLine("结果数组:");
foreach (int j in a)
{
Console.WriteLine(j);
}
}
按Ctrl+F5组合键运行程序,运行结果如图4-19所示。
图4-19 运行结果
使用Array.Clear方法时,一共使用了3个参数。其中第一个参数为要清除的数组,第二个参数为清除开始的位置,第三个参数为清除元素的个数。对于本实例,则是将数组中所有的元素都清除,因此结构中元素的个数都是0。
下面介绍一个实例,使用数组计算学习成绩的平均值。
创建一个Windows控制台应用程序,使用数组存储每个学生的成绩,计算成绩的平均分。
(1)创建一个名为ArrayExample的控制台应用程序项目。
(2)修改Program.cs文件中Main方法的内容如下:
static void Main(string[] args)
{
//定义程序中用到的变量,用数组a存储分数,另外两个双精度变量存储总分和平均分
double[] a = new double[10] { 82, 76, 88, 93, 68, 74, 55, 94, 75, 83 };
double b = 0.0;
double c = 0.0;
foreach (double i in a)
{
//输出数组中的原始成绩
Console.WriteLine("原始分数:{0}", i);
//累加分数
b += i;
}
//求平均值
c = b / 10;
Console.WriteLine("平均成绩为:{0}", c);
}
按Ctrl+F5组合键运行程序,运行结果如图4-20所示。
图4-20 运行结果
程序中对每一项成绩进行累加,最后对总成绩进行平均,即除以学生的总数,即得到成绩的平均值。