Identificar caracteres minúsculos numa string

06/12/2005

Olá!

Alguém tem idéia de como fazer para identificar se existe um caracter minúsculo numa string?

rtava

OBS.1: Não posso aplicar AnsiUpperCase para transformar a string em maiúscula;
OBS.2: Se for executar um ´[b:dd410dfa81]for[/b:dd410dfa81]´ para checar caracter a caracter, ficará lento para minha aplicação.


Rtava

Respostas

06/12/2005

Okama

Poderia dar mais detalhes sobre suas observações?

Você pode usar For..do no intervalo de 97 a 122 que são letras minusculas com Pos() e se a intensão é só identificar não precisar processar o texto todo.


Responder Citar

06/12/2005

Rtava

Sobre a observação do ´for´:

Suponha que eu possua uma string muito longa (exemplo 10 mil caracteres).
Suponha agora que seja feito um ´for´ nessa string, checando caracter a caracter se algum deles está compreendido entre ASCII 97 e 122. O processo levaria uma tempo considerável se existisse um caracter minúsculo lá pela posição 5000 apenas...

Por esse motivo de possível lentidão, fica complicado contar com o auxílio de um ´for´ para executar a tarefa e estou tentando encontrar uma alternativa mais rápida.


Responder Citar

06/12/2005

Okama

Testa esse código e veja quando tempo leva eu faço exportação de banco de dados para arquivos texto com 12000 registros e cerca de 2472000 caracteres em aproximadamente 25 segundos. Talvez pela complexidade do aplicativo e necessidade da verificação deva-se considerar esse tempo.


Var 
  Texto: String;
  I, X: Integer;
  Existe: Boolean;

begin
  Existe := False;
    
  For I := 0 to length( Texto ) -1 to 
    For X := 97 to 122 do 
    begin
      if Pos( chr(X), Texto ) > 0 then
      begin
        Existe := True;
        Break;
      end;

if Existe then 
   showmessage(´Caractere Encontrado´);

end;



Responder Citar

06/12/2005

Emerson

ou ainda:

Var 
  Texto: String; 
  I: Integer; 
  Existe: Boolean; 
begin 
  Existe := False; 
    
  For I := 1 to length( Texto ) do
    If Texto[I&93; in &91;´a´..´z´&93; then
    begin
      Existe := True; 
      Break; 
    end; 

  if Existe then 
    showmessage(´Caractere Encontrado´);
end;


não comparei esta rotina com aquela passada pelo Okama pra ver qual é mais rápida. faça o teste e depois nos diga...

obs: creio que esta seja mais rápida, pois ela tem um for a menos e também não faz uso da função pos().


Responder Citar

06/12/2005

Emerson

fiz o teste numa cadeia de 15.900 caracteres.
foram 3 testes:
- 1o com um caractere MINÚSCULO no fim da string
- 2o com um caractere MINÚSCULO no meio da string
- 3o com a string tendo todas as letras MAIÚSCULAS

com essa rotina:
procedure ContemMinusculo( Texto: string );
  I: Integer; 
  Existe: Boolean; 
begin 
  Existe := False; 
    
  For I := 1 to length( Texto ) do 
    If Texto[I&93; in &91;´a´..´z´&93; then 
    begin 
      Existe := True; 
      Break; 
    end; 

  if Existe then 
    showmessage(´Caractere Encontrado´)
  else 
    showmessage(´Caractere NÃO Encontrado´);
end;
os resultados foram:
1. 1o teste: ´00:00:00:000´ para informar que o caractere EXISTIA
2. 2o teste: ´00:00:00:000´ para informar que o caractere EXISTIA
3. 3o teste: ´00:00:00:000´ para informar que o caractere NÃO existia

com essa rotina (variação da rotina do Okama):
procedure ContemMinusculo( Texto: string );
var 
  I: Integer; 
  Existe: Boolean; 
begin 
  Existe := False; 
    
  For I := 97 to 122 do 
    if Pos( chr(X), Texto ) > 0 then 
    begin 
      Existe := True; 
      Break; 
    end;

  if Existe then 
     showmessage(´Caractere Encontrado´)
  else
     showmessage(´Caractere NÃO Encontrado´);
end;
os resultados foram:
1. 1o teste: ´00:00:00:000´ para informar que o caractere EXISTIA
2. 2o teste: ´00:00:00:000´ para informar que o caractere EXISTIA
3. 3o teste: ´00:00:00:000´ para informar que o caractere NÃO existia

ou seja, as funções se equivalem.

obs.: note que a segunda procedure é uma variação daquela fornecida pelo nosso colega Okama.
com a procedure do Okama (sem as modificações) o 1o e o 2o teste levaram ´00:00:00:000´, mas o 3o. teste levou mais de 10 segundos.


Responder Citar

06/12/2005

Emerson

[color=blue:5c3a0c2426][b:5c3a0c2426]uma pequena correção...[/b:5c3a0c2426][/color:5c3a0c2426]
na rotina adaptada daquela do Okama,
onde está ´[color=darkred:5c3a0c2426]if Pos( chr(X), Texto ) > 0[/color:5c3a0c2426]´,
leia-se ´[color=blue:5c3a0c2426]if Pos( chr( [b:5c3a0c2426]I[/b:5c3a0c2426] ), Texto ) > 0[/color:5c3a0c2426]´


Responder Citar

06/12/2005

Rtava

Okama, eu não entendi bem qual a necessidade do ´for´ mais externo em sua rotina, então fiz algo pouco mais simples, tal como o Emerson. Ficou uma velocidade espantosa... atende às minhas necessidades sem problema.

Meu teste foi com uma string de 420.000 caracteres e levou apenas 130 milisegundos para procurar o caracter ´z´ (minúsculo) que estava quase no final da string de pesquisa.

Obrigado pelas dicas.

Var 
  Texto: WideString;
  I, X: Integer; 
  Existe: Boolean; 
begin
  Existe := False;
  Texto := Memo1.Lines.Text;

   for X := 97 to 122 do
   begin
      Existe := Pos(Chr(X), Texto) > 0;

      if Existe then
      begin
         ShowMessage(´Existe´);
         Break;
      end;
   end;

end;



Responder Citar

06/12/2005

Emerson

[b:1218f0609e]rtava[/b:1218f0609e], por gentileza...
visto que você tem uma cadeira de caracteres tão extensa, faça o teste com essa rotina, por favor:
procedure ContemMinusculo( Texto: string ); 
  I: Integer; 
  Existe: Boolean; 
begin 
  Existe := False; 
    
  For I := 1 to length( Texto ) do 
    If Texto[I&93; in &91;´a´..´z´&93; then 
    begin 
      Existe := True; 
      Break; 
    end; 

  if Existe then 
    showmessage(´Caractere Encontrado´) 
  else 
    showmessage(´Caractere NÃO Encontrado´); 
end;


eu gostaria de saber se a função Pos() seria equivalente em performance à essa forma que eu fiz.

obrigado.


Responder Citar

06/12/2005

Okama

Desculpem foi um equívoco. Pos() avalia toda a string e não há necessidade do ´for´ testar o tamanho da String. escrevi o código mas não testei.

Estava gerando um for para cada caractere da String indevidamente por isso o atraso na execução.

Esse seria o correto:

For X := 97 to 122 do 
    begin 
      if Pos( chr(X), Texto ) > 0 then 
      begin 
        Existe := True; 
        Break; 
      end; 



Responder Citar

06/12/2005

Rtava

Emerson, analisando sua opção inicialmente pareceria que é mais lenta, mas na realidade é muito mais rápida ainda. Gastou 20 milisegundos para processar o mesmo exemplo que citei antes.

Valeu!

OBS.: Quanto a possuir uma string tão grande, na realidade não possuo. Apenas coloquei um Memo na tela e colei um texto qualquer várias vezes (para teste).


Responder Citar