Array
(
)

Identificar caracteres minúsculos numa string

Rtava
   - 06 dez 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 ´for´ para checar caracter a caracter, ficará lento para minha aplicação.


Okama
   - 06 dez 2005

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.


Rtava
   - 06 dez 2005

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.


Okama
   - 06 dez 2005

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.


#Código


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;



Emerson
   - 06 dez 2005

ou ainda:

#Código

Var 
Texto: String;
I: Integer;
Existe: Boolean;
begin
Existe := False;

For I := 1 to length( Texto ) do
If Texto[I] in [´a´..´z´] 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().


Emerson
   - 06 dez 2005

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:
#Código

procedure ContemMinusculo( Texto: string );
I: Integer;
Existe: Boolean;
begin
Existe := False;

For I := 1 to length( Texto ) do
If Texto[I] in [´a´..´z´] 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):
#Código
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.


Emerson
   - 06 dez 2005

uma pequena correção...
na rotina adaptada daquela do Okama,
onde está ´if Pos( chr(X), Texto ) > 0´,
leia-se ´if Pos( chr( I ), Texto ) > 0´


Rtava
   - 06 dez 2005

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.

#Código

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;



Emerson
   - 06 dez 2005

rtava, por gentileza...
visto que você tem uma cadeira de caracteres tão extensa, faça o teste com essa rotina, por favor:
#Código

procedure ContemMinusculo( Texto: string ); 
I: Integer;
Existe: Boolean;
begin
Existe := False;

For I := 1 to length( Texto ) do
If Texto[I] in [´a´..´z´] 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.


Okama
   - 06 dez 2005

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:

#Código

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



Rtava
   - 06 dez 2005

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).