4.6.2 CLR数组(4)
我们将names和weights数组排序,用names数组来决定最终的顺序。然后,在for each循环中针对toBeFound数组中的每个姓名搜索names数组。我们依次将toBeFound数组中的每一个姓名赋给循环变量name。在该循环中,用下面这条语句查找当前的姓名:
- result = Array::BinarySearch(names, name); // Search names array
该语句返回names数组中包含name的那个元素的索引值,或者未找到name时返回一个负整数。然后,我们在if语句中测试结果并产生输出:
- if(result<0) // Check the result
- Console::WriteLine(L"{0} was not found.", name);
- else
- Console::WriteLine(L"{0} weighs {1} lbs.", name, weights[result]);
因为weights数组的顺序取决于names数组的顺序,所以我们可以用names数组中包含name的那个元素的索引值-- 即result来索引weights数组。从输出中可以看出,在names数组中没有找到"Fred"。
当对分搜索操作失败时,函数返回的数值决不是任意的负数。事实上,该整数是第一个大于搜索目标的元素索引值的按位补码,如果没有大于搜索目标的元素,该整数则是Length属性的按位补码。知道了这一点,我们就可以使用BinarySearch()函数求出为了仍然保持元素的正确顺序应该将新对象插入到数组的什么位置。假设我们希望在names数组中插入"Fred"。使用下面这些语句,可以找出应该插入"Fred"的索引位置:
- array<String^>^ names = {"Jill", "Ted", "Mary", "Eve", "Bill",
- "Al", "Ned", "Zoe", "Dan", "Jean"};
- Array::Sort(names); // Sort the array
- String^ name = L"Fred";
- int position = Array::BinarySearch(names, name);
- if(position<0) // If it is negative
- position = ~position; // flip the bits to get the insert index
如果搜索结果为负数,则将所有位反转就是应该插入新姓名的索引位置。如果结果是正数,则说明新姓名与该位置的姓名相同,因此我们可以直接将结果用作新位置。
现在,我们可以将names数组复制到比它多一个元素的新数组中,并使用position的值在适当的位置插入name:
- array<String^>^ newNames = gcnew array<String^>(names->Length+1);
-
- // Copy elements from names to newNames
- for(int i = 0 ; i<position ; i++)
- newNames[i] = names[i];
-
- newNames[position] = name; // Copy the new element
-
- if(position<names->Length) // If any elements remain in names
- for(int i = position ; i<names->Length ; i++)
- newNames[i+1] = names[i]; // copy them to newNames
这段代码首先创建一个比旧数组多一个元素的新数组,然后将旧数组中的元素逐一复制到新数组中,一直复制到索引位置position-1。此刻先复制新姓名,接着再复制旧数组中剩余的元素。为了抛弃旧数组,我们只需写这样一条语句:
- names = nullptr;
3. 多维数组
我们可以创建二维或多维数组,数组的最大维数是32,应该能够适应大多数情况。我们在尖括号内元素类型后面指定数组的维数,中间用逗号分开。数组的维数默认是1,因此我们在之前的示例中不需要指定维数。下面是创建二维整型数组的方法:
- array<int, 2>^ values = gcnew array<int, 2>(4, 5);
这条语句创建一个四行五列的二维数组,因此总共是20个元素。为访问多维数组的元素,我们需要指定多个索引值-- 每一维一个,这些索引值必须写在数组名后面的方括号内,中间以逗号分开。下面是给一个整型二维数组的元素赋值的方法:
- int nrows = 4;
- int ncols = 5;
- array<int, 2>^ values = gcnew array<int, 2>(nrows, ncols);
- for(int i = 0 ; i<nrows ; i++)
- for(int j = 0 ; j<ncols ; j++)
- values[i,j] = (i+1)*(j+1);
嵌套的循环逐一处理该数组的所有元素。外部循环处理每一行,内部循环处理当前行的每一个元素。我们看到,该代码段将表达式(i+1)*(j+1)的值赋给各个元素。因此,第一行元素将是1,2,3,4,5;第二行元素将是2,4,6,8,10;依此类推,最后一行元素将是4,8,12,16,20。
读者肯定已经注意到,这里访问二维数组元素的符号不同于为本地C++(www.cppentry.com)数组使用的符号。C++(www.cppentry.com)/CLI数组不像本地C++(www.cppentry.com)数组那样,是数组的数组,而是真正的二维数组。我们不能对二维C++(www.cppentry.com)/CLI数组使用一个索引值,因为这种数组是元素的二维数组,而非数组的数组。前面曾经讲过,数组的维数被称为等级,因此上面代码段中values数组的等级是2。当然,我们还可以定义等级为3或更大(一直到32)的C++(www.cppentry.com)/CLI数组。相反,本地C++(www.cppentry.com)数组的等级实际上始终是1,因为二维或多维的本地C++(www.cppentry.com)数组事实上是数组的数组。稍后我们将看到,在C++(www.cppentry.com)/CLI中也可以定义数组的数组。
下面的示例中介绍了如何使用多维数组。
试一试:使用多维数组
该CLR控制台示例在二维数组中创建12×12的乘法表。
- // Ex4_16.cpp : main project file.
- // Using a two-dimensional array
-
- #include "stdafx.h"
-
- using namespace System;
-
- int main(array<System::String ^> ^args)
- {
- const int SIZE = 12;
- array<int, 2>^ products = gcnew array<int, 2>(SIZE,SIZE);
-
- for (int i = 0 ; i < SIZE ; i++)
- for(int j = 0 ; j < SIZE ; j++)
- products[i,j] = (i+1)*(j+1);
-
- Console::WriteLine(L"Here is the {0} times table:", SIZE);
-
- // Write horizontal divider line
- for(int i = 0 ; i <= SIZE ; i++)
- Console::Write(L"_____");
- Console::WriteLine(); // Write newline
-
- // Write top line of table
- Console::Write(L" |");
- for(int i = 1 ; i <= SIZE ; i++)
- Console::Write(L"{0,3} |", i);
- Console::WriteLine(); // Write newline
-
- // Write horizontal divider line with verticals
- for(int i = 0 ; i <= SIZE ; i++)
- Console::Write(L"____|");
- Console::WriteLine(); // Write newline
-
- // Write remaining lines
- for(int i = 0 ; i<SIZE ; i++)
- {
- Console::Write(L"{0,3} |", i+1);
- for(int j = 0 ; j<SIZE ; j++)
- Console::Write(L"{0,3} |", products[i,j]);
-
- Console::WriteLine(); // Write newline
- }
-
- // Write horizontal divider line
- for(int i = 0 ; i <= SIZE ; i++)
- Console::Write(L"_____");
- Console::WriteLine(); // Write newline
- return 0;
- }
该示例应该产生下面的输出:
- Here is the 12 times table: