AnsiString


O C++Builder implementa o tipo AnsiString como uma classe. AnsiString é projetado para funcionar como o tipo long string Delphi. Adequadamente, AnsiString fornece as seguintes características de tratamento de strings que são requeridas quando você chama funções do tipo VCL que usam qualquer tipo long string Delphi:


reference count

• string length

• data

• null string terminator


Se você não fornecer um valor inicial, as variáveis AnsiString são iniciadas com instância zero.


Podemos conceituar uma string como um caracter, ou uma seqüência de caracteres colocados entre aspas duplas:


"Alô, Thérbio!"

"Guarulhos é a terra das Pizzarias..."

"Oba!"

"ô"


A classe AnsiString possui um bom nível de independência e flexibilidade nos controles onde é usada, uma vez que não é descendente de Tobject, permitindo-nos realizar diversas operações úteis com strings. A implementação desse arquivo pode ser visualizada no diretório include/vcl/dstring.h da pasta de instalação de seu compilador:




// DSTRING.H - Support for delphi strings in C++
//            (AnsiString and template<sz> SmallString)
// $Revision:   1.25.1.6  $
// $Date:   13 Jan 1999 16:32:30  $
//
// Copyright (c) 1997, 1998 Borland International

#ifndef DSTRING_H
#define DSTRING_H

#pragma delphiheader begin

#include <sysmac.h>


namespace System
{
  class                  TVarRec;
  class RTL_DELPHIRETURN Currency;
  class RTL_DELPHIRETURN WideString;

  /////////////////////////////////////////////////////////////////////////////
  // AnsiString: String class compatible with Delphi's Native 'string' type
  /////////////////////////////////////////////////////////////////////////////
  class RTL_DELPHIRETURN AnsiString
  {
    friend AnsiString __fastcall operator +(const char*, const AnsiString& rhs);
  public:
    // the TStringFloatFormat enum is used by FloatToStrF
    enum TStringFloatFormat
    {sffGeneral, sffExponent, sffFixed, sffNumber, sffCurrency};
    static AnsiString __fastcall StringOfChar(char ch, int count);
    static AnsiString __fastcall LoadStr(int ident);
    static AnsiString __fastcall LoadStr(HINSTANCE hInstance, int ident);
    static AnsiString __fastcall FmtLoadStr(int ident, const TVarRec *args,
                        int size);

    AnsiString& __fastcall       LoadString(HINSTANCE hInstance, int ident);

    // Delphi style 'Format'
    //
    static AnsiString __fastcall Format(const AnsiString& format,
                      const TVarRec *args, int size);

    // C++ style 'sprintf' (NOTE: Target buffer is the string)
    //
    AnsiString& __cdecl  sprintf(const char* format, ...); // Returns *this
    int __cdecl  printf(const char* format, ...); // Returns formatted length

    static AnsiString __fastcall FormatFloat(const AnsiString& format,
                         const long double& value);
    static AnsiString __fastcall FloatToStrF(long double value,
                         TStringFloatFormat format, int precision, int digits);
    static AnsiString __fastcall IntToHex(int value, int digits);
    static AnsiString __fastcall CurrToStr(Currency value);
    static AnsiString __fastcall CurrToStrF(Currency value,
                        TStringFloatFormat format, int digits);

    // Constructors
    __fastcall AnsiString(): Data(0) {}
    __fastcall AnsiString(const char* src);
    __fastcall AnsiString(const AnsiString& src);
//    __fastcall AnsiString(const char* src, unsigned char len);
    __fastcall AnsiString(const char* src, unsigned int len);
    __fastcall AnsiString(const wchar_t* src);
    __fastcall AnsiString(char src);
    __fastcall AnsiString(short);
    __fastcall AnsiString(unsigned short);
    __fastcall AnsiString(int src);
    __fastcall AnsiString(unsigned int);
    __fastcall AnsiString(long);
    __fastcall AnsiString(unsigned long);
    __fastcall AnsiString(__int64);
    __fastcall AnsiString(unsigned __int64);
    __fastcall AnsiString(double src);
    __fastcall AnsiString(const WideString &src);

    // Destructor
    __fastcall ~AnsiString();

    // Assignments
    AnsiString& __fastcall operator =(const AnsiString& rhs);
    AnsiString& __fastcall operator +=(const AnsiString& rhs);

    // Comparisons
    bool __fastcall operator ==(const AnsiString& rhs) const;
    bool __fastcall operator !=(const AnsiString& rhs) const;
    bool __fastcall operator <(const AnsiString& rhs) const;
    bool __fastcall operator >(const AnsiString& rhs) const;
    bool __fastcall operator <=(const AnsiString& rhs) const;
    bool __fastcall operator >=(const AnsiString& rhs) const;
    int  __fastcall AnsiCompare(const AnsiString& rhs) const;
    int  __fastcall AnsiCompareIC(const AnsiString& rhs) const; //ignorecase

    // Accessing character at specified index

    char __fastcall operator [](const int idx) const
    {
      ThrowIfOutOfRange(idx); // Should Range-checking be optional to avoid overhead ??
      return Data[idx-1];
    }

#if defined(ANSISTRING_USE_PROXY_FOR_SUBSCRIPT)

    // The use of a proxy class optimizes the case where Unique() must be called
    // when accessing the string via the subscript operator. However, the use of
    // of the proxy class has some drawbacks. First, it breaks code that apply
    // operators to the return value. For example, &MyString[i]. Second, it
    // fails in cases where a implicit conversion was relied upon. For example,
    //       callFuncThatTakesAnObjectWithACharCtr(MyString[i]);
    // In that case, two implicit conversions would be required...
    // The first issue can be remedied by enhancing the proxy class to support
    // all valid operators. The second issue can be lessened but not completely
    // eliminated. Hence, the use of the PROXY class is not the default!
    //
  private:
    class  TCharProxy;
    friend TCharProxy;
    class  TCharProxy
 {
   public:
    TCharProxy(AnsiString& strRef, int index) : m_Ref(strRef), m_Index(index) {}
    TCharProxy& operator=(char c) 
                { m_Ref.Unique(); m_Ref.Data[m_Index-1] = c; return *this; }
    operator char() const         { return m_Ref.Data[m_Index-1]; }

  protected:
    AnsiString&         m_Ref;
    int                 m_Index;
 };

  public:
    TCharProxy __fastcall operator [](const int idx)
    {
      ThrowIfOutOfRange(idx); // Should Range-checking be optional to avoid overhead ??
      return TCharProxy(*this, idx);
    }

#else

    char& __fastcall operator [](const int idx)
    {
      ThrowIfOutOfRange(idx); // Should Range-checking be optional to avoid overhead ??
      Unique();                 // Ensure we're not ref-counted
      return Data[idx-1];
    }

#endif

    // Concatenation
    AnsiString __fastcall operator +(const AnsiString& rhs) const;

    // C string operator
    char* __fastcall c_str() const { return (Data)? Data: "";}

    // Query attributes of string
    int  __fastcall Length()  const;
    bool __fastcall IsEmpty() const;

    // Make string unique (refcnt == 1)
    AnsiString&  __fastcall Unique();

    // Modify string
    AnsiString&  __fastcall Insert(const AnsiString& str, int index);
    AnsiString&  __fastcall Delete(int index, int count);
    AnsiString&  __fastcall SetLength(int newLength);

    int __fastcall Pos(const AnsiString& subStr) const;
    AnsiString   __fastcall LowerCase() const;
    AnsiString   __fastcall UpperCase() const;
    AnsiString   __fastcall Trim() const;
    AnsiString   __fastcall TrimLeft() const;
    AnsiString   __fastcall TrimRight() const;
    AnsiString   __fastcall SubString(int index, int count) const;

    int          __fastcall ToInt() const;
    int          __fastcall ToIntDef(int defaultValue) const;
    double       __fastcall ToDouble() const;

    // Convert to Unicode
    int          __fastcall WideCharBufSize() const;
    wchar_t*     __fastcall WideChar(wchar_t* dest, int destSize) const;

    // MBCS support
    enum TStringMbcsByteType
    {mbSingleByte, mbLeadByte, mbTrailByte};

    TStringMbcsByteType __fastcall ByteType(int index) const;
    bool  __fastcall IsLeadByte(int index) const;
    bool  __fastcall IsTrailByte(int index) const;
    bool  __fastcall IsDelimiter(const AnsiString& delimiters, int index) const;
    bool  __fastcall IsPathDelimiter(int index) const;
    int   __fastcall LastDelimiter(const AnsiString& delimiters) const;
    int   __fastcall AnsiPos(const AnsiString& subStr) const;
    char* __fastcall AnsiLastChar() const;

  protected:
    void  ThrowIfOutOfRange(int idx) const;

  private:
    char *Data;
  };

  extern AnsiString __fastcall operator +(const char*, const AnsiString& rhs);

#if defined(VCL_IOSTREAM)
  ostream& operator << (ostream& os, const AnsiString& arg);
  istream& operator >> (istream& is, AnsiString& arg);
#endif


  /////////////////////////////////////////////////////////////////////////////
  // SmallStringBase
  /////////////////////////////////////////////////////////////////////////////
  template <unsigned char sz> class SmallStringBase
  {
  protected:
    unsigned char Len;
    char Data[sz];
  };


  /////////////////////////////////////////////////////////////////////////////
  // SmallString
  /////////////////////////////////////////////////////////////////////////////
  template <unsigned char sz> class SmallString : SmallStringBase<sz>
  {

#if defined(VCL_IOSTREAM)
    friend ostream& operator <<(ostream& os, const SmallString& arg)
    {
      os << AnsiString(arg);
      return os;
    }
    friend istream& operator >>(istream& is, SmallString& arg)
    {
      AnsiString s;
      is >> s;
      arg = s;
      return is;
    }
#endif

  public:
    __fastcall SmallString() { Len = 0; }
    __fastcall SmallString(const SmallString& src);
    __fastcall SmallString(const char* src);

    __fastcall SmallString(const AnsiString& src)
    {
      long len = src.Length();
      Len = (unsigned char)((len > sz)? sz: len);
      strncpy(Data, src.c_str(), Len);
    }

    char& __fastcall operator [](const unsigned char idx)
    {return Data[idx-1];}

    SmallString& __fastcall operator =(const SmallString& rhs);

    __fastcall operator AnsiString() const;
  };

  // used when SmallStrings are in unions (can't have a ctor)
  // must cast DummySmallString to SmallString to do anything useful

  template<unsigned char sz> __fastcall
  SmallString<sz>::SmallString(const char* src)
  {
    long len = strlen(src);
    Len = (unsigned char)((len > sz)? sz: len);
    strncpy(Data, src, Len);
  }

  template<unsigned char sz> __fastcall
  SmallString<sz>::SmallString(const SmallString& src)
  {
    Len = src.Len;
    for (int i = 0; i < Len; i++)
      Data[i] = src.Data[i];
  }

  template<unsigned char sz> SmallString<sz>& __fastcall
  SmallString<sz>::operator =(const SmallString& rhs)
  {
    if (this != &rhs)
    {
      Len = rhs.Len;
      for (int i = 0; i < Len; i++)
        Data[i] = rhs.Data[i];
    }
    return *this;
  }

  template<unsigned char sz>
  inline __fastcall SmallString<sz>::operator AnsiString() const
  {
    return AnsiString(Data, Len);
  }
}
using namespace System;

// The following is provided for backward compatibility.
// Otherwise, the new IntToStr(__int64) causes ambiguity for old code
// that used 'bool', uint and DWORD.
//
namespace Sysutils
{
  extern PACKAGE AnsiString __fastcall IntToStr(int Value)/* overload */;
  extern PACKAGE AnsiString __fastcall IntToStr(__int64 Value)/* overload */;
}

#pragma option push -w-inl

inline AnsiString __fastcall IntToStr(bool value)
{
  return Sysutils::IntToStr(int(value));
}
inline AnsiString __fastcall IntToStr(unsigned int value)
{
  return Sysutils::IntToStr(int(value));
}
inline AnsiString __fastcall IntToStr(unsigned long value)
{
  return Sysutils::IntToStr(int(value));
}

#pragma option pop

#pragma delphiheader end.

#endif  // DSTRING_H


Por enquanto não tente entender os fundamentos deste arquivo, pois nele aparecem muitos termos que nos são novidades ainda. No avançar do curso, muitos desses fundamentos serão abordados, tornando a compreensão de partes do arquivo mais ou menos intuitiva.

Todavia, vamos verificar alguns tópicos, por dois motivos:

1º - É importante que tenhamos conhecimento de determinadas facilidades que AnsiString nos proporciona;

2º - aprendermos a operar determinadas funções da classe, por intuição.


Nota: Caption é o rótulo que pode ser estampado no componente, suportando mudanças em tempo de execução. Controles que exibem textos, fazem-no através da propriedade Caption ou da propriedade Text. A propriedade a ser usada dependerá do tipo do controle. De um modo geral, Caption é usado por textos que aparecem como títulos de uma janela ou um rótulo (estampa), enquanto Text é usado por textos que aparecem como conteúdo de um controle. Via de regra, Text podem ser editados pelo usuário, enquanto Caption é uma propriedade que não recebe o foco da aplicação, tendo como característica a finalidade básica de enviar uma informação ao usuário.


Muitos controles usam propriedades da classe AnsiString. Por exemplo, todos os controles que possuem rótulo (forms, edits, panels, labels) usam AnsiString através da propriedade Caption. Outros controles como o EditBox usam a classe AnsiString como base de seus textos (propriedade Text). Se repararmos bem, notaremos que nós já temos usado e implementado objetos AnsiString sem qualquer espécie de declaração. Em outra situação qualquer, a declaração e inicialização de uma string sempre será necessária antes do uso respectivo.


A declaração de uma String é análoga à declaração de um tipo básico, porém usando a palavra AnsiString seguida de um nome válido C++. Eis um exemplo:


AnsiString Pais; 

Em dstring.h podemos observar que AnsiString é uma classe com seu próprio construtor e destruidor:


    // Constructors
    __fastcall AnsiString(): Data(0) {}
    __fastcall AnsiString(const char* src);
    __fastcall AnsiString(const AnsiString& src);
//    __fastcall AnsiString(const char* src, unsigned char len);
    __fastcall AnsiString(const char* src, unsigned int len);
    __fastcall AnsiString(const wchar_t* src);
    __fastcall AnsiString(char src);
    __fastcall AnsiString(short);
    __fastcall AnsiString(unsigned short);
    __fastcall AnsiString(int src);
    __fastcall AnsiString(unsigned int);
    __fastcall AnsiString(long);
    __fastcall AnsiString(unsigned long);
    __fastcall AnsiString(__int64);
    __fastcall AnsiString(unsigned __int64);
    __fastcall AnsiString(double src);
    __fastcall AnsiString(const WideString &src);

    // Destructor
    __fastcall ~AnsiString();

Logo você também pode declarar uma variável dela com parênteses vazios, determinando a chamada do construtor da classe. Eis um exemplo:


AnsiString Animal(); 

Há dois modos principais para você iniciar uma variável AnsiString. Depois de declará-la, pode-se determinar o valor desejado para a variável usando o nome escolhido. Eis um exemplo:


AnsiString Especie;
Especie = "Cachorro";

também podemos, tal qual nos tipos básicos, inicializar a variável String na sua declaração, fornecendo o valor desejado para o nome escolhido. Eis um exemplo:


AnsiString Raca("Pastor Alemão"); 


Uma vez definida, a String poderá ser usada, por exemplo, para alterar o Caption de controles:


//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Meu_Cao;
Meu_Cao = " O Tobby é um vira-lata, que só sabe latir, latir e latir..."; 
Label1->Caption = Meu_Cao;
}
//---------------------------------------------------------------------------

Também poderá ser usada para preencher um controle Edit:


//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
AnsiString Pre_Hist = "Tiranossauro ou 286???";
Edit1->Text = Pre_Hist;
}
//---------------------------------------------------------------------------

Um texto introduzido num Edit box, por exemplo, é, por padrão, considerado uma String, visto que o compilador não pode deduzir que espécie de dado ou valor o usuário deseja manipular. Por essa razão, depois que um valor foi fornecido para um controle que fundamenta-se na classe AnsiString como base de seu conteúdo, para executar qualquer operação matemática com tal String, devemos convertê-la para o tipo de dado desejado. Para essa finalidade podemos, por exemplo, usar a função StrToInt():


void __fastcall TForm1::Button1Click(TObject *Sender)
{
Label1->Caption = "111";
int i = StrToInt(Label1->Caption) - 11;
Edit1->Text = i;
}

Conforme apresentado, a classe AnsiString provê um grande número de construtores que nos permitem a criação de strings de qualquer espécie:


Por exemplo, podemos usar:


um caracter:


AnsiString Simbolo = 'T';


um inteiro


AnsiString Int = 120; 


um long int


AnsiString LongoInt = -73495745; 


um valor ponto flutuante:


AnsiString PtoFlut = 675.15;


Um double:


AnsiString DplPrec = 2.15e28; 


um string


AnsiString AloTher = "Alô, Thérbio"; 


Qualquer dessas variáveis pode ser declarada usando os construtores equivalentes:


//---------------------------------------------------------------------------
AnsiString Simbolo('T');
AnsiString Int(120);
AnsiString AloTher("Alô, Thérbio");
AnsiString PtoFlut(675.15);
AnsiString LongoInt(-73495745);
AnsiString DplPrec(2.15e28);
//---------------------------------------------------------------------------

Baseado na configuração dos construtores AnsiString, podemos converter qualquer valor e torná-lo disponível para um controle que use as propriedades AnsiString. Por exemplo, podemos converter e exibir:


um caracter:

char Letra = 't';

Edit1 -> Text = AnsiString(Letra); 

um inteiro:

Integer Numero = 256;

Edit1->Text = AnsiString(Numero); 

um long integer:

long Valor = 4949431;

Panel1->Caption = AnsiString(Valor); 

um valor ponto flutuante:

Single Distancia = 5698.03;

Label1->Caption = AnsiString(Distancia); 

um double:

Double Tamanho = 24588;

Edit1->Text = AnsiString(Tamanho); 


uma string

AnsiString Servico = "Limpador de Fogões";

Button2->Caption = AnsiString(Servico);

Nota: Você deve ter notado o uso de nomes de tipos diferentes dos apresentados anteriormente. 

Por exemplo:

chamamos o tipo int de Integer, o tipo float de Single; o tipo double de Double ...

Por que será? 

No início do arquivo  dstring.h  vemos a inclusão do arquivo de cabeçalho  sysmac.h:

#include <sysmac.h>
NOTA: Logo abordaremos o uso da palavra typedef para criar outro nome para um tipo de dados:
Vejamos um trecho do arquivo sysmac.h:


    class PACKAGE TVarArray;
    typedef TVarArray *PVarArray;

    typedef bool                 Boolean;          //
    typedef int                  Integer;          // -2147483648..2147484647
    typedef char                 Char;             // 0..255
    typedef wchar_t              WideChar;         // Unicode character
    typedef signed char          Shortint;         // -128..127
    typedef short                Smallint;         // -32768..32767
    typedef unsigned char        Byte;             // 0..255
    typedef unsigned short       Word;             // 0..65535
    typedef unsigned long        DWord;            // 0..4294967295
    typedef void*                Pointer;          //
    typedef char                 AnsiChar;         //
    typedef signed long          Longint;          // -2147483648..2147484647
    typedef unsigned int         Cardinal;         // 0..2147484647
    typedef long double          Extended;         // 10 byte real
    typedef float                Single;           // 4 byte real
    typedef double               Double;           // 8 byte real
    typedef char* const          Openstring;   // D16 string/D32 shortstring formalparm
    typedef void*                file;             //
    typedef void*                Text;             //
    typedef Text                 TextFile;         //
    typedef char*                PChar;            //
    typedef char*                PAnsiChar;        //
    typedef wchar_t*             PWideChar;        //
    typedef unsigned char        ByteBool;         //
    typedef unsigned short       WordBool;         //
    typedef Cardinal             LongBool;         //
    typedef AnsiString           String;           //
    typedef SmallStringBase<255> ShortStringBase;  //
    typedef SmallString<255>     ShortString;      //
    typedef ShortString*         PShortString;     //
    typedef AnsiString*          PAnsiString;      //
    typedef PAnsiString          PString;          //
    typedef WideString*          PWideString;      //
    typedef Extended*            PExtended;        //
    typedef Currency*            PCurrency;        //
    typedef Variant*             PVariant;         //
    typedef __int64              LONG64;           // !! obsolete
    typedef GUID                 TGUID;            //
    typedef TGUID*               PGUID;            //
    typedef HRESULT              HResult;          //

    typedef Integer __fastcall (*TThreadFunc)(Pointer Parameter);
    typedef void (*TModuleUnloadProc)(HINSTANCE hinstance);
    typedef bool (*TEnumModuleFunc)(HINSTANCE hinstance, void *data);

    typedef struct TVarData *PVarData;

Os nomes à direita representam os sinônimos que podem ser usados em substituição aos tipos básicos. Por exemplo, Boolean pode ser usado em substituição ao tipo bool.


Nas próximas lições abordaremos várias implementações de AnsiString.


Nota: voltamos a insistir para que você não se preocupe quando se deparar com nomes de tipos de dados ainda não estudados (como classe, por exemplo) visto que no momento apropriado do curso abordaremos tais tópicos com a profundidade necessária.





anterior

índice

próxima


HOME || MAPA DO SITE || CURSOS || TUTORIAIS || LINKS || FORUM || CONTATO