zoukankan      html  css  js  c++  java
  • String[255]在高版本Delphi里还是被解释成Byte,总体长度256,使用StrPCopy可以给Array String拷贝字符串(内含许多实验测试)

    学了好多不了解的知识:

    procedure TForm1.Button1Click(Sender: TObject);
    var
      s1 : String;
      s2 : String[255];
    begin
      s1:='ç1很好';
      ShowMessage(s1); // 这里显示正常
      s2:=s1;
      ShowMessage(s2); // 这里显示乱码。
      // 问这个问题的原因是,在一个recode pack 里定义了String[255],但是使用Unicode字符给它赋值的时候,就乱码了,这该怎么办?
      // 原因是String[255]还是被翻译成单字节字符,即使在Delphi 2010里也是如此
      // 有没有办法定义一个类似 s2: UnicodeString[255]; 或者s2: WideString[255]这样的东西,好放在record里面使用
    end;
    
    procedure TForm1.Button2Click(Sender: TObject);
    var
      S: ShortString;   { 255个字符长度,256个字节}
      S1: String[255];  { S1和S的字符类型一样,通过使用String声明字符串并且在String后面用中括号规定字符个数的形式定义字符串}
      Len: Integer;
    begin
      S := 'Hello';
      Len := Ord(S[0]); { Len现在包含S的长度为5,Ord函数可以把一个字符类型转换为整数类型}
      ShowMessage(IntToStr(Len));
      Len := SizeOf(S); { Len现在包含的是ShortString类型的大小,为256字节,并不是字符串的长度}
      ShowMessage(IntToStr(Len));
      ShowMessage(IntToStr(Length(s1)));
    end;
    
    procedure TForm1.Button3Click(Sender: TObject);
    var
      DirName    :Array [0..255] of Char;
      myname : String;
    begin
      myname := 'very good';
    //  DirName := myname; // 这里赋值通不过
    //  DirName := PChar(myname); // 这里赋值通不过
    // PAnsiChar StrPCopy(PAnsiChar Dest, const AnsiString Source);
    // PWideChar StrPCopy(PWideChar Dest, const UnicodeString Source);
      StrPCopy(dirname, myname); //
      ShowMessage(DirName); // 这样才可以
    end;
    
    procedure TForm1.Button4Click(Sender: TObject);
    var
      S: ShortString;
      S1: String[255];
    begin
      S := 'Hello';
      ShowMessage(IntToStr(Length(s)));
      ShowMessage(IntToStr(Length(s1))); // 这里显示内容不定,因为S1没有进行初始化
    end;
    
    procedure TForm1.Button5Click(Sender: TObject);
    var
      S: ShortString;
      S1: String[255]; // String[255]的长度,不乘以2。它还是会被翻译成Byte
      S3: String;
      S4: Array [0..255] of Char; // 并没有在前后预留什么空间
    begin
      S := 'Hello';
      ShowMessage(IntToStr(Length(s))); // 5
      PWord(@S)^ := 100;
      ShowMessage(IntToStr(Length(S))); // 100,因为自动管理的长度值被改了
      PWord(@S1)^ := 200;
      ShowMessage(IntToStr(Length(S1))); // 200,因为自动管理的长度值被改了
    
      SetLength(S3, 255);
    
      ShowMessage(IntToStr(SizeOf(s)));  // 256,之所以多了1,是因为有长度管理
      ShowMessage(IntToStr(SizeOf(s1))); // 256,之所以多了1,是因为有长度管理(还是最后一个字符是#0?不太可能)
      ShowMessage(IntToStr(SizeOf(s3))); // 4
      ShowMessage(IntToStr(SizeOf(s4))); // 512
      ShowMessage(s4); // 内容不定,因为没有初始化
    end;
    
    // 删掉Array里的某个字符,相当于Delete函数
    procedure ArrayDelete(var pArray: array of Char; const nIndex, nCount: Integer);
    begin
      // Move ( const SourcePointer; var DestinationPointer; CopyCount : Integer ) ;
      Move(pArray[nIndex + nCount], pArray[nIndex], (StrLen(pArray) - nCount + 1) * SizeOf(Char));
    end;
    
    procedure TForm1.Button6Click(Sender: TObject);
    var
      a: array[0..255] of Char;
    begin
      a := '123456789';
      ArrayDelete(a, 2, 3);
      ShowMessage(a);
    end;

    lstrcpy
    你也可以用windows单元里的lstrcpy函数。
    这个是windows提供的等价strcpy的函数。
    性能比strcpy低,但是有异常处理。

    ------------------------------------------------

    var
    DirName : String[255]
    begin
    // 若干赋值
    Delete(DirName, Length(DirName), 1);
    end;

    现在改成:
    var
    DirName : Array [0..254] of Char
    begin
    // 这个Delete应该怎么写?没有初始化的字符,默认都是#0?
    end;

    比方说S1是Array [0..255] of Char
    目前S1的值是MyName
    我就是想把最后一个字符去掉,改成MyNam

    ------------------------------------------------

    应该是错误的办法:
    move(a[1], a[0], strlen(a)*sizeof(char));
    去看tlist的delete方法

    可能的办法:
    a[5] := 0;

    聪明办法:
    procedure ArrayDelete(var pArray: array of Char; const nIndex, nCount: Integer);
    begin
    Move(pArray[nIndex + nCount], pArray[nIndex], (StrLen(pArray) - nCount + 1) * SizeOf(Char));
    end;

    var
    a: array[0..255] of Char;
    begin
    a := '123456789';
    ArrayDelete(a, 2, 2);
    ShowMessage(a);
    end;

    笨办法:
    mystring:=DirName;
    mystring:=LeftStr(mystring, Length(mystring)-1);
    StrPCopy(DirName, mystring);

    ------------------------------

    疑问:
    1. Array数组没有用完的时候,后面的字符会被初始化成什么?什么才是字符串准确终止?
    2. String可否包含#0?应该可以。另外要学会使用String的头部数据。
    3. 据说AnsiString和UnicodeString可以相互赋值
    4. move只是移动内存数据 不会覆盖不被移动的区域
    那a这个array是如何感受到,它的字符串变短了呢?
    array不是有一个前缀,这样才能知道当前array用了多长的空间


    学习了:
    1. 新学了StrLen、Delete函数
    2. 移动开发,String下标从0开始

    --------------------------------

    procedure TForm1.Button7Click(Sender: TObject);
    var
    S1: Array [0..255] of Char;
    S2: String[255];
    begin
    S1:='0123456789';
    S1[3]:=#0;
    ShowMessage(String(S1)); // 012,我估计是转换到String的时候,碰到#0就停了。但其实S1的长度仍是10

    S2:='0123456789';;
    Byte(S2[0]) := 3;
    ShowMessage(String(S2)); // 012,修改S2的长度管理,人工强行变成只使用了3个字符。
    end;

    这说明,array看到#0就停止。String[255]则是有一个前缀在管理使用的长度

    这样就截断字符串了,就是你说的Delete,而且不考虑删除中间

    最后一个小小问题:Array有一个前缀来管理使用的长度吗?
    回答:没有。但是array of Char又有了。

    --------------------------------

    type
    T = packed record
    A: char;
    B: string[5];
    end;

    procedure TForm1.Button8Click(Sender: TObject);
    begin
    ShowMessage(IntToStr(SizeOf(T)));
    end;

    答案是8,即2+1+5

  • 相关阅读:
    CUUG PostgreSQL中级认证PGCP首考圆满结束!
    OCP 063中文考试题库(cuug内部资料)第21题
    OCP 063中文考试题库(cuug内部资料)第20题
    OCP 063中文考试题库(cuug内部资料)第19题
    OCP 063中文考试题库(cuug内部资料)第17题
    cdq实现树状数组
    P3810 【模板】三维偏序(陌上花开) 题解(cdq分治模板)
    CSUST 递增数组2 题解(思维+分段考虑)
    E. Clear the Multiset 题解(分治+贪心)
    P5019 [NOIP2018 提高组] 铺设道路 题解(贪心+思维)
  • 原文地址:https://www.cnblogs.com/findumars/p/5243774.html
Copyright © 2011-2022 走看看