From 3a4e9e3c7127cc65f6dba4addd828c1aaefd7a25 Mon Sep 17 00:00:00 2001 From: FrankLIKE Date: Tue, 26 Jul 2016 22:02:20 +0800 Subject: [PATCH 1/5] =?UTF-8?q?Update=20=E5=AE=8C=E6=88=90=E7=BF=BB?= =?UTF-8?q?=E8=AF=91~arrays.d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ddili/src/ders/d.cn/arrays.d | 222 +++++++++++++++++------------------ 1 file changed, 111 insertions(+), 111 deletions(-) diff --git a/ddili/src/ders/d.cn/arrays.d b/ddili/src/ders/d.cn/arrays.d index e57befb..0abe003 100644 --- a/ddili/src/ders/d.cn/arrays.d +++ b/ddili/src/ders/d.cn/arrays.d @@ -3,7 +3,7 @@ Ddoc $(DERS_BOLUMU $(IX array) Arrays) $(P -We have defined five variables in one of the exercises of the last chapter, and used them in certain calculations. The definitions of those variables were the following: +在上一章的一个练习中我们定义过五个变量,并用它们做过特定计算。下面各项是这些变量的定义: ) --- @@ -15,21 +15,21 @@ We have defined five variables in one of the exercises of the last chapter, and --- $(P -This method of defining variables individually does not scale to cases where even more variables are needed. Imagine needing a thousand values; it is almost impossible to define a thousand variables from $(C value_1) to $(C value_1000). +这种定义个别变量的方法不能扩展到需要更多变量的情况下。想象一下,需要一千个值;定义从 $(C value_1) 到 $(C value_1000) 一千个变量,这几乎是不可能的。 ) $(P -Arrays are useful in such cases: the array feature allows us to define a single variable that stores multiple values together. Although simple, arrays are the most common data structure used to store a collection of values. +数组在这种情况下是有用的:数组功能允许我们定义一个把多个值存储到一起的单个变量。虽然简单,但数组是用于存储值的集合中最常见的数据结构。 ) $(P -This chapter covers only some of the features of arrays. More features will be introduced later in $(LINK2 /ders/d.en/slices.html, the Slices and Other Array Features chapter). +本章仅涉及数组的部分功能。更多功能将在后面 $(LINK2 /ders/d.en/slices.html, 切片和别的数组功能) 一章中介绍。 ) -$(H5 Definition) +$(H5 定义) $(P -The definition of array variables is very similar to the definition of normal variables. The only difference is that the number of values associated with the variable is specified in square brackets. We can contrast the two definitions as follows: +数组变量的定义与正常变量的定义非常相似。唯一的区别是,与变量相关联的值的个数在方括号中指定。我们可以对比两种定义如下: ) --- @@ -38,11 +38,11 @@ The definition of array variables is very similar to the definition of normal va --- $(P -The first line above is the definition of a variable which stores a single value, just like the variables that we have defined so far. The second line is the definition of a variable which stores ten consecutive values. In other words, it stores an array of ten integer values. You can also think of it as defining ten variables of the same type, or as defining an array, for short. +上面的第一行定义了一个存储单个值的变量,就像我们以前定义过的变量那样。第二行定义了一个存储连续十个值的变量。换句话说,它是一个可存储十个整数值的数组。你也可以把它定义为同类型的十个变量,或作为数组定义的简称。 ) $(P -Accordingly, the equivalent of the five separate variables above can be defined as an array of five values using the following syntax: +因此,上面的五个独立的变量可以等效的使用下面的语法定义为含五个值的数组: ) --- @@ -50,49 +50,49 @@ Accordingly, the equivalent of the five separate variables above can be defined --- $(P -$(IX scalar) That definition can be read as $(I 5 double values). Note that I have chosen the name of the array variable as plural to avoid confusing it with a single-valued variable. Variables which only store a single value are called scalar variables. +$(IX 标量) 这个定义可以理解为 $(I 5 个 double 值)。请注意,我选择了数组变量的名字为复数,以避免它与单值变量混淆。只存储一个值的变量称为标量变量。 ) $(P -In summary, the definition of an array variable consists of the type of the values, the number of values, and the name of the variable that refers to the array of values: +总之,数组变量的定义包括值的类型、 值的个数和涉及数组值的变量名称: ) --- - $(I type_name)[$(I value_count)] $(I variable_name); + $(I 类型名称)[$(I 值的个数)] $(I 变量名称); --- $(P -The type of the values can also be a user-defined type. (We will see user-defined types later.) For example: +值的类型也可以是用户定义的类型。(我们将在后面看到用户定义类型。)例如: ) --- - // An array that holds the weather information of all - // cities. Here, the bool values may mean - // false: overcast - // true : sunny + // 保存所有城市气象信息的 + // 数组。在这里,bool 值可能意味着 + // false:阴天 + // true :晴天 bool[cityCount] weatherConditions; - // An array that holds the weights of a hundred boxes + // 保存一百个箱子重量的数组 double[100] boxWeights; - // Information about the students of a school + // 有关学校学生的信息 StudentInformation[studentCount] studentInformation; --- -$(H5 $(IX container) $(IX element) Containers and elements) +$(H5 $(IX container) $(IX element) 容器和元素) $(P -Data structures that bring elements of a certain type together are called $(I containers). According to this definition, arrays are containers. For example, an array that holds the air temperatures of the days in July can bring 31 $(C double) values together and form $(I a container of elements of type $(C double)). +聚集特定类型元素的数据结构称为 $(I 容器)。根据定义,数组就是容器。例如,一个保存了七月每天的气温的数组能汇集 31 个 double 值,形成一个 $(I $(C double) 类型元素的容器)。 ) $(P -The variables of a container are called $(I elements). The number of elements of an array is called the $(I length) of the array. +容器的变量称为 $(I 元素)。数组元素的个数称为数组的 $(I length)。 ) -$(H5 $(IX []) Accessing the elements) +$(H5 $(IX []) 元素的访问) $(P -In order to differentiate the variables in the exercise of the previous chapter, we had to append an underscore and a number to their names as in $(C value_1). This is not possible nor necessary when a single array stores all the values under a single name. Instead, the elements are accessed by specifying the $(I element number) within square brackets: +为了与前一章练习中的变量有所区别,我们给变量的名字加上了下划线与数字,像 $(C value_1) 这样。让一个数组在一个名字下存储所有的值,那是不可能也没必要的。相反,通过指定方括号内的元素位置数就可以访问元素: ) --- @@ -100,52 +100,52 @@ In order to differentiate the variables in the exercise of the previous chapter, --- $(P -That expression can be read as $(I the element with the number 0 of the array named values). In other words, instead of typing $(C value_1) one must type $(C values[0]) with arrays. +这个表达式可以理解为 $(I 数组 values 位置 0 处的元素)。换句话说,对数组输入 $(C values[0]) 而不是键入 $(C value_1) 。 ) $(P -There are two important points worth stressing here: +还有两点值得强调: ) $(UL -$(LI $(B The numbers start with zero:) Although humans assign numbers to items starting with 1, the numbers in arrays start at 0. The values that we have numbered as 1, 2, 3, 4, and 5 before are numbered as 0, 1, 2, 3, and 4 in the array. This variation can confuse new programmers. +$(LI $(B 从零开始编号:) 虽然人们习惯于从 1 开始给项目分配编号,但数组是从 0 开始的。以前被我们编号为 1、2、3、4 和 5 的值在数组中编号为 0、1、2、3 和 4。这种变化可能会让编程新手感到困惑。 ) -$(LI $(B Two different uses of the $(C[]) characters:) Don't confuse the two separate uses of the $(C []) characters. When defining arrays, the $(C []) characters are written after the type of the elements and specify the number of elements. When accessing elements, the $(C []) characters are written after the name of the array and specify the number of the element that is being accessed: +$(LI $(B$(C[]) 的两种不同用法:) 不要混淆 $(C []) 的两种独特用法。当我们定义数组时,$(C []) 写在元素类型之后,并指定元素个数。访问元素时,$(C []) 写在数组名称之后,并指定要访问的元素位置数: --- - // This is a definition. It defines an array that consists - // of 12 elements. This array is used to hold the number - // of days in each month. + // 这个是数组的定义。它定义了一个可以存储 + // 12个元素的数组。这个数组用于存储 + // 每个月的天数。 int[12] monthDays; - // This is an access. It accesses the element that - // corresponds to December and sets its value to 31. + // 这个是数组的访问。它访问对应于 + // 十二月的元素,并设置它的值为 31。 monthDays[11] = 31; - // This is another access. It accesses the element that - // corresponds to January, the value of which is passed to - // writeln. + // 这是另一个访问。它访问对应于 + // 一月的元素,并把它的值传给 + // writeln 函数。 writeln("January has ", monthDays[0], " days."); --- $(P -$(B Reminder:) The element numbers of January and December are 0 and 11 respectively; not 1 and 12. +$(B 提醒:) 一月和十二月的元素位置数分别是 0 和 11;而不是 1 和 12。 ) ) ) -$(H5 $(IX index) Index) +$(H5 $(IX index) Index(索引)) $(P -The number of an element is called its $(I index) and the act of accessing an element is called $(I indexing). +元素的位置数称为 $(I index),访问元素的行为称为$(I 索引)。 ) $(P -An index need not be a constant value; the value of a variable can also be used as an index, making arrays even more useful. For example, the month can be determined by the value of the $(C monthIndex) variable below: +索引不必是恒定值;变量的值也能用作索引,这会让数组更有用。例如,下面通过变量 $(C monthIndex) 的值来确定该月: ) --- @@ -153,42 +153,42 @@ An index need not be a constant value; the value of a variable can also be used --- $(P -When the value of $(C monthIndex) is 2, the expression above would print the value of $(C monthDays[2]), the number of days in March. +当 $(C monthIndex) 的值为 2,上面的表达式将输出 $(C monthDays[2]) 的值,即三月的天数。 ) $(P -Only the index values between zero and one less than the length of the array are valid. For example, the valid indexes of a three-element array are 0, 1, and 2. Accessing an array with an invalid index causes the program to be terminated with an error. +只有与数组长度的差值在 0 与 1 之间的索引才有效。例如,一个具有三个元素的数组的有效索引是 0、1 和 2。访问具有无效索引的数组将导致出错从而终止程序。 ) $(P -Arrays are containers where the elements are placed side by side in the computer's memory. For example, the elements of the array holding the number of days in each month can be shown like the following (assuming a year when February has 28 days): +数组是容器,其中的元素在计算机的内存中是逐个放置的。例如,下面数组的元素保存了每个月的天数(假定一年中二月有 28 天): ) $(MONO - indexes → 0 1 2 3 4 5 6 7 8 9 10 11 - elements → | 31 | 28 | 31 | 30 | 31 | 30 | 31 | 31 | 30 | 31 | 30 | 31 | + 索引 → 0 1 2 3 4 5 6 7 8 9 10 11 + 元素 → | 31 | 28 | 31 | 30 | 31 | 30 | 31 | 31 | 30 | 31 | 30 | 31 | ) $(P -$(I $(B Note:) The indexes above are for demonstration purposes only; they are not stored in the computer's memory.) +$(I $(B 注意:) 上面的索引仅用于演示;并没有存储在计算机的内存中。) ) $(P -The element at index 0 has the value 31 (number of days in January); the element at index 1 has the value of 28 (number of days in February), etc. +索引 0 处元素的值为 31(一月的天数);索引1 处元素的值为 28(二月的天数)依次类推。 ) -$(H5 $(IX fixed-length array) $(IX dynamic array) $(IX static array) Fixed-length arrays vs. dynamic arrays) +$(H5 $(IX 定长数组) $(IX 动态数组) $(IX 静态数组) 定长数组与动态数组) $(P -When the length of an array is specified when the program is written, that array is a $(I fixed-length array). When the length can change during the execution of the program, that array is a $(I dynamic array). +当数组的长度是在写程序时指定时,该数组就是一个$(I 定长数组)。当长度可以在程序的执行过程中进行修改时,该数组就是一个$(I 动态数组)。 ) $(P -Both of the arrays that we have defined above are fixed-length arrays because their element counts are specified as 5 and 12 at the time when the program is written. The lengths of those arrays cannot be changed during the execution of the program. To change their lengths, the source code must be modified and the program must be recompiled. +上面我们定义的数组都为定长数组,因为元素的个数在写程序时已指定为 5 和 12。在程序的执行过程中数组的长度不可修改。要修改长度,就必须修改源代码,而且程序必须重新编译。 ) $(P -Defining dynamic arrays is simpler than defining fixed-length arrays because omitting the length makes a dynamic array: +因为省略了长度,所以定义动态数组比定长数组简单: ) --- @@ -196,17 +196,17 @@ Defining dynamic arrays is simpler than defining fixed-length arrays because omi --- $(P -The length of such an array can increase or decrease during the execution of the program. +在程序的执行过程中这种数组的长度可以增加或减少。 ) $(P -Fixed-length arrays are also known as static arrays. +定长数组也被称为静态数组。 ) -$(H5 $(IX .length) Using $(C .length) to get or set the number of elements) +$(H5 $(IX .length) 使用 $(C .length) 来获取或设置元素的个数) $(P -Arrays have properties as well, of which we will see only $(C .length) here. $(C .length) returns the number of elements of the array: +数组也有 properties(属性),在这儿我们只会看到 $(C .length)。$(C .length) 返回数组元素的个数: ) --- @@ -214,32 +214,32 @@ Arrays have properties as well, of which we will see only $(C .length) here. $(C --- $(P -Additionally, the length of dynamic arrays can be changed by assigning a value to this property: +另外,通过对这个 property 指定一个值就可以修改动态数组的 length: ) --- - int[] array; // initially empty - array.length = 5; // now has 5 elements + int[] array; // 初始时为空 + array.length = 5; // 现在有 5 个元素 --- -$(H5 An array example) +$(H5 一个数组例子) $(P -Let's now revisit the exercise with the five values and write it again by using an array: +现在我们重温一下使用五个值的例子,用数组重写一下它: ) --- import std.stdio; void main() { - // This variable is used as a loop counter + // 该变量用作循环计数器 int counter; - // The definition of a fixed-length array of five - // elements of type double + // 定义了一个可包含五个 double + // 类型元素的数组 double[5] values; - // Reading the values in a loop + // 在循环中从输入流读取元素值 while (counter < values.length) { write("Value ", counter + 1, ": "); readf(" %s", &values[counter]); @@ -253,34 +253,34 @@ void main() { ++counter; } - // The loop that calculates the fifths of the values would - // be written similarly + // 经过计算的五个数值 + //将在循环中输出 } --- -$(P $(B Observations:) The value of $(C counter) determines how many times the loops are repeated (iterated). Iterating the loop while its value is less than $(C values.length) ensures that the loops are executed once per element. As the value of that variable is incremented at the end of each iteration, the $(C values[counter]) expression refers to the elements of the array one by one: $(C values[0]), $(C values[1]), etc. +$(P $(B 观测:) $(C counter) 的值决定了循环的重复次数(迭代)。当它的值小于 $(C values.length) 时,迭代循环可以保证每个元素只执行了一次。在每个迭代结束时该变量值都会递增,$(C values[counter]) 表达式指的是数组的逐个元素:$(C values[0])、$(C values[1]) 等等。 ) $(P -To see how this program is better than the previous one, imagine needing to read 20 values. The program above would require a single change: replacing 5 with 20. On the other hand, a program that did not use an array would have to have 20 variable definitions. Furthermore, since you would be unable to use a loop to iterate the 20 values, you would also have to repeat several lines 20 times, one time for each single-valued variable. +要看一看这个程序怎样才能比以前的更好,让我们设想需要读取 20 个值。修改一下上面的程序:用 20 替换 5。另一方面,这个程序若不使用数组那将必须定义 20 个变量。此外,因为您无法使用循环遍历 20 个值,您也不得不把那几行代码重复 20 次,每个单值变量来一次。 ) -$(H5 $(IX initialization, array) Initializing the elements) +$(H5 $(IX 初始化,数组) 初始化元素) $(P -Like every variable in D, the elements of arrays are automatically initialized. The initial value of the elements depends on the type of the elements: 0 for $(C int), $(C double.nan) for $(C double), etc. +像在 D 语言中的每个变量,数组的元素自动初始化。元素的初始值取决于元素类型:$(C int) 的为 0,$(C double) 的为 $(C double.nan) 等等。 ) $(P -All of the elements of the $(C values) array above are initialized to $(C double.nan): +上面 $(C values) 数组的所有元素都初始化为 $(C double.nan): ) --- - double[5] values; // elements are all double.nan + double[5] values; // 元素都是 double.nan --- $(P -Obviously, the values of the elements can be changed later during the execution of the program. We have already seen this above when assigning to an element of an array: +显然,元素的值可以在以后程序执行期间发生变化。这在上面给数组的元素赋值时我们已经看到: ) --- @@ -288,7 +288,7 @@ Obviously, the values of the elements can be changed later during the execution --- $(P -That also happened when reading a value from the input: +从输入流中读取值时也发生了: ) --- @@ -296,7 +296,7 @@ That also happened when reading a value from the input: --- $(P -Sometimes the desired values of the elements are known at the time when the array is defined. In such cases, the initial values of the elements can be specified on the right-hand side of the assignment operator, within square brackets. Let's see this in a program that reads the number of the month from the user, and prints the number of days in that month: +有时在数组定义时元素的期望值是已知的。在这种情况下,元素的初始值可以在分配操作的右手侧方括号内指定。让我们来看一看这个程序,读取来自用户的月数,并输出当月的天数: ) --- @@ -318,27 +318,27 @@ void main() { --- $(P -As you can see, the $(C monthDays) array is defined and initialized at the same time. Also note that the number of the month, which is in the range 1-12, is converted to a valid array index in the range 0-11. Any value that is entered outside of the 1-12 range would cause the program to be terminated with an error. +正如你所看到的,$(C monthDays) 数组在定义的时候就已初始化。另外请注意, 1-12 范围内的月份数字转换为了有效的数组索引范围 0-111-12 范围外的任何值都将导致程序出现错误而终止。 ) $(P -When initializing arrays, it is possible to use a single value on the right-hand side. In that case all of the elements of the array are initialized to that value: +当初始化数组时,也可以在右手侧使用单个值。在这种情况下,所有的数组元素都初始化为该值: ) --- - int[10] allOnes = 1; // All of the elements are set to 1 + int[10] allOnes = 1; // 所有的元素都设置为 1 --- -$(H5 Basic array operations) +$(H5 数组的基本操作) $(P -Arrays provide convenience operations that apply to all of their elements. +数组提供了适用于所有元素的方便操作。 ) -$(H6 $(IX copy, array) Copying fixed-length arrays) +$(H6 $(IX 复制, 数组) 复​​制定长数组) $(P -The assignment operator copies all of the elements from the right-hand side to the left-hand side: +赋值运算符将所有元素从右手侧复制到左手侧: ) --- int[5] source = [ 10, 20, 30, 40, 50 ]; @@ -348,24 +348,24 @@ The assignment operator copies all of the elements from the right-hand side to t --- $(P -$(I $(B Note:) The meaning of the assignment operation is completely different for dynamic arrays. We will see this in a later chapter.) +$(I $(B 注意:) 赋值运算符的含义与动态数组完全不同。我们将在后面的章节中看到这一点。) ) -$(H6 $(IX ~=) $(IX append, array) $(IX add element, array) Adding elements to dynamic arrays) +$(H6 $(IX ~=) $(IX 附加, 数组) $(IX 添加元素, 数组) 给动态数组添加元素) $(P -The $(C ~=) operator adds new elements to the end of a dynamic array: +$(C ~=) 运算符是指在动态数组的尾部添加新的元素: ) --- - int[] array; // empty - array ~= 7; // array is now equal to [7] - array ~= 360; // array is now equal to [7, 360] - array ~= [ 30, 40 ]; // array is now equal to [7, 360, 30, 40] + int[] array; // 空数组 + array ~= 7; // 数组现在等于 [7] + array ~= 360; // 数组现在等于 [7, 360] + array ~= [ 30, 40 ]; // 数组现在等于 [7, 360, 30, 40] --- $(P -It is not possible to add elements to fixed-length arrays: +不可能给定长数组添加元素: ) --- @@ -373,10 +373,10 @@ It is not possible to add elements to fixed-length arrays: array ~= 7; $(DERLEME_HATASI) --- -$(H6 $(IX ~, concatenation) $(IX concatenation, array) Combining arrays) +$(H6 $(IX ~, 连接) $(IX 连接, 数组) 连接数组) $(P -The $(C ~) operator creates a new array by combining two arrays. Its $(C ~=) counterpart combines the two arrays and assigns the result back to the left-hand side array: + $(C ~) 运算符通过连接两个数组从而创建一个新数组。$(C ~=) 组合两侧的数组并把结果赋值给左侧数组: ) --- @@ -388,15 +388,15 @@ void main() { int[] result; result = first ~ second; - writeln(result.length); // prints 20 + writeln(result.length); // 输出 20 result ~= first; - writeln(result.length); // prints 30 + writeln(result.length); // 输出 30 } --- $(P -The $(C ~=) operator cannot be used when the left-hand side array is a fixed-length array: +左侧数组是定长数组时 $(C ~=) 运算符不能使用: ) --- @@ -406,7 +406,7 @@ The $(C ~=) operator cannot be used when the left-hand side array is a fixed-len --- $(P -If the array sizes are not equal, the program is terminated with an error during assignment: +如果数组大小不一致,会导致赋值期间出错而终止程序: ) --- @@ -421,10 +421,10 @@ $(SHELL object.Error@(0): Array lengths don't match for copy: $(HILITE 20 != 21) ) -$(H6 $(IX sort) Sorting the elements) +$(H6 $(IX sort(排序)) 排序元素) $(P -$(C std.algorithm.sort) can sort the elements of many types of collections. In the case of integers, the elements get sorted from the smallest value to the greatest value. In order to use the $(C sort()) function, one must import the $(C std.algorithm) module first. (We will see functions in a later chapter.) +$(C std.algorithm.sort) 可以对许多类型集合中的元素进行排序。对于整数,元素按从小到大排序。为了使用 $(C sort()) 函数,必须先导入 $(C std.algorithm) 模块。(在后面的章节我们将看到这些函数。) ) --- @@ -439,17 +439,17 @@ void main() { --- $(P -The output: +输出: ) $(SHELL [1, 2, 3, 4, 5] ) -$(H6 $(IX reverse) Reversing the elements) +$(H6 $(IX reverse(反转)) 反转元素) $(P -$(C std.algorithm.reverse) reverses the elements in place (the first element becomes the last element, etc.): +$(C std.algorithm.reverse) 反转元素的位置(第一个元素成为最后一个元素,以此类推): ) --- @@ -464,7 +464,7 @@ void main() { --- $(P -The output: +输出: ) $(SHELL @@ -474,14 +474,14 @@ $(SHELL $(PROBLEM_COK $(PROBLEM -Write a program that asks the user how many values will be entered and then reads all of them. Have the program sort the elements using $(C sort()) and then reverse the sorted elements using $(C reverse()). +编写一个程序,要求用户输入多少值,然后全部读取。让程序使用 $(C sort()) 函数排序元素,然后使用 $(C reverse()) 函数反转排序的元素。 ) $(PROBLEM -Write a program that reads numbers from the input, and prints the odd and even ones separately but in order. Treat the value -1 specially to determine the end of the numbers; do not process that value. +编写一个程序,从输入流中读取数字,并先后按顺序分别输出奇数和偶数。并专门用值 -1 来确定数字的结束;不处理该值。 $(P -For example, when the following numbers are entered, +例如,当输入了下面的数字, ) $(SHELL @@ -489,7 +489,7 @@ $(SHELL ) $(P -have the program print the following: +程序会输出以下内容: ) $(SHELL @@ -497,16 +497,16 @@ $(SHELL ) $(P -$(B Hint:) You may want to put the elements in separate arrays. You can determine whether a number is odd or even using the $(C %) (remainder) operator. +$(B 提示:) 你可以把元素放入单独的数组。使用 $(C %)(求余数)运算符来确定数字是奇数还是偶数。 ) ) $(PROBLEM -The following is a program that does not work as expected. The program is written to read five numbers from the input and to place the squares of those numbers into an array. The program then attempts to print the squares to the output. Instead, the program terminates with an error. +以下为预期不起作用的程序。程序要求从输入流中读取五个数字,并把这些数字放入一个数组。然后程序会输出这些平方。若有错误,程序会终止。 $(P -Fix the bugs of this program and make it work as expected: +请修复程序的 bug,让它按预期的方式执行: ) --- @@ -542,11 +542,11 @@ void main() { ) Macros: - SUBTITLE=Arrays + SUBTITLE=数组 - DESCRIPTION=Basic array operations of the D programming language + DESCRIPTION=D 语言数组的基本操作 - KEYWORDS=d programming language tutorial book arrays fixed-length dynamic + KEYWORDS=D 编程语言 教程 定长 动态 $(Ergin) From 3e0a6c496e790f46d8d759b5dbb1bc755837a2c5 Mon Sep 17 00:00:00 2001 From: FrankLIKE Date: Tue, 26 Jul 2016 22:03:10 +0800 Subject: [PATCH 2/5] =?UTF-8?q?Update=20=E5=AE=8C=E6=88=90=E7=BF=BB?= =?UTF-8?q?=E8=AF=91~arrays.cozum.d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ddili/src/ders/d.cn/arrays.cozum.d | 38 +++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/ddili/src/ders/d.cn/arrays.cozum.d b/ddili/src/ders/d.cn/arrays.cozum.d index 3e0d3fa..a7cfaa0 100644 --- a/ddili/src/ders/d.cn/arrays.cozum.d +++ b/ddili/src/ders/d.cn/arrays.cozum.d @@ -1,6 +1,6 @@ Ddoc -$(COZUM_BOLUMU Arrays) +$(COZUM_BOLUMU 数组) $(OL @@ -18,7 +18,7 @@ void main() { double[] values; values.length = count; - // The counter is commonly named as 'i' + // 计数器通常命名作‘i’ int i; while (i < count) { write("Value ", i, ": "); @@ -51,15 +51,15 @@ void main() { ) $(LI -The explanations are included as code comments: +解释包含在代码说明中: --- import std.stdio; import std.algorithm; void main() { - // Using dynamic arrays because it is not known how many - // values are going to be read from the input + // 使用动态数组的原因是不知道有多少 + // 值要从输入流中读取 int[] odds; int[] evens; @@ -67,18 +67,18 @@ void main() { while (true) { - // Reading the value + // 从输入流中读取值 int value; readf(" %s", &value); - // The special value of -1 breaks the loop + // 特殊值 -1 中断循环 if (value == -1) { break; } - // Adding to the corresponding array, depending on - // whether the value is odd or even. It is an even - // number if there is no remainder when divided by 2. + // 根据值的奇偶性,把值添加到 + //相应的数组。如果值被 2 + // 整除而没有余数,那这个数就是偶数。 if ((value % 2) == 0) { evens ~= value; @@ -87,17 +87,17 @@ void main() { } } - // The odds and evens arrays are sorted separately + // 分别排序奇偶数的数组 sort(odds); sort(evens); - // The two arrays are then appended to form a new array + // 连接两个数组从而形成一个新数组 int[] result; result = odds ~ evens; writeln("First the odds then the evens, sorted:"); - // Printing the array elements in a loop + // 在循环中输出数组元素 int i; while (i < result.length) { write(result[i], " "); @@ -111,14 +111,14 @@ void main() { ) $(LI -There are three mistakes (bugs) in this program. The first two are with the $(C while) loops: Both of the loop conditions use the $(C <=) operator instead of the $(C <) operator. As a result, the program uses invalid indexes and attempts to access elements that are not parts of the arrays. +程序有三个错误(bugs)。前两个在 $(C while) 循环: 循环条件都使用 $(C <=) 运算符而不使用 $(C <) 运算符。结果是,程序使用无效的索引,试图访问不在数组中的元素。 $(P -Since it is more beneficial for you to debug the third mistake yourself, I would like you to first run the program after fixing the previous two bugs. You will notice that the program will not print the results. Can you figure out the remaining problem before reading the following paragraph? +自行调试第三个错误对你来说更有益,建议你在修复了前两个 bug 之后先运行一下程序。你将注意到程序不会输出结果。在没有读下面这段话之前你能指出剩下的问题吗? ) $(P -The value of $(C i) is 5 when the first $(C while) loop terminates, and that value is causing the logical expression of the second loop to be $(C false), which in turn is preventing the second loop to be entered. The solution is to reset $(C i) to 0 before the second $(C while) loop, for example with the statement $(C i = 0;) +当第一个 $(C while) 循环结束时 $(C i) 值为 5,该值导致第二个循环的逻辑表达式的值为 $(C false),是它阻止进入第二个循环。 解决办法就是在第二个 $(C while) 循环前重设 $(C i) 为 0,比如使用语句 $(C i = 0;) ) ) @@ -126,8 +126,8 @@ The value of $(C i) is 5 when the first $(C while) loop terminates, and that val ) Macros: - SUBTITLE=Arrays Solutions + SUBTITLE=数组习题解答 - DESCRIPTION=Programming in D exercise solutions: arrays + DESCRIPTION=D 语言编程习题解答:数组 - KEYWORDS=programming in d tutorial arrays solution + KEYWORDS=D 语言编程教程 数组 习题解答 From dea541c594c5c7f4b1bf5ab674d20a1e47f9ed34 Mon Sep 17 00:00:00 2001 From: FrankLIKE Date: Thu, 4 Aug 2016 19:58:16 +0800 Subject: [PATCH 3/5] =?UTF-8?q?Update=20=E7=BF=BB=E8=AF=91=E6=9B=B4?= =?UTF-8?q?=E6=AD=A3=20~=20arrays.d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ddili/src/ders/d.cn/arrays.d | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ddili/src/ders/d.cn/arrays.d b/ddili/src/ders/d.cn/arrays.d index 0abe003..f0a80ab 100644 --- a/ddili/src/ders/d.cn/arrays.d +++ b/ddili/src/ders/d.cn/arrays.d @@ -3,7 +3,7 @@ Ddoc $(DERS_BOLUMU $(IX array) Arrays) $(P -在上一章的一个练习中我们定义过五个变量,并用它们做过特定计算。下面各项是这些变量的定义: +在上一章的一个练习中我们定义过五个变量,并用它们做过特定计算。下面是这些变量的定义: ) --- @@ -15,21 +15,21 @@ $(P --- $(P -这种定义个别变量的方法不能扩展到需要更多变量的情况下。想象一下,需要一千个值;定义从 $(C value_1) 到 $(C value_1000) 一千个变量,这几乎是不可能的。 +这种定义个别变量的方法不能扩展到需要更多变量的情况。想象一下,需要一千个值;定义从 $(C value_1) 到 $(C value_1000) 一千个变量,这几乎是不可能的。 ) $(P -数组在这种情况下是有用的:数组功能允许我们定义一个把多个值存储到一起的单个变量。虽然简单,但数组是用于存储值的集合中最常见的数据结构。 +数组在这种情况下就派上用场了:数组的特征允许我们定义把多个值存储到一起的单个变量。虽然简单,但数组是用于存储值的集合中最常见的数据结构。 ) $(P -本章仅涉及数组的部分功能。更多功能将在后面 $(LINK2 /ders/d.en/slices.html, 切片和别的数组功能) 一章中介绍。 +本章仅涉及数组的部分功能。更多功能将在后面的 $(LINK2 /ders/d.cn/slices.html, 切片和别的数组功能) 一章中介绍。 ) $(H5 定义) $(P -数组变量的定义与正常变量的定义非常相似。唯一的区别是,与变量相关联的值的个数在方括号中指定。我们可以对比两种定义如下: +数组变量的定义与正常变量的定义非常相似。唯一的区别是,应在方括号中指定与数组变量相关联的值的个数。我们可以对比两种定义如下: ) --- From 1b2e2268c4a14462de6eb1c1d1206c4f6cf4b1ff Mon Sep 17 00:00:00 2001 From: FrankLIKE Date: Thu, 4 Aug 2016 20:01:10 +0800 Subject: [PATCH 4/5] =?UTF-8?q?Update=20=E7=BF=BB=E8=AF=91=E6=9B=B4?= =?UTF-8?q?=E6=AD=A3=20~=20arrays.cozum.d?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ddili/src/ders/d.cn/arrays.cozum.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ddili/src/ders/d.cn/arrays.cozum.d b/ddili/src/ders/d.cn/arrays.cozum.d index a7cfaa0..3840534 100644 --- a/ddili/src/ders/d.cn/arrays.cozum.d +++ b/ddili/src/ders/d.cn/arrays.cozum.d @@ -111,14 +111,14 @@ void main() { ) $(LI -程序有三个错误(bugs)。前两个在 $(C while) 循环: 循环条件都使用 $(C <=) 运算符而不使用 $(C <) 运算符。结果是,程序使用无效的索引,试图访问不在数组中的元素。 +程序有三个错误(bugs)。前两个与 $(C while) 循环有关: 循环条件都用了 $(C <=) 运算符而没用 $(C <) 运算符。因此,程序使用了无效的索引,试图访问不在数组中的元素。 $(P 自行调试第三个错误对你来说更有益,建议你在修复了前两个 bug 之后先运行一下程序。你将注意到程序不会输出结果。在没有读下面这段话之前你能指出剩下的问题吗? ) $(P -当第一个 $(C while) 循环结束时 $(C i) 值为 5,该值导致第二个循环的逻辑表达式的值为 $(C false),是它阻止进入第二个循环。 解决办法就是在第二个 $(C while) 循环前重设 $(C i) 为 0,比如使用语句 $(C i = 0;) +当第一个 $(C while) 循环结束时 $(C i) 值为 5,该值使得第二个循环的逻辑表达式的值为 $(C false),因此进入不了第二个循环。 解决办法就是在第二个 $(C while) 循环前重设 $(C i) 为 0,比如使用语句 $(C i = 0;) ) ) From 94d102780a567fb8ae044b17d1601eea0947f498 Mon Sep 17 00:00:00 2001 From: FrankLIKE Date: Tue, 6 Sep 2016 07:53:30 +0800 Subject: [PATCH 5/5] Update ~slices.d,slices.cozum.d --- ddili/src/ders/d.cn/slices.cozum.d | 30 +-- ddili/src/ders/d.cn/slices.d | 320 ++++++++++++++--------------- 2 files changed, 175 insertions(+), 175 deletions(-) diff --git a/ddili/src/ders/d.cn/slices.cozum.d b/ddili/src/ders/d.cn/slices.cozum.d index 9667aea..26ecb0b 100644 --- a/ddili/src/ders/d.cn/slices.cozum.d +++ b/ddili/src/ders/d.cn/slices.cozum.d @@ -3,7 +3,7 @@ Ddoc $(COZUM_BOLUMU Slices and Other Array Features) $(P -Iterating over elements by consuming a slice from the beginning is an interesting concept. This method is also the basis of Phobos ranges that we will see in a later chapter. +通过从开始处缩减切片来遍历元素是一个有意思的想法。在后面的一章中我们将看到这个方法也是 Phobos 的 range 的基本方法。 ) --- @@ -12,29 +12,29 @@ import std.stdio; void main() { double[] array = [ 1, 20, 2, 30, 7, 11 ]; - double[] slice = array; // Start with a slice that - // provides access to all of - // the elements of the array + double[] slice = array; // 允许切片 + // 访问数组的 + // 所有元素 - while (slice.length) { // As long as there is at least - // one element in that slice + while (slice.length) { // 只要切片 + // 至少有一个元素 - if (slice[0] > 10) { // Always use the first element - slice[0] /= 2; // in the expressions + if (slice[0] > 10) { // 在表达式中 + slice[0] /= 2; // 总是使用第一个元素 } - slice = slice[1 .. $]; // Shorten the slice from the - // beginning + slice = slice[1 .. $]; // 从开始处缩短 + // 切片 } - writeln(array); // The actual elements are - // changed + writeln(array); // 实际元素已经 + // 发生变化 } --- Macros: - SUBTITLE=Slices and Other Array Features Solution + SUBTITLE=切片和其它的数组特征习题解答 - DESCRIPTION=Programming in D exercise solutions: arrays + DESCRIPTION=D 语言编程习题解答:数组 - KEYWORDS=programming in d tutorial arrays solution + KEYWORDS=D 语言编程教程 数组 习题解答 diff --git a/ddili/src/ders/d.cn/slices.d b/ddili/src/ders/d.cn/slices.d index 598d64f..21f5a45 100644 --- a/ddili/src/ders/d.cn/slices.d +++ b/ddili/src/ders/d.cn/slices.d @@ -1,66 +1,66 @@ Ddoc -$(DERS_BOLUMU $(IX slice) $(IX array) Slices and Other Array Features) +$(DERS_BOLUMU $(IX slice) $(IX 数组) 切片和其它的数组特征) $(P -We have seen in the $(LINK2 /ders/d.en/arrays.html, Arrays chapter) how elements are grouped as a collection in an array. That chapter was intentionally brief, leaving most of the features of arrays to this chapter. +在 $(LINK2 /ders/d.cn/arrays.html, 数组) 一章中我们已经看到元素是如何被整理为一个数组中的集合。那章是比较简短,数组的大部分特征都留在这一章来讲。 ) $(P -Before going any further, here are a few brief definitions of some of the terms that happen to be close in meaning: +在细讲特征之前,先简单介绍一些意思相近的术语: ) $(UL -$(LI $(B Array:) The general concept of a group of elements that are located side by side and are accessed by indexes. +$(LI $(B 数组:) 通常是指被逐个放置并通过索引来访问的一组元素。 ) $(LI -$(B Fixed-length array (static array):) An array with a fixed number of elements. This type of array owns its elements. +$(B 定长数组(静态数组):) 有固定数量元素的数组。该类型数组拥有自己的元素。 ) $(LI -$(B Dynamic array:) An array that can gain or lose elements. This type of array provides access to elements that are owned by the D runtime environment. +$(B 动态数组:)能获得或失去元素的数组。该类数组允许访问受 D 运行时环境管理的元素。 ) -$(LI $(B Slice:) Another name for $(I dynamic array). +$(LI $(B 切片:)$(I 动态数组)的另一名称。 ) ) $(P -When I write $(I slice) I will specifically mean a slice; and when I write $(I array), I will mean either a slice or a fixed-length array, with no distinction. +书中的 $(I slice) 特指 slice(切片);$(I 数组)指 slice 或定长数组,没有区别。 ) -$(H5 Slices) +$(H5 切片) $(P -Slices are the same feature as dynamic arrays. They are called $(I dynamic arrays) for being used like arrays, and are called $(I slices) for providing access to portions of other arrays. They allow using those portions as if they are separate arrays. +切片与动态数组的特征一致。当它的用法像数组时称为$(I 动态数组),当它可以访问别的数组接口时称为$(I 切片)。它们允许使用那些接口,就像它们是独立的数组。 ) $(P -$(IX .., slice element range) Slices are defined by the $(I number range) syntax that correspond to the indexes that specify the beginning and the end of the range: +$(IX .., 切片元素范围) 切片由$(I 数量范围)语法定义,该语法与范围的开始、结束索引相对应: ) --- - $(I beginning_index) .. $(I one_beyond_the_end_index) + $(I 开始索引) .. $(I 超出的结束索引) --- $(P -In the number range syntax, the beginning index is a part of the range but the end index is outside of the range: +在数量范围的语法中,开始索引是范围的一部分,但结束索引在范围之外: ) --- -/* ... */ = monthDays[0 .. 3]; // 0, 1, and 2 are included; but not 3 +/* ... */ = monthDays[0 .. 3]; // 0,1,和 2 包括在内,但不含 3 --- $(P -$(I $(B Note:) Number ranges are different from Phobos ranges. Phobos ranges are about struct and class interfaces. We will see these features in later chapters. +$(I $(B 注:)数量范围与 Phobos 的 range 不同。Phobos 的 range 与 struct 和 class 接口有关。在后面的章节中我们将看到这些特征。 ) ) $(P -As an example, we can $(I slice) the $(C monthDays) array to be able to use its parts as four smaller arrays: +举个例子,我们$(I 裁减)一下 $(C monthDays) 数组,以便把它用作四个小数组: ) --- @@ -74,7 +74,7 @@ As an example, we can $(I slice) the $(C monthDays) array to be able to use its --- $(P -The four variables in the code above are slices; they provide access to four parts of an already existing array. An important point worth stressing here is that those slices do not have their own elements. They merely provide access to the elements of the actual array. Modifying an element of a slice modifies the element of the actual array. To see this, let's modify the first elements of each slice and then print the actual array: +上面代码中的四个变量就是切片;它们可以访问现有数组的四个部分。值得强调的一点是,这些切片不拥有自己的元素。它们只能访问实际数组的元素。修改切片的元素就会修改实际数组的元素。让我们修改一下每个切片的第一个元素,然后打印实际的数组来看一看: ) --- @@ -87,7 +87,7 @@ The four variables in the code above are slices; they provide access to four par --- $(P -The output: +输出: ) $(SHELL @@ -95,24 +95,24 @@ $(SHELL ) $(P -Each slice modifies its first element, and the corresponding element of the actual array is affected. +每个切片修改了第一个元素,实际数组的相应元素受到了影响。 ) $(P -We have seen earlier that valid array indexes are from 0 to one less than the length of the array. For example, the valid indexes of a 3-element array are 0, 1, and 2. Similarly, the end index in the slice syntax specifies one beyond the last element that the slice will be providing access to. For that reason, when the last element of an array needs to be included in a slice, the length of the array must be specified as the end index. For example, a slice of all elements of a 3-element array would be $(C array[0..3]). +前面我们已经看到,有效的数组索引是从 0 到一个小于数组长度的值。例如,3 个元素数组的有效索引是 0,1 和 2。同样地,在切片语法中结束索引特指超过切片能访问的最后一个元素的索引。因此,当需要把数组的最后一个元素包括在切片中时,就必须把数组的长度值指定为结束索引。例如,一个包含 3 个元素数组的全部元素的切片会是 $(C array[0..3])。 ) $(P -An obvious limitation is that the beginning index cannot be greater than the end index: +一个明显的限制是开始索引不能大于结束索引: ) --- int[3] array = [ 0, 1, 2 ]; - int[] slice = array[2 .. 1]; // ← run-time ERROR + int[] slice = array[2 .. 1]; // ←运行时错误 --- $(P -It is legal to have the beginning and the end indexes to be equal. In that case the slice is empty. Assuming that $(C index) is valid: +开始索引和结束索引相等是合法的。这种情况下切片是空的。假设 $(C index) 有效: ) --- @@ -121,28 +121,28 @@ It is legal to have the beginning and the end indexes to be equal. In that case --- $(P -The output: +输出: ) $(SHELL The length of the slice: 0 ) -$(H5 $(IX $, slice length) Using $(C $), instead of $(C array.length)) +$(H5 $(IX $, 切片长度)使用 $(C $),而不是 $(C array.length)) $(P -When indexing, $(C $) is a shorthand for the length of the array: +在索引中,$(C $) 是数组长度的简写: ) --- - writeln(array[array.length - 1]); // the last element - writeln(array[$ - 1]); // the same thing + writeln(array[array.length - 1]); // 最后一个元素 + writeln(array[$ - 1]); // 同上 --- -$(H5 $(IX .dup) $(IX copy, array) Using $(C .dup) to copy) +$(H5 $(IX .dup) $(IX 复制, 数组) 使用 $(C .dup) 复制) $(P -Short for "duplicate", the $(C .dup) property makes a new array from the copies of the elements of an existing array: +作为“duplicate(复制)”的简写,$(C .dup) property(属性)从现有数组元素的副本中生成一个新的数组: ) --- @@ -151,7 +151,7 @@ Short for "duplicate", the $(C .dup) property makes a new array from the copies --- $(P -As an example, let's define an array that contains the number of days of the months of a leap year. A method is to take a copy of the non-leap-year array and then to increment the element that corresponds to February: +作为一个例子,让我们来定义一个包含某个闰年的月份天数的数组。一种方法是取非闰年数组的一个副本,然后递增相应的二月份的元素: ) --- @@ -163,7 +163,7 @@ void main() { int[] leapYear = monthDays$(HILITE .dup); - ++leapYear[1]; // increments the days in February + ++leapYear[1]; // 递增二用份的天数 writeln("Non-leap year: ", monthDays); writeln("Leap year : ", leapYear); @@ -171,7 +171,7 @@ void main() { --- $(P -The output: +输出: ) $(SHELL_SMALL @@ -179,22 +179,22 @@ Non-leap year: [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] Leap year : [31, $(HILITE 29), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] ) -$(H5 $(IX assignment, array) Assignment) +$(H5 $(IX 赋值, 数组) 赋值) $(P -We have seen so far that the assignment operator $(I modifies) values of variables. It is the same with fixed-length arrays: +到目前为止,我们已经看到赋值运算符可以$(I 修改)变量的值。对定长数组这个同样有效: ) --- int[3] a = [ 1, 1, 1 ]; int[3] b = [ 2, 2, 2 ]; - a = b; // the elements of 'a' become 2 + a = b; // ‘a’的元素变为了 2 writeln(a); --- $(P -The output: +输出: ) $(SHELL @@ -202,14 +202,14 @@ $(SHELL ) $(P -The assignment operation has a completely different meaning for slices: It makes the slice start providing access to new elements: +赋值操作对切片有完全不同的含义:它让切片可以访问新元素: ) --- int[] odds = [ 1, 3, 5, 7, 9, 11 ]; int[] evens = [ 2, 4, 6, 8, 10 ]; - int[] slice; // not providing access to any elements yet + int[] slice; // 还不能访问任何元素 $(HILITE slice =) odds[2 .. $ - 2]; writeln(slice); @@ -219,7 +219,7 @@ The assignment operation has a completely different meaning for slices: It makes --- $(P -Above, $(C slice) does not provide access to any elements when it is defined. It is then used to provide access to some of the elements of $(C odds), and later to some of the elements of $(C evens): +上面的 $(C slice) 在定义时不能访问任何元素。赋值后它就可以访问 $(C odds) 数组的部分元素,以及后来可以访问 $(C evens) 数组的部分元素: ) $(SHELL @@ -227,14 +227,14 @@ $(SHELL [4, 6, 8] ) -$(H5 Making a slice longer may terminate sharing) +$(H5 生成更长的切片可以终止共享) $(P -Since the length of a fixed-length array cannot be changed, the concept of $(I termination of sharing) is only about slices. +由于定长数组的长度不能修改,因此$(I 终止共享)的概念仅与切片有关。 ) $(P -It is possible to access the same elements by more than one slice. For example, the first two of the eight elements below are being accessed through three slices: +可以让一个以上的切片来访问相同的元素。例如,通过三个切片可以访问下面八个元素中的前两个: ) --- @@ -245,7 +245,7 @@ void main() { int[] half = slice[0 .. $ / 2]; int[] quarter = slice[0 .. $ / 4]; - quarter[1] = 0; // modify through one slice + quarter[1] = 0; // 通过一个切片修改 writeln(quarter); writeln(half); @@ -254,7 +254,7 @@ void main() { --- $(P -The effect of the modification to the second element of $(C quarter) is seen through all slices: +通过所有的切片可以看到修改 $(C quarter) 的第二个元素所产生的效果: ) $(SHELL @@ -264,27 +264,27 @@ $(SHELL ) $(P -$(IX stomping) When viewed this way, slices provide $(I shared) access to elements. This sharing opens the question of what happens when a new element is added to one of the slices. Since multiple slices can provide access to same elements, there may not be room to add elements to a slice without $(I stomping) on the elements of others. +$(IX stomping) 当这样查看时, 切片提供元素的$(I 共享)访问。当给这样的切片添加新元素时,这种共享可能会有麻烦。由于多个切片可以访问相同的元素,若切片没有空间添加元素,那么在别的切片元素上就没有 $(I stomping(覆盖))。 ) $(P -D disallows element stomping and answers this question by terminating the sharing relationship if there is no room for the new element: The slice that has no room to grow leaves the sharing. When this happens, all of the existing elements of that slice are copied to a new place automatically and the slice starts providing access to these new elements. +如果没有为新元素留出空间,D 就不允许元素 stomping,并且通过终止共享关系来回应这个问题:没有成长空间的切片会停止共享。当这种情况发生时,切片所有的现有元素都被自动复制到一个新的地方,然后切片会提供对这些新元素的访问。 ) $(P -To see this in action, let's add an element to $(C quarter) before modifying its second element: +为看到这种行为,让我们在修改第二个元素之前给 $(C quarter) 添加一个元素: ) --- - quarter ~= 42; // this slice leaves the sharing because - // there is no room for the new element + quarter ~= 42; // 切片停止了共享,因为 + // 没有为新元素留出空间 - quarter[1] = 0; // for that reason this modification - // does not affect the other slices + quarter[1] = 0; //因此,这样的修改 + // 不会影响到别的切片 --- $(P -The output of the program shows that the modification to the $(C quarter) slice does not affect the others: +程序的输出显示,对 $(C quarter) 切片的修改没有影响到其它切片: ) $(SHELL @@ -294,37 +294,37 @@ $(SHELL ) $(P -Explicitly increasing the length of a slice makes it leave the sharing as well: +明确增加切片的长度也会让它远离共享: ) --- - ++quarter.length; // leaves the sharing + ++quarter.length; // 没有共享 --- $(P -or +或者 ) --- - quarter.length += 5; // leaves the sharing + quarter.length += 5; // 没有共享 --- $(P -On the other hand, shortening a slice does not affect sharing. Shortening the slice merely means that the slice now provides access to fewer elements: +另一方面,缩短切片不会影响共享。缩短切片仅仅意味着切片可以访问较少的元素: ) --- int[] a = [ 1, 11, 111 ]; int[] d = a; - d = d[1 .. $]; // shortening from the beginning - d[0] = 42; // modifying the element through the slice + d = d[1 .. $]; // 从开始位置缩短 + d[0] = 42; // 通过切片修改元素 - writeln(a); // printing the other slice + writeln(a); // 输出别的切片 --- $(P -As can be seen from the output, the modification through $(C d) is seen through $(C a); the sharing is still in effect: +从输出中可以看出,通过 $(C a) 可以看到对 $(C d) 的修改;共享仍然有效: ) $(SHELL @@ -332,23 +332,23 @@ $(SHELL ) $(P -Reducing the length in different ways does not terminate the sharing either: +以不同方式减少长度都不会终止共享: ) --- - d = d[0 .. $ - 1]; // shortening from the end - --d.length; // same thing - d.length = d.length - 1; // same thing + d = d[0 .. $ - 1]; // 从末端缩短 + --d.length; // 同上 + d.length = d.length - 1; // 同上 --- $(P -Sharing of elements is still in effect. +元素的共享仍然有效。 ) -$(H6 $(IX .capacity) Using $(C capacity) to determine whether sharing will be terminated) +$(H6 $(IX .capacity) 使用 $(C capacity) 来确定是否会终止共享) $(P -There are cases when slices continue sharing elements even after an element is added to one of them. This happens when the element is added to the longest slice and there is room at the end of it: +有时候,在元素添加到其中的一个切片后,切片仍继续共享元素。这是因为,当元素添加到最长的切片上时,在末端留有空间: ) --- @@ -359,8 +359,8 @@ void main() { int[] half = slice[0 .. $ / 2]; int[] quarter = slice[0 .. $ / 4]; - slice ~= 42; // adding to the longest slice ... - $(HILITE slice[1] = 0); // ... and then modifying an element + slice ~= 42; // 添加到最长的切片上 ... + $(HILITE slice[1] = 0); // ... 修改一个元素 writeln(quarter); writeln(half); @@ -369,7 +369,7 @@ void main() { --- $(P -As seen in the output, although the added element increases the length of a slice, the sharing has not been terminated, and the modification is seen through all slices: +在输出中可以看到,虽然添加元素增加了切片的长度,共享还没有终止,通过所有的切片可以看到修改:: ) $(SHELL @@ -379,39 +379,39 @@ $(SHELL ) $(P -The $(C capacity) property of slices determines whether the sharing will be terminated if an element is added to a particular slice. ($(C capacity) is actually a function but this distinction does not have any significance in this discussion.) +一个元素添加到特定切片上时,切片的 $(C capacity) property(属性)决定了共享是否会终止。虽然 ($(C capacity) 实际上是个函数,但讨论这种差别没有任何意义。) ) $(P -The value of $(C capacity) has the following meanings: +$(C capacity) 的值具有如下含义: ) $(UL $(LI -When its value is 0, it means that this is not the longest original slice. In this case, adding a new element would definitely relocate the elements of the slice and the sharing would terminate. +值为 0,表示这不是最长的原始切片。在这种情况下,添加新元素一定会迁移切片的元素,并且共享将终止。 ) $(LI -When its value is nonzero, it means that this is the longest original slice. In this case $(C capacity) denotes the total number of elements that this slice can hold without needing to be copied. The number of $(I new elements) that can be added can be calculated by subtracting the actual length of the slice from the capacity value. If the length of the slice equals its capacity, then the slice will be copied to a new location if one more element is added.) +值为非零时,则表示这是最长的原始切片。这种情况下, $(C capacity) 表示切片拥有的不需要被复制的元素总数。可以加入的 $(I 新元素) 的数量可以通过从容量值中减去切片的实际长度来计算。如果切片的长度等于它的容量,那么添加一个以上的元素时,切片将被复制到新的位置。) ) $(P -Accordingly, a program that needs to determine whether the sharing will terminate should use a logic similar to the following: +因此,需要确定共享是否终止的程序可以使用类似于下面的逻辑: ) --- if (slice.capacity == 0) { - /* Its elements would be relocated if one more element - * is added to this slice. */ + /* 如果一个以上的元素添加到切片上时,它的元素 + * 的位置会迁移。*/ // ... } else { - /* This slice may have room for new elements before - * needing to be relocated. Let's calculate how - * many: */ + /* 在切片迁移之前,切片还有空间 + * 存储新元素。让我们计算 + * 一下还需要多少:*/ auto howManyNewElements = slice.capacity - slice.length; // ... @@ -419,14 +419,14 @@ Accordingly, a program that needs to determine whether the sharing will terminat --- $(P -An interesting corner case is when there are more than one slice to $(I all elements). In such a case all slices report to have capacity: +一个有趣的不引人注意的情况是,当有一个以上的切片拥有$(I 所有的元素)时,这种情况下,所有的切片都会报告有 capacity: ) --- import std.stdio; void main() { - // Three slices to all elements + // 三个切片拥有全部元素 int[] s0 = [ 1, 2, 3, 4 ]; int[] s1 = s0; int[] s2 = s0; @@ -438,7 +438,7 @@ void main() { --- $(P -All three have capacity: +三个都有 capacity: ) $(SHELL @@ -448,11 +448,11 @@ $(SHELL ) $(P -However, as soon as an element is added to one of the slices, the capacity of the others drop to 0: +然而,一旦其中的一个切片添加了一个元素, 其它切片的容量就降为了 0: ) --- - $(HILITE s1 ~= 42); $(CODE_NOTE s1 becomes the longest) + $(HILITE s1 ~= 42); $(CODE_NOTE s1 变为了最长的) writeln(s0.capacity); writeln(s1.capacity); @@ -460,19 +460,19 @@ However, as soon as an element is added to one of the slices, the capacity of th --- $(P -Since the slice with the added element is now the longest, it is the only one with capacity: +由于现在最长的切片是添加元素的那个,它是唯一有 capacity 的切片: ) $(SHELL 0 -7 $(SHELL_NOTE now only s1 has capacity) +7 $(SHELL_NOTE 现在只有 s1 有 capacity) 0 ) -$(H6 $(IX .reserve) Reserving room for elements) +$(H6 $(IX .reserve) 为元素预留空间) $(P -Both copying elements and allocating new memory to increase capacity have some cost. For that reason, appending an element can be an expensive operation. When the number of elements to append is known before hand, it is possible to reserve capacity for the elements: +无论复制元素还是分配新内存对增加 capacity 都有一定的成本。因此,附加元素应该是一个昂贵的操作。当要附加的元素数目已知时,就可以为元素预留容量: ) --- @@ -485,31 +485,31 @@ void main() { writeln(slice.capacity); foreach (element; 0 .. $(HILITE 17)) { - slice ~= element; $(CODE_NOTE these elements will not be moved) + slice ~= element; $(CODE_NOTE 这些元素将不会移动) } } --- $(SHELL -31 $(SHELL_NOTE Capacity for at least 20 elements) +31 $(SHELL_NOTE 至少有 20 个元素的容量) ) $(P -The elements of $(C slice) would be moved only after there are more than 31 elements. +$(C slice) 的元素在超过 31 个时将会移动。 ) -$(H5 $(IX array-wise operation) $(IX elements, operation on all) Operations on all elements) +$(H5 $(IX 数组方式操作) $(IX 元素, 全部操作)所有元素上的操作) $(P -This feature is for both fixed-length arrays and slices. +定长数组和切片都有这个特征。 ) $(P -The $(C []) characters written after the name of an array means $(I all elements). This feature simplifies the program when certain operations need to be applied to all of the elements of an array. +数组名后写出的 $(C []) 字符意味着$(I 全部元素)。当某些操作需要被应用到数组的所有元素时该特征简化了程序。 ) $(P -$(I $(B Note:) dmd 2.071, the compiler that was used to compile the examples in this chapter, did not fully support this feature yet. For that reason, some of the examples below use only fixed-length arrays.) +$(I $(B 注:) dmd 2.071,是用来编译本章例子的编译器,还没有完全支持这一特征呢。因此,下面只使用一些定长数组的例子。) ) --- @@ -526,7 +526,7 @@ void main() { --- $(P -The output: +输出: ) $(SHELL @@ -534,19 +534,19 @@ $(SHELL ) $(P -The addition operation in that program is applied to the corresponding elements of both of the arrays in order: First the first elements are added, then the second elements are added, etc. A natural requirement is that the lengths of the two arrays must be equal. +在上面的程序中,加法操作被依次应用到两个数组的相应元素上:首先是第一对元素相加,然后是第二对元素相加,以此类推。这自然要求两个数组的长度必须相等。 ) $(P -The operator can be one of the arithmetic operators $(C +), $(C -), $(C *), $(C /), $(C %), and $(C ^^); one of the binary operators $(C ^), $(C &), and $(C |); as well as the unary operators $(C -) and $(C ~) that are typed in front of an array. We will see some of these operators in later chapters. +运算符可以是算术运算符之一 $(C +),$(C -),$(C *),$(C /),$(C %) 和 $(C ^^);二元运算符之一 $(C ^),$(C &) 和 $(C |);以及在数组前面键入的一元运算符 $(C -) 和 $(C ~)。在后面的章节中我们将看到一些运算符。 ) $(P -The assignment versions of these operators can also be used: $(C =), $(C +=), $(C -=), $(C *=), $(C /=), $(C %=), $(C ^^=), $(C ^=), $(C &=), and $(C |=). +这些运算符的赋值版本也可以使用:$(C =),$(C +=),$(C -=),$(C *=),$(C /=),$(C %=),$(C ^^=),$(C ^=),$(C &=) 和 $(C |=)。 ) $(P -This feature works not only using two arrays; it can also be used with an array and a compatible expression. For example, the following operation divides all elements of an array by four: +这个特征不只是使用两个数组时才可以这样;单个数组和一个复合表达式也可以。例如,下面的操作让数组的全部元素都除以四: ) --- @@ -557,7 +557,7 @@ This feature works not only using two arrays; it can also be used with an array --- $(P -The output: +输出: ) $(SHELL @@ -565,7 +565,7 @@ $(SHELL ) $(P -To assign a specific value to all elements: +给所有的元素赋一个特定值: ) --- @@ -574,7 +574,7 @@ To assign a specific value to all elements: --- $(P -The output: +输出: ) $(SHELL @@ -582,24 +582,24 @@ $(SHELL ) $(P -This feature requires great attention when used with slices. Although there is no apparent difference in element values, the following two expressions have very different meanings: +在使用切片时,这个特征需要高度重视。虽然下面两个表达式的元素值没有明显的差异,但含义明显不同: ) --- - slice2 = slice1; // ← slice2 starts providing access - // to the same elements that - // slice1 provides access to + slice2 = slice1; // ← slice2 开始提供 + // 对 slice1 所提供的 + // 相同元素的访问 - slice3[] = slice1; // ← the values of the elements of - // slice3 change + slice3[] = slice1; // ←修改 slice3 + // 访问 --- $(P -The assignment of $(C slice2) makes it share the same elements as $(C slice1). On the other hand, since $(C slice3[]) means $(I all elements of $(C slice3)), the values of its elements become the same as the values of the elements of $(C slice1). The effect of the presence or absence of the $(C []) characters cannot be ignored. +$(C slice2) 的赋值使得它与 $(C slice1) 共享相同的元素。另一方面,由于 $(C slice3[]) 指的是 $(C slice3) 的$(I 全部元素),元素的值变为与 $(C slice1) 的元素值一致。$(C []) 字符存不存在的影响不能忽略。 ) $(P -We can see an example of this difference in the following program: +在下面的程序中我们能看到这种差异: ) --- @@ -610,23 +610,23 @@ void main() { double[] slice2 = [ 2, 2, 2 ]; double[] slice3 = [ 3, 3, 3 ]; - slice2 = slice1; // ← slice2 starts providing access - // to the same elements that - // slice1 provides access to + slice2 = slice1; // ← slice2 开始提供 + // 对 slice1 所提供的 + // 相同元素的访问 - slice3[] = slice1; // ← the values of the elements of - // slice3 change + slice3[] = slice1; // ←修改 slice3 + // 的元素值 writeln("slice1 before: ", slice1); writeln("slice2 before: ", slice2); writeln("slice3 before: ", slice3); - $(HILITE slice2[0] = 42); // ← the value of an element that - // it shares with slice1 changes + $(HILITE slice2[0] = 42); // ← 它与 slice1 共享元素值的 + // 变化 - slice3[0] = 43; // ← the value of an element that - // only it provides access to - // changes + slice3[0] = 43; // ← 它只提供对 + // 该变化值的 + // 访问 writeln("slice1 after : ", slice1); writeln("slice2 after : ", slice2); @@ -635,7 +635,7 @@ void main() { --- $(P -The modification through $(C slice2) affects $(C slice1) too: +通过 $(C slice2) 的修改也会影响 $(C slice1): ) $(SHELL @@ -648,17 +648,17 @@ slice3 after : [43, 1, 1] ) $(P -The danger here is that the potential bug may not be noticed until after the value of a shared element is changed. +此处的危险是潜在的 bug 直到共享的元素值有了变化时才让人注意到。 ) -$(H5 $(IX multi-dimensional array) Multi-dimensional arrays) +$(H5 $(IX 多维数组) 多维数组) $(P -So far we have used arrays with only fundamental types like $(C int) and $(C double). The element type can actually be any other type, including other arrays. This enables the programmer to define complex containers like $(I array of arrays). Arrays of arrays are called $(I multi-dimensional arrays). +到目前为止,我们用过的数组里只有像 $(C int) 和 $(C double) 这样的基本类型。元素类型实际上可以是任何类型,包括数组。这使得程序员能够定义如$(I 数组的数组)这样复杂的容器。数组的数组被称为 $(I 多维数组)。 ) $(P -The elements of all of the arrays that we have defined so far have been written in the source code from left to right. To help us understand the concept of a two-dimensional array, let's define an array from top to bottom this time: +迄今为止所有我们所定义的数组元素都是从左到右的写入到源代码中的。为了帮助我们理解二维数组的概念,这次我们从上到下的定义数组: ) --- @@ -671,11 +671,11 @@ The elements of all of the arrays that we have defined so far have been written --- $(P -As you remember, most spaces in the source code are used to help with readability and do not change the meaning of the code. The array above could have been defined on a single line and would have the same meaning. +你还记得,源代码中的大部分空格都是用来帮助提高可读性的,并且不会改变代码的含义。上面的数组可以定义在一行,而且含义不变。 ) $(P -Let's now replace every element of that array with another array: +现在让我们用别的数组替换数组的每个元素: ) --- @@ -688,7 +688,7 @@ Let's now replace every element of that array with another array: --- $(P -We have replaced elements of type $(C int) with elements of type $(C int[]). To make the code conform to the array definition syntax, we must now specify the type of the elements as $(C int[]) instead of $(C int): +我们已用 $(C int[]) 类型的元素替换了 $(C int) 类型的元素。要使代码符合数组定义语法,我们现在必须指定 $(C int[]) 作为元素的类型而不是 $(C int): ) --- @@ -701,20 +701,20 @@ We have replaced elements of type $(C int) with elements of type $(C int[]). To --- $(P -Such arrays are called $(I two-dimensional arrays) because they can be seen as having rows and columns. +这样的数组被称为 $(I 二维数组),因为它们有行和列。 ) $(P -Two-dimensional arrays are used the same way as any other array as long as we remember that each element is an array itself and is used in array operations: +二维数组的使用方式和我们记得的任何其它数组一样,每个元素本身就是一个数组,数组操作也能使用: ) --- - array ~= [ 50, 51 ]; // adds a new element (i.e. a slice) - array[0] ~= 13; // adds to the first element + array ~= [ 50, 51 ]; // 添加一个新元素 (即一个切片) + array[0] ~= 13; // 添加到第一个元素 --- $(P -The new state of the array: +数组的新状态: ) $(SHELL_SMALL @@ -722,29 +722,29 @@ $(SHELL_SMALL ) $(P -Arrays and elements can be fixed-length as well. The following is a three-dimensional array where all dimensions are fixed-length: +数组和元素尽量长度固定。下面的是一个所有维度都固定的三维数组: ) --- - int[2][3][4] array; // 2 columns, 3 rows, 4 pages + int[2][3][4] array; // 2 列,3 行,4 页 --- $(P -The definition above can be seen as $(I four pages of three rows of two columns of integers). As an example, such an array can be used to represent a 4-story building in an adventure game, each story consisting of 2x3=6 rooms. +上面的定义可以看作是 $(I 四页三行两列的整数)。例如,在冒险游戏中这种数组可以用来表示一个4 层建筑物,每层由 2x3=6 个房间组成。 ) $(P -For example, the number of items in the first room of the second floor can be incremented like the following: +例如,第二层第一室的项目数可以像下面这样增长: ) --- - // The index of the second floor is 1, and the first room - // of that floor is accessed by [0][0] + // 第二层的索引是 1,该层 + // 第一个房间通过 [0][0] 来访问 ++itemCounts[1][0][0]; --- $(P -In addition to the syntax above, the $(C new) expression can also be used to create a $(I slice of slices). The following example uses only two dimensions: +除了上述语法, $(C new) 表达式也能用来创建 $(I 切片的切片)。下面是只使用两个维度的例子: ) --- @@ -757,43 +757,43 @@ void main() { --- $(P -The $(C new) expression above creates 2 slices containing 3 elements each and returns a slice that provides access to those slices and elements. The output: +上面的 $(C new) 表达式创建了一个包含 2 个切片、每个切片含有 3 个元素的切片,该切片可以访问它们以及内部的元素。输出: ) $(SHELL [[0, 0, 0], [0, 0, 0]] ) -$(H5 Summary) +$(H5 摘要) $(UL $(LI -Fixed-length arrays own their elements; slices provide access to elements that don't belong exclusively to them. +定长数组拥有自己的元素;切片提供对不专属于它们的元素的访问。 ) $(LI -Within the $(C []) operator, $(C $) is the equivalent of $(C $(I array_name).length). +在 $(C []) 运算符内部,$(C $) 与 $(C $(I 数组名称).length) 等价。 ) $(LI -$(C .dup) makes a new array that consists of the copies of the elements of an existing array. +$(C .dup) 由一个现有数组元素的副本生成一个新的数组。 ) $(LI -With fixed-length arrays, the assignment operation changes the values of elements; with slices, it makes the slices start providing access to other elements. +对于定长数组,赋值操作改变元素的值;对于切片,它让切片开始提供对别的元素的访问。 ) $(LI -Slices that get longer $(I may) stop sharing elements and start providing access to newly copied elements. $(C capacity) determines whether this will be the case. +变长的切片 $(I 可以) 停止元素的共享,并开始提供对新复制元素的访问。$(C capacity) 可以确定是否属于这种情况。 ) $(LI -The syntax $(C array[]) means $(I all elements of the array); the operation that is applied to it is applied to each element individually. +$(C array[]) 语法表示$(I 数组的所有元素);在它上面的操作可以单独应用到每个元素。 ) $(LI -Arrays of arrays are called multi-dimensional arrays. +数组的数组被称为多维数组。 ) ) @@ -801,7 +801,7 @@ Arrays of arrays are called multi-dimensional arrays. $(PROBLEM_TEK $(P -Iterate over the elements of an array of $(C double)s and halve the ones that are greater than 10. For example, given the following array: +迭代 $(C double) 类型数组的元素,并对大于 10 的元素作减半处理。例如,下面给出的数组: ) --- @@ -809,7 +809,7 @@ Iterate over the elements of an array of $(C double)s and halve the ones that ar --- $(P -Modify it as the following: +修改为下面这样: ) $(SHELL @@ -817,11 +817,11 @@ $(SHELL ) $(P -Although there are many solutions of this problem, try to use only the features of slices. You can start with a slice that provides access to all elements. Then you can shorten the slice from the beginning and always use the first element. +虽然这个问题有好多解决办法,但这儿尽量使用切片的特征。你可以从切片开始,它可以提供对所有元素的访问。然后你可以从数组的开始处缩短切片,并且总是使用第一个元素。 ) $(P -The following expression shortens the slice from the beginning: +下面的表达式从数组的开始处缩短了切片: ) --- @@ -831,8 +831,8 @@ The following expression shortens the slice from the beginning: ) Macros: - SUBTITLE=Slices and Other Array Features + SUBTITLE=数组和其它的数组特征 - DESCRIPTION=More features of D slices and arrays + DESCRIPTION=D 语言切片和数组的更多特征 - KEYWORDS=d programming language tutorial book arrays slices fixed-length dynamic + KEYWORDS=d 编程语言手册 数组 切片 定长 动态