Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Sacar números de cadenas de caracteres. (https://www.clubdelphi.com/foros/showthread.php?t=71093)

McK 30-11-2010 14:46:53

Sacar números de cadenas de caracteres.
 
Parece una pregunta un tanto tonta, ya que con 2 bucles for y recorriéndola se puede hacer, pero me preguntaba si pudiera existir alguna función en delphi que sea más efectiva y menos medieval para hacerlo.

Como ejemplo, lo que quiero hacer es sacar los numeros que vienen detras de unas letras concretas en una cadena de caracteres:

DHS274HGL23JH41234HGL412YG

Las letras concretas aquí (p.e.) serían HGL. Por lo que los números que en este caso necesitaría sacar y guardar son el 23 y el 412.

Un saludo y gracias!

marcoszorrilla 30-11-2010 15:06:51

Si mantiene la posición puedes utilizar Copy

Código Delphi [-]
xx:=Copy(Cadena,4,3);


Un Saludo.

Neftali [Germán.Estévez] 30-11-2010 17:38:25

Pues a mi sólo se me ocurre con 2 bucles.
El primero para encontrar y recorrer las ocurrencias de la cadena buscada (suponiendo que hay varias) y el segundo para extraer los números antes de la csiguiente letra (que por lo que veo pueden tener longitud indeterminada).

ecfisa 30-11-2010 19:09:08

Hola McK.

Estoy de acuerdo con Neftali, se necesitan dos ciclos.

Pero mas eficiente que usar dos for es:
Código Delphi [-]
function ExtractNum(Sub, Str: string): TStrings;
var
  i, p: Integer;
begin
  Result:= TStringList.Create;
  p:= 1;
  while p <> 0 do
  begin
    p:= Pos(Sub, Str);
    if p > 0 then
    begin
      Inc(p, Length(Sub));
      i:= 1;
      while Str[p + i] in ['0'..'9'] do Inc(i);
      Result.Add(Copy(Str, p, i));
      Inc(p, i);
      Str:= Copy(Str, p, MaxInt);
    end;
  end;
end;

Ejemplo de llamada:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
const
  Cadena = 'HGL44DHS274HGL23JHGL41234HGL412YGHGL555XADSF1AHG12HGL999';
begin
  Memo1.Lines:= ExtractNum('HGL', Cadena);
end;

Saludos. :)

Estifmauin 01-12-2010 00:05:25

Otro enfoque, más legible, pero creo que menos eficiente:

Código Delphi [-]
function SoloNumeros(s:string):string;
var
  n :integer;
begin
  result:='';
  n:=1;
  while (n <= Length(s))
  and (s[n] in ['0'..'9']) do begin
    result:=result+s[n];
    Inc(n);
  end;
end;

function ExtraerNumeros(cadena, prefijo :string) :TStrings;
var
  i :integer;
begin
  result:=TStringList.Create;
  result.CommaText:=StringReplace(cadena,prefijo,',',[rfReplaceAll]);
  for i:=result.Count -1 downto 0 do begin
    result[i]:=SoloNumeros(result[i]);
    if result[i] = '' then result.Delete(i);
  end;
end;
Para llamarlo:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
begin
  memo1.Lines:=ExtraerNumeros('HGL44DHS274HGL23JHGL41234HGL412YGHGL555XADSF1AHG12HGL999','HGL');
end;
Es más legible, pero insisto en que menos eficiente, y requiere uses StrUtils

McK 01-12-2010 13:44:41

Perfecto, gracias a todos. Aunque no haya una instrucción de Delphi eso está bastante simplificado. Yo lo tenía algo peor implementado.

Un saludo!

roman 01-12-2010 16:23:58

Desafortunadamente delphi no cuenta con un manejo de expresiones regulares, al menos delphi 7. Por ejemplo, en PHP este problema se resuelve así:

Código PHP:

<?php
$s 
'DHS274HGL23JH41234HGL412YG';
preg_match_all('/HGL([0-9]+)/'$s$matches);
var_dump($matches[1]);
?>

// Saludos

McK 02-12-2010 11:16:52

Cita:

Empezado por ecfisa (Mensaje 383658)
Hola McK.

Estoy de acuerdo con Neftali, se necesitan dos ciclos.

Pero mas eficiente que usar dos for es:

Código Delphi [-]

function ExtractNum(Sub, Str: string): TStrings;
var
i, p: Integer;
begin
Result:= TStringList.Create;
p:= 1;
while p <> 0 do
begin
p:= Pos(Sub, Str);
if p > 0 then
begin
Inc(p, Length(Sub));
i:= 1;
while Str[p + i] in ['0'..'9'] do Inc(i);
Result.Add(Copy(Str, p, i));
Inc(p, i);
Str:= Copy(Str, p, MaxInt);
end;
end;
end;


Ejemplo de llamada:

Código Delphi [-]

procedure TForm1.Button1Click(Sender: TObject);
const
Cadena = 'HGL44DHS274HGL23JHGL41234HGL412YGHGL555XADSF1AHG12HGL999';
begin
Memo1.Lines:= ExtractNum('HGL', Cadena);
end;


Saludos.

No me está funcionando tu código amigo. Siempre me detecta el primer substring por lo que se queda en un bucle infinito..

ecfisa 02-12-2010 11:55:45

Cita:

Empezado por McK (Mensaje 383811)
No me está funcionando tu código amigo. Siempre me detecta el primer substring por lo que se queda en un bucle infinito..

Mi amigo, acabo de copiar y pegar el código de la función y funciona correctamente.

Te adjunto la prueba:
Código Delphi [-]
function ExtractNum(Sub, Str: string): TStrings;
var
  i, p: Integer;
begin
  Result:= TStringList.Create;
  p:= 1;
  while p <> 0 do
  begin
    p:= Pos(Sub, Str);
    if p > 0 then
    begin
      Inc(p, Length(Sub));
      i:= 1;
      while Str[p + i] in ['0'..'9'] do Inc(i);
      Result.Add(Copy(Str, p, i));
      Inc(p, i);
      Str:= Copy(Str, p, MaxInt);
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
const
  Cadena = 'XX979ASDB12XX77DT12ADSXX99199ABCXX8838xx33'; // Con la del ejemplo anterior también funciona OK
begin
  Memo1.Lines:= ExtractNum('xx', Cadena); // muestra 33
  ShowMessage('FIN');
  Memo1.Lines:= ExtractNum('', Cadena);  // no muestra nada
  ShowMessage('FIN');
  Memo1.Lines:= ExtractNum('XX', Cadena); // muestra 979, 77, 99199, 8838
  ShowMessage('FIN');
  Memo1.Lines:= ExtractNum('xy', Cadena); // no muestra nada
  ShowMessage('FIN');
end;

¿ Podrías poner un ejemplo que te dé el ciclo infinito ? Así puedo evaluarlo.

Saludos. :)

McK 02-12-2010 23:27:27

Cita:

Empezado por ecfisa (Mensaje 383815)
Mi amigo, acabo de copiar y pegar el código de la función y funciona correctamente.

Te adjunto la prueba:
Código Delphi [-]function ExtractNum(Sub, Str: string): TStrings; var i, p: Integer; begin Result:= TStringList.Create; p:= 1; while p <> 0 do begin p:= Pos(Sub, Str); if p > 0 then begin Inc(p, Length(Sub)); i:= 1; while Str[p + i] in ['0'..'9'] do Inc(i); Result.Add(Copy(Str, p, i)); Inc(p, i); Str:= Copy(Str, p, MaxInt); end; end; end; procedure TForm1.Button1Click(Sender: TObject); const Cadena = 'XX979ASDB12XX77DT12ADSXX99199ABCXX8838xx33'; // Con la del ejemplo anterior también funciona OK begin Memo1.Lines:= ExtractNum('xx', Cadena); // muestra 33 ShowMessage('FIN'); Memo1.Lines:= ExtractNum('', Cadena); // no muestra nada ShowMessage('FIN'); Memo1.Lines:= ExtractNum('XX', Cadena); // muestra 979, 77, 99199, 8838 ShowMessage('FIN'); Memo1.Lines:= ExtractNum('xy', Cadena); // no muestra nada ShowMessage('FIN'); end;


¿ Podrías poner un ejemplo que te dé el ciclo infinito ? Así puedo evaluarlo.

Saludos. :)

Gracias compañero ya lo he arreglado con un auxiliar. No sé porque mi variable p no pasaba de la primera substring pero es tu código tal cual... con mi aux lo que hago es copiarme la cadena y a la que va encontrando las substrings las va borrando, por lo que a la fuerza tiene que coger la siguiente. Tengo Delphi 7, quizas por la versión.... :confused:

ecfisa 02-12-2010 23:40:26

Cita:

Empezado por McK (Mensaje 383887)
Gracias compañero ya lo he arreglado con un auxiliar. No sé porque mi variable p no pasaba de la primera substring pero es tu código tal cual... con mi aux lo que hago es copiarme la cadena y a la que va encontrando las substrings las va borrando, por lo que a la fuerza tiene que coger la siguiente. Tengo Delphi 7, quizas por la versión.... :confused:

Un detalle McK, si bien no me pasó lo del bucle infinito, descubrí un fallo en el código.

En la cadena anterior:
Cita:

XX979ASDB12XX77DT12ADSXX99199ABCXX8838xx33
Si usas: ExtractNum('AS', Cadena) -> te devuelve: 'B'.

Es por que inicialicé mal el contador de ocurrencias numéricas y si o sí me pone un caracter aunque no sea un número.
Hay que inicializar distinto a 'i':
Código Delphi [-]
...
  begin
      Inc(p, Length(Sub));
      //  i:= 1;      BORRAR LINEA 
      i:= 0;  // NUEVA LINEA
  ...


Un saludo. :)

mamcx 03-12-2010 04:02:10

Cita:

Empezado por roman (Mensaje 383745)
Desafortunadamente delphi no cuenta con un manejo de expresiones regulares

En la version actual si. Ademas que agregarle la libreria es cosa de niños.

McK 03-12-2010 09:01:02

Cita:

Empezado por ecfisa (Mensaje 383889)
Un detalle McK, si bien no me pasó lo del bucle infinito, descubrí un fallo en el código.

En la cadena anterior:

Si usas: ExtractNum('AS', Cadena) -> te devuelve: 'B'.

Es por que inicialicé mal el contador de ocurrencias numéricas y si o sí me pone un caracter aunque no sea un número.
Hay que inicializar distinto a 'i':
Código Delphi [-]... begin Inc(p, Length(Sub)); // i:= 1; BORRAR LINEA i:= 0; // NUEVA LINEA ...



Un saludo. :)

Vaaaaale ya sé lo que pasaba!!! Que despiste.... lo de i:= 0 ya me dí cuenta cuando lo depuraba..

Código:

function ExtractNum(Sub, Str: string): TStrings;
var
  i, p: Integer;
begin
  Result:= TStringList.Create;
  p:= 1;
  while p <> 0 do
  begin
    p:= Pos(Sub, Str);
    if p > 0 then
    begin
      Inc(p, Length(Sub));
      i:= 1;
      while Str[p + i] in ['0'..'9'] do Inc(i);
      Result.Add(Copy(Str, p, i));
      Inc(p, i);
      Str:= Copy(Str, p, MaxInt); // Esta línea no la había metido!!! 
    end;                          // De todas formas en mi procedure he metido esto tal cual sin crear ninguna función
  end;                            // y por no modificar mi cadena por eso he utilizado el auxiliar.
end;

Mil gracias y perdona por el mareo!!
Saludos :)

roman 03-12-2010 16:54:02

Cita:

Empezado por mamcx (Mensaje 383909)
En la version actual si. Ademas que agregarle la libreria es cosa de niños.

Entonces, en la versión actual, definitivamente se impone el uso de expresiones regulares para resolver problemas como éste

También tienes razón en que puede usarse una librería (biblioteca por si Al lee esto) externa, pero cuando se requiere para apenas un uso puntual, como que se siente que se está matando una pulga a cañonazos :)

// Saludos

Delfino 03-12-2010 21:24:31

Cita:

Empezado por roman (Mensaje 383745)
Desafortunadamente delphi no cuenta con un manejo de expresiones regulares, al menos delphi 7.

Ya lo tiene en Delphi XE, y aqui un ejemplo..


La franja horaria es GMT +2. Ahora son las 20:35:31.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi