转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 软件开发 >> Delphi程序 >> 正文
Delphi之数组         ★★★★

Delphi之数组

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1295 更新时间:2009/4/23 18:39:22

Delphi之数组
     Object Pascal中可以建立丰富的数据类型。数组毫无疑问也是众多自定义数据类型中的一种。
     Type
       TA = array[0..9] of Integer;
     ...
     var
       A : TA;
     和下面这段代码通常效果是相同的(不同的地方在类型篇再说)
     var
       A : Array [0..9] of Integer;
     这相当于C中的
     int A[10];
     或Basic中的
     Dim A(9) as Long或 Dim A(0 to 9) as Long
下面将分几个方面讲OP的数组:
多维数组:
     多维数组的本质其实就是数组之数组。   
     type
      TA = array[0..9] of array [0..9] of Integer;
      TB = array[0..9, 0..9] of Integer;
      TCA = array[0..9] of Integer;
      TC = array[0..9] of TCA;
     在这里TA,TB,TC是等价的。在使用时是没有分别的。例如X[0][0]:=1;Tx[0,0]:=1;(X是TA、TB、TC类型)
     都是合法的。因为这几种类型都是在内存中开辟一块100x100xSizeOf(Integer)的区域,你根本无法区
     分他是如何申请的,也没有必要去区分。
     多维数组如何取得维数呢?
     前面已经说过多维数组就是数组之数组,所以可以利用下面的方法来取得多维数组的维数:
      var
        k:array[2..10,3..20]of integer;
      begin
       showmessage(Inttostr(Low(k))+''''   ''''+Inttostr(High(k)));
       showmessage(Inttostr(Low(k[Low(K)]))+''''   ''''+Inttostr(High(k[Low(K)])));//k[n]是array[3..20] of integer;的数组

      end;
动态数组:
     OP中动态数组的声明是
       type
         TA=Array of Integer;
     动态数组应用中十分广泛。现在有一种趋势就是在数据结构中用动态数组代替链表
     (到底哪个好哪个坏自有评价我们在这里不予以讨论)。
     可能你会说动态数组根本不必要使用,我就从来没有用过。 我不信你没有用过动态数组!
     String类型你用过吧,它近似可以说是动态数组的一种。
     动态数组的内存是在使用分配长度时才予以分配的,他的下界只能0(AnsiString字符串例外,下界是1,原因后面再说),
     动态数组的生存期是自管理的使用后一般不用释放,如果要强行释放就用把Nil附给他。
     使用动态数组往往爱犯的错误:
     1)和静态数组概念混淆:
     动态数组的地址并不是他第一个元素的地址,而在静态数组中我们大家常常使用这样的语句:
     var
       A, B : array[0..19] of Integer;
     ... 
     CopyMemory(@A, @B, 20*SizeOf(Integer));
   或者CopyMemory(@A[0], @B[0], 20*SizeOf(Integer));
   都是正确的,因为静态数组中数组的首地址就是他第一个元素的地址。

     但是在动态数组中只有第二种写法会得到正确结果。即只能写成:
     var
       A, B : array of Integer;
     ... 
     SetLength(A, 20);
     SetLength(B, 20);
     CopyMemory(@A[0], @B[0], 20*SizeOf(Integer));    
     2)数组的附值:
     静态数组中的附值很简单
     var
       A, B : array[0..19] of Integer;
     ...
     A := B;
     即可对数组进行赋值;在动态数组中就要倍加小心,请看
     var
       A, B: array of Integer;
     begin
       Setlength(A, 10);
       SetLength(B, 10);
       B[1] := 50;
       A := B;
       B[1] := 100;        
     end; 
     a[1]是多少呢?按照常理A[1]的值应该是附值前的50,但恰恰相反A[1]的值是附值后B[1]再次被赋的值,
     100动态数组中A := B;仅仅是将动态数组A 的指针指向动态数组B,而并不是像我们希望的那样为A开辟一
     块空间。如果非要为A开辟一块空间就要用Copy来复制B的数据。
     AnsiString也是动态数组,所以同样的情况也存在于String类型。
特殊的数组:
     本来字符串想单独说一说,但是却因为它具有太多的动态数组特性所以不单独说了。
     再一个,这里的代码和说的以后你很可能是用不到的,但是能加深你对ObjectPascal的理解。
     在设计时你会知道它是如何工作的,通过这些你会更有效率的使用它。
     大多数字符串与其说是数组倒不如说他是个结构。但是我们用他的数组特性更多一些。
     1.ShorString:是为了与老的Pascal兼容而保留的类型。最大255个字符。
       Type
         TShortString
           Length:Byte;
           Data:array[1..Length] of Char;
         end;
     从结构上可以看出ShortString最大只能保存255个字符。我们可以做个实验
       var
         k:ShortString;
       begin
         k:=''''I am a Delphi fan!'''';
         k[0]:=Char(13);//k.Length被置为13
         showmessage(k);
       end;
       ///两种方法效果相同
       var
         k:ShortString;
         p:^Byte;
       begin
         k:=''''I am a Delphi fan!'''';
         p:=@k[1];
         Dec(p,1);
         p^:=13;//k.Length被置为13
         showmessage(k);
       end;
      运行一下看看会出什么结果,呵呵。
      为什么Short的数组下限是0呢?想一想Byte和Char的关系我不想多说.
     2.AnsiString:标准的字符串,以Nil结尾。
       Type
        TAnsiString=record
           allocSiz: LongWord;//分配的大小
           ReferencCount:LongWord;       //引用次数
           Length:LongWord;         //字符串长度
           Data:array[1..(Length+1)] of AnsiChar;
        end;
       有人要问为什么长度是1..(Length+1)而不是Length呢?
       因为后面还要有一位NULL字符,表示结束。可见AnsiString和C\C++的兼容性也是很好的。
       如下代码:
       var
          k: AnsiString;
          p:^LongWord;
        begin
          k := ''''I am a Delphi fan!'''';
          p:=@K[1];
          Dec(p,1);
          P^:=13;                     //k.Length被置为13
          showmessage(k);
        end;
      由此我们会知道ANsiString的效率是很高的,他的信息存储于字符串头中。例如我们要取字符串的长度只须读出
      TAnsiString.Length的内容即可。而其c\c++的字符串就不行,取字符串的长度要从头读起直到遇到NULL记录下
      读过的字符个数就是长度。可是如果字符串很长效率的差异就显示出来了,比如一个很大的文件?
      前面讲过动态数组赋值的问题,它并不为动态数组单独开辟一块空间,而是简单的把指针指向所赋的数组。只有被赋值的
      数组在改变时才真正分配给他空间。这样做的好处是在赋值的时候会很快。如果被赋值的数组没有改变那就比直接分配空间
      快上许多。另外如果被赋值数组发生改变重新分配空间,只是花费和直接分配空间相同的时间而已。
      有些人会想那么如下代码:
        var
          k,j:AnsiString;
        begin
          k:''''123'''';
          j:=''''456'''';
          k:=j;
        end;
       k的空间已经分配,既然k的指针指向了j,那么k原来的空间岂不是浪费,造成了内存垃圾?
       前面说过AnsiString也是动态数组的一种,符合动态数组生存期自管理。
       但实际的情况是:当把一个指针指向一个字符创空间时,他的引用次数位就加1,
       当有指针指向从这个字符串离开时引用次数位就减1,所以当引用次数位为0是就意味着没有人使用了
       就自动释放这段空间。这就是我们所说的生存期自管理技术。
       Type
        //实际分配大小对我们来说意义不大,所以这里我们先不取他                   
        PAnsiString=^TAnsiString;
        TAnsiString= record
           ReferencCount:LongWord;       //引用次数
      &

[1] [2]  下一页


没有相关教程
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · C语言系列  · VB.NET程序
    · JAVA开发  · Delphi程序
    · 脚本语言
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台