4.6.2 CLR数组(5)
示例说明
该程序看起来包含大量代码,但其中大多数都是为了使输出更美观。我们用下面的语句创建二维数组:
- const int SIZE = 12;
- array<int, 2>^ products = gcnew array<int, 2>(SIZE,SIZE);
第一行定义了一个整型常量,以指定数组每一维的元素数量。第二行定义了一个等级为2的数组,共有12行,每行12个元素。该数组将存储12×12乘法表中的乘积。
我们在嵌套循环中设定products数组中各元素的值:
- for (int i = 0 ; i < SIZE ; i++)
- for(int j = 0 ; j < SIZE ; j++)
- products[i,j] = (i+1)*(j+1);
外部循环逐一处理每一行,内部循环逐一处理每一列。各个元素的值是行、列索引值分别加1之后的乘积。main()中的其余代码仅仅与生成输出有关。
在首先输出表标题之后,我们用下面的代码生成一条水平直线作为乘法表的顶线:
- for(int i = 0 ; i <= SIZE ; i++)
- Console::Write(L"_____");
- Console::WriteLine(); // Write newline
该循环的每次迭代都输出5个下划线字符。注意,循环的上限是包括在内的,因此将输出13×5个下划线,以便为乘法表的行标签和12列数据留出位置。
接下来,我们用另一个循环输出乘法表的一行列标签:
- // 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
我们必须在行标签位置的上方单独输出空格,因为那是个特殊位置,不包含任何输出值。各个列标签是在该循环中输出的。然后,输出一个换行符,以便为下一行输出作好准备。
我们使用下面的嵌套循环,输出各个乘积行:
- 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
- }
外部循环逐一处理每一行,其中的代码将输出包括左边行标签在内的完整一行。内部循环输出products数组中对应于第i行的数值,中间用竖线分开。
其余代码再输出一条水平直线,以作为乘法表的底线。
4. 数组的数组
数组元素可以是任意类型,因此当然也可以是引用数组的跟踪句柄。这给我们提供了创建所谓锯齿数组的可能性,因为各个句柄引用的数组可能包括数量不等的元素。通过看一个例子,我们非常容易理解这一点。假设我们希望按照得分等级,分组存储班内儿童的姓名,等级为A,B,C,D,E共5种。我们可以首先创建包含5个元素的数组,各个元素存储一个姓名数组。下面是相应的语句:
- array< array< String^ >^ >^ grades = gcnew
array< array< String^ >^ >(5);
不要被那些^符号搞糊涂,该语句实际上很简单。数组变量grades是array<type>^类型的句柄,该数组的每个元素也是数组的句柄,因此这些数组元素的类型具有相同的形式-- array<type>^,故必须将其放入原来数组类型说明中的尖括号内,结果就是array< array<type>^ >^。那些数组中存储的元素又是String对象的句柄,因此我们必须用String^代替上一个表达式中的type,这样最终得到的数组类型就是array< array< String^ >^ >^。
有了前面创建的数组的数组,现在就可以创建那5个姓名数组。下面是一个例子:- grades[0] = gcnew array<String^>{"Louise", "Jack"};
// Grade A - grades[1] = gcnew array<String^>{"Bill", "Mary",
"Ben","Joan"}; // Grade B - grades[2] = gcnew array<String^>{"Jill", "Will",
"Phil"}; // Grade C - grades[3] = gcnew array<String^>{"Ned","Fred",
"Ted","Jed","Ed"}; // Grade D - grades[4] = gcnew array<String^>{"Dan", "Ann"}; // Grade E
表达式grades[n]访问grades数组的第n个元素,而各个元素当然是指向String^数组的句柄。因此,这5条语句都将创建一个String对象句柄的数组,并将被创建数组的地址存入grades数组的元素中。我们看到,字符串数组的长度是变化的,因此显然可以用这种方法管理一组任意长度的数组。
我们可以用一条语句,创建并初始化整个数组的数组:
- array< array< String^ >^ >^ grades = gcnew array< array< String^ >^ >
- {
- gcnew array<String^>{"Louise", "Jack"}, // Grade A
- gcnew array<String^>{"Bill", "Mary", "Ben", "Joan"}, // Grade B
- gcnew array<String^>{"Jill", "Will", "Phil"}, // Grade C
- gcnew array<String^>{"Ned", "Fred", "Ted", "Jed", "Ed"},
- // Grade D
- gcnew array<String^>{"Dan", "Ann"} // Grade E
- };
元素的初值必须写在大括号之间。
下面把这段代码放入一个可运行程序中,以示范如何来处理数组的数组。