编程C,C ++,Java,PHP,Ruby,图灵,VB
计算机科学加拿大 
编程C,C ++,Java,PHP,Ruby,图灵,VB  

用户名:   Password: 
 登记登记   
 [教程]数组
指数 -> 编程,图灵 -> 图灵教程
查看上一个主题 可打印的版本下载主题利率主题订阅本主题私人信息刷新页面 查看下一个主题
作者 信息
克莱顿




邮政发布: 2006年12月02日星期六下午2:36  帖子主题:[教程]数组

阵列


注意:通过本教程时,所有标题 红色的 是您应该做的问题,以便完全理解阵列的概念。在继续阅读教程之前完成它们。强烈建议您完成这些问题。解决方案将遵循以下 橘子 标题。除非你完全被困,否则请不要试图查看解决方案。

基础

问题1

写一个程序以获得15人的名字。在您获得了所有名称后,按照您获取的顺序显示所有名称。

解决方案

您得到的代码应该如下所示:

代码:

var. name1,name2,name3,name4,name5,name6,name7,name8,name9,name10,name11,name12,name13,name14,name15: string := ""

放"请输入名字" ..
获取name1.:*
放"请输入第二个名称" ..
获取名称2.:*
放"请输入第三个名称" ..
获取名称3.:*
放"请输入第四个名称" ..
获取名称4.:*
放"请输入第五个名称" ..
获取名称5.:*
放"请输入第六个名称" ..
获取名称6.:*
放"请输入第七个名称" ..
获取名称7.:*
放"请输入eigth名称" ..
获取名称8.:*
放"请输入第九个名称" ..
获取名称9.:*
放"请输入第十个名称" ..
获取名称10.:*
放"请输入第十一名称" ..
获取姓名11.:*
放"请输入第十一名称" ..
获取名称12.:*
放"请输入第十三个名称" ..
获取名称13.:*
放"请输入第十四个名称" ..
获取名称14.:*
放"请输入姓氏" ..
获取姓名15.:*
放"你输入的名字是: "
放name1
放name2
放name3
放name4
放name5
放name6
放name7
放name8
放name9
放name10
放name11
放name12
放name13
放name14
放name15


哇!这花了很长时间才写,除了对我们的一些名字反动,我们甚至没有为我们做任何事情。无论哪种方式,你都要思考,“有更好的方式!”没有恐惧,有!

什么是数组?
数组是相同类型的线性集合。换句话说,它的一组变量由相同的名称引用,但每个值都有一个唯一的 指数。 “但是什么是IDEX?”。好吧,让我向您展示一个数组的示例:

代码:

var. my_array.:数组0 .. 14字符串


Whaaaaaaa!?!?!

别担心,它真的不像看起来那么困难。让我们一分起。

代码:

var. my_array.


简单真的,我们现在创建了一种名为“my_array”的某种变量。

代码:

:数组0 .. 14字符串


这是阵列的肉。发生了什么是变量 my_array.. 被键入为数组,其中15个元素(0是元素,加上另一个14),并且该阵列的所有元素都是类型的 细绳.

什么是一个元素?

将一个阵列想象为一行中的一堆框。每个框都可以保持一个值,然后我们可以通过使用其索引参考(“框号”,如果您愿意)并使用它就像普通变量一样访问此值。

很棒,我如何使用数组?

真的很简单。声明您的数组后,您可以使用其他变量独立使用其所有元素。前任:

代码:

var. my_array.: array 0 .. 4 of int

my_array..(3) := 5
放my_array(3)


相当漂亮的呃?括号中的数字是您要访问的元素的索引。只需用一个响应该元素 整数,没有别的,否则就会生气。

索引您的阵列

在图灵中,阵列不是自动零索引;也就是说,任何阵列的索引都不会默认开始为零,就像它在其他语言(如C ++)中一样。声明您的数组时,您将设置较低和上限(换句话说,您设置了第一个框的索引,并为最后一个框设置索引,也可以在创建之间创建的所有框)。据说,以下是完全合法的:

代码:

var. my_array.:阵列54 .. 56的int


然而,除非有充分的理由这样做,否则通常会劝阻这样的事情。通常,您的阵列应以0或1.开始,从1开始直观,因为当我们谈论我们的数组中的第一个元素时,我们将其索引。当我们谈论第六个元素时,我们将其索引数字6.但是,使用0索引启动数组也是有用的。它可能看起来是反直观的,因为我们必须使用索引4访问数组的第五个元素。但是,从0开始的次数使得我们更容易的算术。

问题2.

修改问题1以便它使用数组而不是质量变量。

解决方案

代码:

var.名称:数组1 ..字符串15

为我: 1 .. upper(names)
    put "请输入名称编号", i ..
    get names(i) :*
结束

放"您输入的名称是: "

为我: 1 .. upper(names)
    put names(i)
结束


注意:如果您不确定循环,请访问 这里

哇!写的是多少?阵列不让你的生活更容易吗?

现在我在这里做了几个有趣的事情。首先,我已经通过变量整数恢复了数组中的一个元素(i 在我的循环中)。还记得我上面所说的关于引用数组,你需要的只是一个整数吗?整数变量仍然是一个整数。

其次,我用过这个功能 上()。它所做的是参数的数组(在这种情况下名称),并返回传递给它的数组的上限。这个功能伴随着(虽然我没有使用它) 降低(),返回阵列的下限。

具有用户定义的上限

声明您的数组时,您可以将整数变量替换为您的下限和上限的声明。例如:

代码:

Const Upper_bounds.: int := 6
var. my_array.:Array 1 .. Boolean的Upper_bounds


这里没有魔法。价值 Upper_bounds. 被替换为表达式以制作变量,我们得到了我们期望的:带有下限1和上限6的Boolean数组。

问题3.

从问题2修改您的程序,以便首先提示用户输入用户始终输入15个名称,而不是要求用户始终输入15个名称。

解决方案

代码:

var. upper_bounds.: int := 0

放"你想输入多少个名字?" ..
获得Upper_bounds.

var.名称:数组1 .. upper_bound的字符串

为我: 1 .. upper(names)
    put "请输入名称编号", i ..
    get names(i) :*
结束

放"您输入的名称是: "

为我: 1 .. upper(names)
    put names(i)
结束


对上一个程序只有略微修改;这次我们要求用户进入多少名称, 然后 我们声明了我们的阵列。然后我们最后一次继续它。

将数组传递为论据

所以现在你已经了解了阵列的基础;你应该对他们感到相得益彰。但是,如果出于某种原因,您必须将数组传递为函数或过程的参数?说,排序数据?您将一个参数声明为正常,它的类型为类型。

代码:

过程print_array.(arr :阵列1 .. 5的字符串)
    for i : lower (arr) .. upper (arr)
        put arr (i)
    end for
结束print_array.

下一行上的%使用新命令: init (short for initialize)。声明阵列后立即使用它。
在这种情况下,必须准确地给出%init。好像我们已经完成了'var num: int := 7'.
var.音乐家:阵列1 .. 5的字符串:= init ("Al Stewart", "Mark Knopfler", "B.B. King", "詹姆斯队长吉尔克船长", "Roger Waters")
print_array..(musicians)

这是有效的。
输出写道:

斯图尔特
马克·诺弗勒
B.B.国王
詹姆斯队长吉尔克船长
罗杰沃特


但是,这个程序, print_array.,高度专业化。它打印一系列恰好5个元素。不仅如此,下限必须是1,上限必须为5.如果我们给它一个5个元素阵列的字符串,从索引0开始,它会做什么?它将输出数组中的最后四个名称,然后给出错误,因为我们正在尝试在索引5处访问元素,但没有。

我们可以概括这一点。我们可以修改我们的程序,以便它需要一个未知长度的数组。为此,在向我们的过程中声明参数时,我们将使用星号(*)替换上限(以前5)。

代码:

过程print_array.(arr :数组1 .. *字符串)
    for i : 1 .. upper (arr)
        put arr (i)
    end for
结束print_array.

%现在我们可以给它一个长度的数组:
var.征服者:数组1 .. 3的字符串:= init ("Ghengis Kahn", "George W. Bush", "Agamemnon")
print_array..(conquerors)
var.诗人:数组1 .. 6字符串:= init ("Robert Frost", "John McCrae", "Lewis Caroll", "Percy Shelly", "Robert W. Service", "Carl Sandburg")
print_array..(poets)

这是有效的。

这是一个重要的例子:排序。我们将看的算法称为插入排序。我们将编写一个参加数组的过程并修改它,以便对其进行排序。这是代码(从Zylum的排序主题取出,可以找到 这里):

代码:

程序转移(var list :数组1 .. * int,i,j: int)
    const temp := list (j)
    for decreasing k : j .. i + 1
        list (k) := list (k - 1)
    end for
    list (i) := temp
结束班次

程序插入(var list : array 1 .. * of int)
    for j : 2 .. upper (list)
        var i := 1
        loop
           当i = j或列表时退出(i) >= list (j)
            i += 1
        end loop
        shift (list, i, j)
    end for
easherionsort.

var. nums.:阵列1 .. 10的int

为我: 1 .. upper (nums)
    nums (i) := Rand.Int (1, 100)
    put nums (i)
结束

放""

插入(nums)

为我: 1 .. upper (nums)
    put nums (i)
结束


代码相当复杂。给它一个好的外观,试图了解它的工作原理,但如果你不遵循它,不要太过分。有足够的时间来稍后学习排序算法。


从函数返回数组

如果您有一个数组,要在每个元素上应用特定功能(因为简单起见,我们会说我们想向数组的每个元素添加1个元素)吗?您可以做的一件事是使用一个过程并修改阵列的内容,但这不是良好的编码实践。相反,我们应该创建一个函数,该函数在数组的每个元素上应用函数,并返回一个新数组。但是,在图灵中有一个限制,只是允许您从函数返回数组 在编译时具有已知范围。 换句话说,您只能从函数返回静态数组。

代码:

函数add_one.(num : int)
    result num + 1
结束add_one.

函数apply_add_one.(items : array 1 .. 5 of int) : array 1 .. 5 of int
    var nums : array 1 .. 5 of int
    for i : 1 .. 5
        nums (i) := add_one (items (i))
    end for
    result nums
结束Apply_add_one.

var.数字:阵列1 .. 5的int:= init (1, 2, 3, 4, 5)

为我: 1 .. 5
    put numbers (i)
结束

放skip

数字:= apply_add_one (numbers)

为我: 1 .. 5
    put numbers (i)
结束


这种行为也向我们展示了其他内容:数组是一个第一类值,就像整数或字符串一样。我们知道这一点,因为我们能够将阵列传递为值并将它们从函数返回,就像我们的字符串或整数一样。

请记住,当您从函数返回数组时,您必须返回a 静态的 array.

第1节结束
赞助
赞助
赞助
赞助
沉默的复仇者




邮政发布: 2006年12月02日星期六下午3:46  帖子主题:(没有主题)

非常好的教程怪手,好工作!
克莱顿




邮政发布: 2006年12月11日星期一:下午9:47  帖子主题:(没有主题)

Part 2



多维阵列


问题4.
让用户输入5个人的名称以及他们的昵称。

解决方案
图灵:

var. 名称 : arr...ay 1 .. 5 细绳
var. 昵称 : arr...ay 1 .. (名称) 细绳
为了 i : 1 .. 5
    “请输入你的名字”
    得到 名称 (i) :*
    “请输入您的昵称”
    得到 昵称 (i) :*
结尾 为了

为了 i : 1 .. 5
    名称 (i), "    ", 昵称 (i)
结尾 为了


多什么?

实质上,多维数组是一系列数组。

什么?

是的,数组数组。从第1部分采取我们的示例,ressay是一系列框。然而,多维数组(更具体地用于二维阵列),更像是矩阵(具有行和列的网格)。它以实际情况实际上具有行和列,它是reclyge。

例时间!

图灵:

var. my2darray : arr...ay 1 .. 5 arr...ay 1 .. 5


花哨呃?因此,多维数组实际上是数组数组。你怎么称呼你说这么野兽的元素?简单!

图灵:

my2darray (1)(1)


现在,那种调用阵容的方式是艰苦的 - 谁想用那么多括号?我知道我没有。因此,图灵有一个方便的小功能。关于:

图灵:

var. my2darray : arr...ay 1 .. 5, 1 .. 5

my2darray (1,1)


这里没有太大的变化,眼睛只有有点易于更容易。请记住,您声明的第一个界限是您的“行”和第二个“列”。

问题5.
修改问题4以便它使用2D阵列而不是并行阵列来获取用户名和昵称(此时假设它们有3个)。

解决方案
图灵:

var. nicks_and_names. : arr...ay 1 .. 5, 1 .. 4 细绳

为了 i : 1 .. 5
    “请输入你的名字”
    得到 nicks_and_names. (一世,1)
    为了 j : 2 .. 4
        “请输入昵称”, j
        得到 nicks_and_names. (我,J.)
    结尾 为了
结尾 为了

为了 i : 1 .. 5
    nicks_and_names. (一世, 1)
    为了 i : 2 .. 4
        nicks_and_names. (我,J.)
    结尾 为了
    跳过
结尾 为了


多维数组eh更容易?

只要记住,一个数组可以像你所想要的那样多的尺寸,尺寸的增加很容易添加,如果有任何疑问,请在[图灵帮助]中发布它们,我相信有人会很高兴回答你的问题。
塞万提斯




邮政发布: 2006年12月11日10:26 PM  帖子主题:(没有主题)

您为多维阵列提供的示例更适合使用记录的线性阵列:
代码:

人民: array 1 .. 10 of
    record
        name : string
        nicknames :数组1 .. 3的字符串
    end record


我认为更合适的例子是为棋盘游戏创建网格,或者是这样的。

此外,如果您将作为阵列数组推出多维阵列,为什么不解释这完全是合法的,因为以下论点:
数组只是值列表。阵列本身是一个值。因此,阵列可以是阵列列表。然后我们得到以下语法:
代码:

var. arr.:数组1 .. 5的阵列1 .. 3的int
arr....(4) (2) := 19

更常见的语法,
代码:
var. arr.:阵列1 .. 5,1 .. 3的int
arr....(4, 2) := 19

是第一个的简单句法糖。

但这看起来很好。你打算有多少份?
克莱顿




邮政发布: 2006年12月11日星期一10:34 PM  帖子主题:(没有主题)

我有点打算有3个部分(我不记得我要写的第3部分 使困惑, 有什么建议?)

我正在考虑做一个游戏的网格,但我不想把图形带入这个,所以我把它置于名字(是的,我意识到的记录是我写这篇文章时的方式,但我为所有意图和目的设计,这将是现在的,但我想我现在可以改变它,或者现在制作第3部分。

我也将在您的积分中添加关于2D阵列合法的为什么(与您提供的参数)

感谢您的反馈!
塞万提斯




邮政发布: 2006年12月11日星期一10:45 PM  帖子主题:(没有主题)

您不需要引入重型图形。只是在文字中做到这一点!

在里面 练演练,我们在进入阵列时学习了子程序,所以我们可以编写子程序来保持代码,以便为此相当轻松和可理解。对于教程材料来说不要太难。

阵列的第3部分可能是灵活的数组。 微笑 如果您愿意,您欢迎清理我的教程。
克莱顿




邮政发布: 2006年12月11日星期一10:46 PM  帖子主题:(没有主题)

好吧,我喜欢那种声音,那样,所有的阵列都在一个教程中(虽然,你可能必须重新排列帖子以使它们在一起)。此外,对于文本,我可以说,制作棋盘,然后让它们输出颜色数字(只是确保他们拥有它)或类似的东西?
塞万提斯




邮政发布: 2006年12月11日星期一11:08 PM  帖子主题:(没有主题)

这将是一个非常容易的例子。我建议做两个例子。这可能是第一个。也许第二个可以是塞尔达等瓷砖视频游戏的基础。 2D阵列的每个元素都是一个整数:0对于草,树为1,2为岩石......然后有一系列人;每个都需要一个x和y坐标。嗯,这真的需要记录。也许记录应该只是在阵列之前去 练演练。想法?这就是在我的方案中教授的方式:在列表之前教了结构。它运作良好。
赞助
赞助
赞助
赞助
WTD.




邮政发布: 2006年12月11日11:10 PM  帖子主题:(没有主题)

听起来不错。
克莱顿




邮政发布: 2006年12月11日11:11 PM  帖子主题:(没有主题)

我认为记录真的应该在阵列之前去。事实是,如果您在阵列中需要多于单个维度,那么您应该随时随地使用记录。然后,我们也可以在教程中工作。
[Gandalf]




邮政发布: 2006年12月12日星期二上午9:18  帖子主题:(没有主题)

并不真地。同样,在网格的示例中,假设你正在制作一个棋盘......是什么更有意义,一个8×8个正方形,或8行/列的数组长度是8个正方形的?

此外,良好的工作在教程中,但颜色通常可以使用一些改进,并且一些额外使用粗体/更大的字体标签将是漂亮的。 (这几天这些丑陋的彩虹彩色教程是什么?人们试图模仿塞万提斯',只做它非常错误?) 使困惑

*编辑*在我写这个时一定很累......这是一个8x8网格而不是10x10。
塞万提斯




邮政发布: 2006年12月12日星期二上午9:45  帖子主题:(没有主题)

弗雷克曼写道:
事实是,如果您在阵列中需要多于单个维度,那么您应该随时随地使用记录。

正如Gandalf所说,没有。拿棋盘。使用您的建议,我们将其代表为一系列记录:
代码:

var.棋盘: array 1 .. 8 of
    record
       Spot1,Spot2,Spot3,Spot4,Spot5,Spot6,Spot7,Spot8: int
    end record

这也可能是
代码:

var.棋盘: array 1 .. 8 of
    record
        spots : array 1 .. 8 of int
    end record

基本上是
代码:

var.棋盘:阵列1 .. 8的阵列1 .. 8的int

因为记录只有一个字段。
克莱顿




邮政发布: 2006年12月30日星期六晚上9:02  帖子主题:(没有主题)

第三部分


灵活的阵列


灵活的?

所以你现在知道一个数组是什么,如何与之合作,以及他们能做什么。但是,你知道阵列是否会变得更好?好吧,他们可以。我们已经使用的阵列的问题是它们是静态的 - 它们总是更加粗糙相同的大小。为什么这可能是一个问题,你问?因为你从来没有真正知道用户进入多少名字,或者屏幕上当前有多少个项目。

所以,当你到达Nitty GriTy时: 灵活的数组是具有动态上限的数组。

我如何使用一个?

优秀的问题。灵活阵列的声明相当简单:

代码:

var. foo:灵活的阵列下限。


相当简单的权利?您的变量名称是一个灵活的数组,从较低到上部(这两个整数),都是类型的类型。现在关于灵活阵列非常有趣的事情是他们能够具有小于下限的上限。现在这可能听起来不像它是有道理的,但它确实如此。考虑以下示例:

图灵:

var. 酒吧 : 灵活的 arr...ay 1 .. 0


现在可能看起来很奇怪,但这一切都意味着当前阵列中有零元素。就像它一样,没有信息才能填充该阵列。

等等,你说我可以改变上限!

你可以,使用 新的 关键词。只需引用您的灵活数组,您要更改您想要的新上限的上限。举一个例子:

图灵:

var.Foo : 灵活的 arr...ay 1 .. 0
新的Foo, 5


运行后,您将创建(在开始时)一个名为foo的数组,其中包含零元素。下一行将采用阵列foo,并将其重新分配为包含5个元素。真的很简单。您可以尽可能多地进行更改,但是,您可以确定上限,确保您永远不会尝试使上限小于下限的下方。

现在这是如何帮助我的?

灵活的阵列非常有用。在长期以来,你会发现自己一直在使用它们。这是一个例子。从文件中获取输入信息;到目前为止,您必须确切地知道您的文件中有多少行,以便您可以将其读入数组。你不需要知道更多!现在,您可以使用您了解灵活的数组,Upper()函数,以及循环来解决您的问题(如果您不确定文件I / O,请不要担心文件的东西,只需专注于代码本身)。

图灵:

var. file_contents. : 灵活的 arr...ay 1 .. 0 细绳
var. 溪流 :
打开 : 溪流, “foo.txt”, 得到
环形
    出口 什么时候 EOF. (溪流)
    新的 file_contents, (file_contents.) + 1
    得到 : Stream,file_contents. ( (file_contents.))
结尾 环形


这里相当简单。我们声明了一个灵活的数组来保存所有文件的内容。然后我们打开文件并输入循环。如果我们不是在文件的末尾,那么我们向我们的数组添加一个新元素(通过拍摄当前的上限并向它添加一个;这是一个具有灵活阵列的常见的东西)并获得文件内容线。

柔性阵列的另一个用途采用射击游戏,您必须处理多个子弹。您有一个记录来保存所有子弹的信息(例如x和y坐标,速度等),并创建一个灵活的该类型。请记住,任何类型,无论是创建它,还是预定义,都可以分配给灵活的数组。所以看看这个例子看我的意思:

图灵:

const b_start_x. := maxx. div 2
const b_start_x_vel. := 5
var. 钥匙 : arr...ay char 布尔基
var.子弹 : 灵活的 arr...ay 1 .. 0
    记录 :
        x :
        x_vel :
    结尾 记录

环形
    Input.keydown. (钥匙)
    如果 钥匙 (key_enter.) 然后
        新的子弹, (子弹) + 1
        bullets ( (子弹))。X := b_start_x
        bullets ( (子弹))。X _vel. := b_start_x_vel
    结尾 如果
    为了 i : 1 .. (子弹)
        如果子弹 (i)。X >= maxx. 然后
            %在这里摆脱子弹。如何在第四部分讨论这一点
        别的
            %移动子弹
            bullets (i)。X +=子弹 (i)。X _vel.
        结尾 如果
    结尾 为了
结尾 为了


本教程的下一部分由塞万提斯撰写,因为我相信他可以比我能更好地解释它:

多维灵活阵列

图灵有时会告诉你,“复杂的多维灵活阵列重新分配不实现 - 抱歉。”
斗牛* t!与流行的信仰相反,我们 能够 更改多维灵活阵列的上限。但是,有局限性。
我正在使用图灵4.0.5,所以我所说的一切都仅对这个版本有效。我要说的话 可能 不适用于您的特定版本的图灵。你必须为自己尝试一下。
因此,要更改多维灵活阵列的上限,似乎我们首先要么 将至少一个维度的上限设置为零或单独留下其中一个尺寸。让我们有一些代码:
代码:

var. a:灵活的数组1 .. 2,1 .. 3的int
放upper (a, 1)
放upper (a, 2)
放"---"
新A,0,3
放upper (a, 1)
放upper (a, 2)
放"---"
新的A,1,5
放upper (a, 1)
放upper (a, 2)
放"---"
新的A,15,0
放upper (a, 1)
放upper (a, 2)
放"---"

这都是有效的,倾向于倾向的代码(再次,4.0.5,不一定是先前的版本)。让我们试着离开一个维度,因为它在改变另一个时:
代码:

var. a:灵活的数组1 .. 2,1 .. 3的int
放upper (a, 1)
放upper (a, 2)
放"---"
新的A,1,3
放upper (a, 1)
放upper (a, 2)
放"---"
新的A,1,6
放upper (a, 1)
放upper (a, 2)
放"---"

其中的一部分工作。只要我们单独离开其他维度,我们可以改变第一维度,但不是第二个维度。如果您必须更改两个维度,则有一个环形交叉路口方法:
Bacchus写道:

有一点偶然,占用了一些空间。只需创建一个新的数组(不必是灵活的)并存储原始阵列,然后将维度更改为0并在恢复原始数组的值之前返回到您想要的内容。


现在,让我们尝试3个维度。
代码:

var. a:灵活的数组1 .. 2,1 .. 3,1。4。int
放upper (a, 1)
放upper (a, 2)
放upper (a, 3)
放"---"
新的A,10,0,9
放upper (a, 1)
放upper (a, 2)
放upper (a, 3)
放"---"
新的A,10,8,9
放upper (a, 1)
放upper (a, 2)
放upper (a, 3)
放"---"

这也有效。所以,让我们在这里进行一些规则。

  • 您可以将任何高界更改为0到x,或从x到0更改。
  • 如果将一个上限更改为零,则可以使用其他上限进行任何您想要的。
  • 在2D阵列中,如果您单独留下第二个上限,则可以更改第一个上限。


结论:

所以本教程的第二部分。本节介绍了阵列的主题,其上限为灵活。这种新的力量具有很大的潜力。我们正在朝着操纵动态的数据,而不是静态。动态数据是我们在现实世界中遇到的。

第三部分结束
克莱顿




邮政发布: 2006年12月30日10:32 PM  帖子主题:(没有主题)

第四部分


从灵活的数组中删除元素

您可以从第III部分知道,通过将该数组重新分配,您可以简单地从数组中删除最后一个元素 新的 关键字,并提供低于当前的新绑定。但是,如果您不想删除最后一个元素,该怎么办?如果你想删除,哦,说,7个元数组中的第三个元素?最简单的方法是将第7(最后)元素的值复制到第3个位置。它看起来像这样:

图灵:

%创建数组并用随机数填充它
var.Foo : 灵活的 arr...ay 1 .. 0
为了 i : 1 .. 7
    新的Foo, (Foo) + 1
    foo (i) := 兰德 (1, 100)
结尾 为了

%删除第3元件:
Foo (3) :=Foo ( (Foo))
新的Foo, (Foo) - 1


请注意,如果您不关心存储在数组中的信息的顺序,则应仅使用此方法,因为它 将要 得到 screwed up.

如果你不关心订单怎么办?如果您需要按字母顺序保留所有内容,那么您需要正确地将所有元素保持在一起。这个不是那么简单。我们需要将所有元素占据第三个以上并将其移至一个位置 然后 我们可以降低上限。我们如何这样做? (注意我为简单缘故使用整数,但字符串和字母顺序也是如此:

图灵:

%创建一个数组并用数字1到7填充它
var.Foo : 灵活的 arr...ay 1 .. 0
为了 i : 1 .. 7
    新的Foo, i
    foo (i) := i
结尾 为了


var. exporte_to_be_removed. : := 0
“请输入要删除的元素: (1 - 7)"
得到 exporte_to_be_removed.

为了 i : exporte_to_be_removed. .. (Foo) - 1
    foo (i) :=Foo (我+ 1)
结尾 为了

新的Foo, (Foo) - 1


所以让我们走过这一点,以确保你得到它。第一部分是简单的:声明灵活的阵列foo并分配七个元素中的每一个值1,2,3,...,7.接下来我要求用户在1到7之间输入一个元素,是删除了。最后一个循环是一切都掉下来的地方。我们从要删除的元素开始,并将我们的方式转到第二个最后一个元素。在for循环中(在第一次迭代)中,我们要删除的元素将由其上方的元素写入。这一切都达到第二个最后一个元素(使旧的最后一个元素成为第二个最后一个元素),然后我们退出for循环并缩小一个元素,导致元素的删除。

从For循环中的数组中删除元素:

如果我们通过我们的数组迭代,检查是否需要删除元素时检查条件?借用射击游戏的例子。我们有一个灵活的子弹数组。在我们的主循环中,我们必须迭代符合子弹检查碰撞的阵列。如果有碰撞,我们必须从我们的阵列中删除该子弹。所以我们在循环中迭代到1到我们数组的上限,我们发现我们需要删除第二个元素。如果我们只做我们上面所做的事,那么在第二个元素被删除后,我们的数组将是一个元素较小。但是,有一个问题。 for循环仍将迭代到旧的上限,而不是新的上限。这是因为循环特殊形式在执行开始时评估其“Arguments”一次。因此,如果我们从我们的阵列中删除一个元素,则for循环最终将到达旧的上限,这是一个大于新的上限,所以我们会收到一个错误。

这个问题有几个解决方案。在删除元素后,最简单的只是退出for循环。但是,这是一个不满意的,因为它意味着,即使应该删除两个或多个元素,也可以在主循环的每个迭代中删除一个元素。这可能不是问题,或者可能是一个巨大的问题。

缺陷的尝试

这是一个可能的解决方案。这里的想法是,我们跟踪我们要删除的元素数量。这存储在 number_to_remove.。正如我们遍历我们的阵列,如果我们找到要删除的元素,请将其上方的元素移至一个(正如我们上面所做的那样)和才能 number_to_remove.。但是,在退出此循环之后,我们不会缩小数组。这是代码:
图灵:

var. number_to_remove. : := 0
var. 数字 : 灵活的 arr...ay 1 .. 20
为了 i : 1 .. 20
    numbers (i) := i
结尾 为了

%删除所有倍数4
为了 i : 1 .. (数字)
    如果 数字 (i) 摩擦 4 = 0 然后
        number_to_remove += 1
        为了 j : i .. (数字) - number_to_remove
            numbers (j) := 数字 (J + 1)
        结尾 为了
    结尾 如果
结尾 为了

新的 数字, (数字) - number_to_remove
为了 i : 1 .. (数字)
    数字 (i)
结尾 为了


这似乎有效。但是,如果代替删除所有倍数4,我们想删除所有倍数4和5?相反,我们将使用以下代码:
图灵:

var. number_to_remove. : := 0
var. 数字 : 灵活的 arr...ay 1 .. 20
为了 i : 1 .. 20
    numbers (i) := i
结尾 为了

%删除所有倍数4
为了 i : 1 .. (数字)
    如果 数字 (i) 摩擦 4 = 0 或者 数字 (i) 摩擦 5 = 0 然后
        number_to_remove += 1
        为了 j : i .. (数字) - number_to_remove
            numbers (j) := 数字 (J + 1)
        结尾 为了
    结尾 如果
结尾 为了

新的 数字, (数字) - number_to_remove
为了 i : 1 .. (数字)
    数字 (i)
结尾 为了

输出写道:

1
2
3
5
6
7
9
11
13

有两个问题。第一个是列表中的5。发生了,因为当我们删除4时,我们将5,6,7,......按一个位置移位。所以现在5是第四个元素。我们的循环已经过了第四个元素。这是4.所以现在它移动到第五个元素,现在是6.我们完全跳过5!第二个问题是,我们以某种方式删除了14,17,18和19,但这都不是4或5的倍数。要了解这一点,让我们来看看我们在我们发布之前的数组看起来像什么 新的 command:
我们的数组写道:

1
2
3
5
6
7
9
11
13
14
16
17
18
19
20
20
20
20
20
20

您还注意到,出于与未删除的原因相同的原因,1未被删除。 16之后,在15之后立即是5的倍数。
现在,在最后看看所有20岁?他们在那里有意义吗?当我们向下转移元素时,我们单独留下顶部。结果,重复顶部元素20。然而,我们的循环迭代到第20个元素。一旦它到达该块20的块,它认为它需要删除该元素。实际上,我们不关心该元素,因为当我们发出时将被删除 新的 命令。然而,20是4和5的倍数,因此我们的If语句的条件是真的。这引起 number_to_remove. 被递增。这就是为什么我们的阵列结束了这么快,它应该有:13而不是19。

正如您可以清楚地看到的那样,这种方法存在很多问题。然而,描述这种失败的方法不是浪费时间。了解这些陷阱很重要。它们不是那种容易识别的错误,他们采取了相当多的工作要理解 为什么 错误正在发生。

工作方法

第二种方法我们将尝试使用另一个灵活的数组来存储我们要删除的元素的缩义。我们会看到这种方法有效。我会介绍代码并在讨厌它之后丢失。

图灵:

var. 数字 : 灵活的 arr...ay 1 .. 0
var.indeces_to_remove... : 灵活的 arr...ay 0 .。 - 1

为了 i : 1 .. 20
    新的 数字, (数字) + 1
    numbers (i) := i
结尾 为了

为了 i : 1 .. (数字)
    如果 数字 (i) 摩擦 4 = 0 或者 数字 (i) 摩擦 5 = 0 然后
        新的indeces_to_remove.., (indeces_to_remove..) + 1
        indeces_to_remove ( (indeces_to_remove..)) := 一世 - (indeces_to_remove..)
    结尾 如果
结尾 为了

%取消注释以下行,以帮助了解这是如何工作的
%为我: 1 .. upper (indeces_to_remove)
%   放在indeces_to_remove.(i)
%结束
%放"---"

为了 i : 0 .. (indeces_to_remove..)
    为了 j :indeces_to_remove... (i) .. (数字) - 1
        numbers (j) := 数字 (J + 1)
    结尾 为了
    新的 数字, (数字) - 1
结尾 为了

为了 i : 1 .. (数字)
    数字 (i)
结尾 为了


要注意的一件事是我使用0来缩小 indeces_to_remove..。它让事情变得更容易。如果我已经开始了1,我就必须在某些地方减去1。
你也会注意到我骗了你,一点点。我说我们将使用一个数组来存储我们要删除的元素的义级。但是,我已经使用了一个数组来存储我们想要删除的元素,并完成一些额外的差异。每次找到一个元素(在位置 i)我想删除,我为我的新元素添加了一个新的元素 indeces_to_remove.. 阵列和推动 I - Upper(indeces_to_remove 在那里。减法的原因将在后面变得明显。

下一步是删除元素 indeces_to_remove.. 指导我们。我们以通常的方式执行此操作,通过向下移动元素并删除顶部元素。现在让我们考虑如果我没有在上段中提到的那么重要的减法,请考虑会发生什么。要删除的第一个元素是4,在索引4.我按下一个位置以上的所有位置,所以现在我的数组如下所示:[1,2,3,5,6,7,8,9,10,图11,12,13,14,15,16,17,18,19,20,20]。然后我删除顶部元素。接下来,我指示删除第五个元素。与以前相对应的元素5,但现在,看!第五个元素是6!我删除它,获取我的新阵列:[1,2,3,5,7,8,9,10,11,12,13,14,15,16,17,18,19,20,20]。而且,我切断了顶部元素。接下来,我指示删除元素,该元素从头到尾8.然而,现在,它对应于值10!我在这里幸运了,因为10实际上是我想要删除的东西。但是,它仍然是一个问题,因为后来我会被要求删除第十个元素。

因此,减法的原因是纠正这个问题。每次我们都删除像这样的元素 indeces_to_remove.. 指导我们,我们将数组转移一个。因此,当我们去除我们要删除的第二个元素时,它是 实际上 发现一个低于最初的指数!当我们去除我们要删除的第二个元素时,它是 实际上 发现在索引 低于原来!因此,通过执行减法,我已经预先计划了这种情况的灾害并发症。

同样,这可能看起来很复杂,但了解这些怪癖是可怕的。写一个好的程序并在其中有一个缺陷是非常痛苦的,这需要几个小时才能找到。我们在这里捕获的错误是可能导致大毛发磨损和齿磨的错误。

结论:
您现在已经学习了如何处理动态数据以及如何处理,操作和删除动态阵列的这些数据。当您编写代码时,请记住这些内容,并尽可能多地应用。你可以制作一个程序的动力越多,它就会越好。写一个概括,这总是一件好事, 动态的 程序并看到它处理各种情况,其中一些情况甚至可能甚至无法深入考虑。

第四部分和教程结束
从上一个显示帖子:   
   指数 -> 编程,图灵 -> 图灵教程
查看上一个主题 告诉一个朋友可打印的版本下载主题利率主题订阅本主题私人信息刷新页面 查看下一个主题

11  [ 14 Posts ]
跳到:   


Style:  
搜索: