Fórum Ler string ignorando espaços em branco #230290

05/05/2004

0

Gente, os campos q preciso ler estão todos numa mesma linha, só q eles não seguem um padrão de posições, eles só são separados por espaços em branco, alguém sabe se existe alguma função no delphi q leia um pedaço da string (até o espaço em branco) e jogue numa variável esse conteúdo?
Em PHP eu sei q existe, a função se chama (acho) split(variavel, char_separador), ela funciona lendo os campos até encontrar o ´char_separador´ e vai jogando para um vetor o conteúdo.
Eu entendo q fazer esse tipo de tratamento não é tão complicado, mas se existe função pra isso... ajuda bastante.
Obrigada


Fer_nanda

Fer_nanda

Responder

Posts

06/05/2004

Tnaires

Descoheço a função na API do Delphi, mas o Fortes Report vem com uma unit chamada RLUtils que contém uma função chamada Token.
Uso:
function Token(const string_a_separar: string; numero_do_token: integer; separador: char = ´|´): string;

Por exemplo, se vc tem:
s := ´token1 token2 token3´;
a linha Token(s, 2, ´ ´) retornaria token2.


Responder

Gostei + 0

06/05/2004

Beppe

function Split(const S: String; Ch: Char; IncludeBlanks: Boolean; Items: TStrings): Integer; 
var 
  P, Q, T: PChar; 
  Temp: String; 
begin 
  Result := 0; 
  if S <> ´´ then 
  begin 
    P := Pointer(S); 
    Q := P + Length(S); 
    repeat 
      T := P; 
      if P^ <> Ch then 
      repeat 
        Inc(P); 
      until (P >= Q) or (P^ = Ch); 
      if IncludeBlanks or (P <> T) then 
      begin 
        SetString(Temp, T, P - T); 
        Items.Add(Temp); 
        Inc(Result); 
      end; 
      Inc(P); 
    until P >= Q; 
  end; 
end;


Fiz há algum tempo já, naum lembro se tá funcionando, mas acho q sim... :oops:

Chame Split(Linha, ´ ´, False, SuasStrings);

Vc precisa criar um descendente de TStrings, SuasStrings, para receber os dados.


Responder

Gostei + 0

06/05/2004

Allen74

Esta dica é in memorian e em homenagem ao nosso amigo 4olho, que utilizou o artifício em um puzzle que propus em outro fórum para manipulação de palavras:

Em primeiro lugar, um código de exemplo para você testar em seu formulário. Coloque este código no evento OnClick de um botão qualquer.
var
  st : TStringList;
begin
  st := TStringList.Create;

  // informa qual caractere delimitador
  st.Delimiter := ´ ´;

  // informar o texto delimitado - não importa a quantidade de espaços
  // que irá separar os campos
  st.DelimitedText := ´campo0 campo1  campo2 campo3  campo4 campo5´;

  ShowMessage (´Quantidade de campos na string: ´+IntToStr(st.count)+#1313+
               ´st[0] = ´+st.Strings[0]+13+
               ´st[1] = ´+st.Strings[1]+13+
               ´st[2] = ´+st.Strings[2]+13+
               ´st[3] = ´+st.Strings[3]+13+
               ´st[4] = ´+st.Strings[4]+13+
               ´st[5] = ´+st.Strings[5]+13
  );
  st.Free;
end;

A classe TStringList possui a capacidade de trabalhar com strings delimitadas, te permitindo converter uma string em um vetor de strings, conforme explicitado no exemplo acima.

As partes importantes do artifício estão comentadas: utilizar a propriedade Delimiter para indicar qual o caractere que estará delimitando os campos e a propriedade DelimitedText para atribuir o texto delimitado que irá compor a lista.

Detalhes importantes:
- nunca se esquecer de destruir o objeto TStringList (st.free).
- se o caractere delimitador aparecer mais de uma vez em sequência, mesmo assim será considerado como um delimitador apenas. Separanco campo1 e campo 2 coloquei dois espaços, mas é interpretado como um. Assim, para inserir campos vazios, teria que abrir e fechar aspas. Maiores detalhes, consulte o help do Delphi.


Responder

Gostei + 0

06/05/2004

Fer_nanda

Exatamente disso q eu preciso.
Funcionou 100¬.
Valeu =)


Responder

Gostei + 0

06/05/2004

Allen74

Amigos,

O membro Marcos Salles me avisou que o código que postei não funcionou no Delphi5. O motivo é que a classe TStringList desta versão do Delphi não possui os recursos para manipular texto delimitado. Sendo assim, uma alternativa para versões do Delphi anteriores à versão 6 seria:
//
function Explode (Delimiter : Char; Texto : String) : TStringList;
var
  st : TStringList;
  i : integer;
begin
  st := TStringList.Create;
  while length(Texto) > 0 do
  begin
    // remove presença do delimitador no início do texto
    while Pos(Delimiter, Texto) = 1 do delete(Texto,1,1);
    i := Pos(Delimiter,Texto);
    if i > 0
    then begin
      st.add (Copy(Texto,1,i-1));
      delete(Texto, 1, i);
    end
    else break;
  end;
  if length(Texto) > 0
  then st.add(Texto);
  result := st;
end;
Não se esquecendo que esta função retorna uma nova instância de TStringList que deve ser destruída quando não for mais utilizada no código. O exemplo anterior utilizando esta função ficaria assim:
var
  st : TStringList;
begin
  st := Explode(´ ´, ´campo0 campo1  campo2 campo3  campo4 campo5´);

  ShowMessage (´Quantidade de campos na string: ´+IntToStr(st.count)+#1313+
               ´st[0] = ´+st.Strings[0]+13+
               ´st[1] = ´+st.Strings[1]+13+
               ´st[2] = ´+st.Strings[2]+13+
               ´st[3] = ´+st.Strings[3]+13+
               ´st[4] = ´+st.Strings[4]+13+
               ´st[5] = ´+st.Strings[5]+13
  );
  st.Free;
end;

Uma função que poderia ser utilizada nos casos em que você sabe a quantidade de campos que existe a string seria:
function GetDelimited (Delimiter : Char; Texto : string; indice : integer) : string;
var
  i,j : integer;
begin
  j := 0;
  while length(Texto) > 0 do
  begin
    // remove presença do delimitador no início do texto
    while Pos(Delimiter, Texto) = 1 do delete(Texto,1,1);
    i := Pos(Delimiter,Texto);
    if i > 0
    then begin
      result := Copy(Texto,1,i-1);
      delete(Texto, 1, i);
      if indice = j
      then exit;
      inc(j);
    end
    else break;
  end;
  if indice <> j
  then result := ´´
  else result := Texto;
end;

// exemplo de utilização

  txt := ´campo0 campo1  campo2 campo3  campo4 campo5´;

  ShowMessage (´campos na string: ´+#1313+
               ´st[0] = ´+GetDelimited(´ ´,txt,0)+13+
               ´st[1] = ´+GetDelimited(´ ´,txt,1)+13+
               ´st[2] = ´+GetDelimited(´ ´,txt,2)+13+
               ´st[3] = ´+GetDelimited(´ ´,txt,3)+13+
               ´st[4] = ´+GetDelimited(´ ´,txt,4)+13+
               ´st[5] = ´+GetDelimited(´ ´,txt,5)+13
  );



Responder

Gostei + 0

06/05/2004

Paulo_amorim

//
function Explode (Delimiter : Char; Texto : String) : TStringList;
var
  st : TStringList;
  i : integer;
begin
  st := TStringList.Create;
  while length(Texto) > 0 do
  begin
    // remove presença do delimitador no início do texto
    while Pos(Delimiter, Texto) = 1 do delete(Texto,1,1);
    i := Pos(Delimiter,Texto);
    if i > 0
    then begin
      st.add (Copy(Texto,1,i-1));
      delete(Texto, 1, i);
    end
    else break;
  end;
  if length(Texto) > 0
  then st.add(Texto);
  result := st;
end;
Não se esquecendo que esta função retorna uma nova instância de TStringList que [b:77cd923c61]deve ser destruída quando não for mais utilizada no código[/b:77cd923c61].


Olá

Agradeço também pelo algoritmo, Allen, pois também usarei essa versão D5.

Somente complementando: no algoritmo desenvolvido foi declarada uma variável st: TStringList, a qual não foi destruída ao final da function

Assim, como o Allen mesmo disse, deve-se destruir a variável, e a function deveria ter um final assim ao meu ver:

  result := st;
  st.Free;
end;


Até+


Responder

Gostei + 0

06/05/2004

Allen74

Olá Paulo!

Somente complementando: no algoritmo desenvolvido foi declarada uma variável st: TStringList, a qual não foi destruída ao final da function

Neste caso, Paulo, como estamos criando uma função que retornará uma nova instância de TStringList, não podemos destruir o objeto referenciado por [b:0d8574e10a]st[/b:0d8574e10a] no final da função, porque assim destruimos o próprio objeto que deveria ser retornado, devolvendo um ponteiro inválido que causaria uma AccessViolation na primeira referência ao objeto na memória.

Como você pode observar no exemplo de utilização da função Explode(), o objeto retornado pela função, que também atribuí a uma variável de nome [b:0d8574e10a]st[/b:0d8574e10a] é destruído depois da exibição dos valores por ShowMessage(). Então a responsabilidade pela destruição do objeto retornado fica por conta de quem estiver utilizando a função.


Responder

Gostei + 0

Utilizamos cookies para fornecer uma melhor experiência para nossos usuários, consulte nossa política de privacidade.

Aceitar