Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Función que devuelva la posición del primer carácter que no esté en la máscara de bus (https://www.clubdelphi.com/foros/showthread.php?t=95095)

aguml 26-02-2021 19:24:38

Función que devuelva la posición del primer carácter que no esté en la máscara de bus
 
Buenas, pues eso, hay alguna función en C para buscar unos caracteres en una cadena y que devuelve la posición de la primera o última de cualquier carácter pero yo quiero lo contrario, o sea, Supongamos que la función se llama buscar, pues:
Buscar("abc", "acabo");
Devolviese la posición del carácter 'o' ya que no está entre los caracteres indicados en la máscara de busqueda, no sé si me explico.
¿Conocen algo así?
Lo que quiero hacer es filtrar lo que se pegue desde el portapapeles a un tedit y que solo sean caracteres hexadecimales.

ecfisa 26-02-2021 21:13:54

Hola.

Si se diera que hay dos o más caracteres que no existen en la máscara de búsqueda, ¿ Cuál debería devolver ?

Saludos :)

aguml 26-02-2021 22:28:52

Eso es lo de menos ya que si hay uno no válido la idea es no permitir el pegado.

movorack 26-02-2021 22:57:42

Podrías usar una expresión regular para hacer la busqueda.

Código Delphi [-]
function BuscarPattern(Pattern, Input: string): string;
  var
    i: integer;
    lRegex: TRegEx;
begin
  Result := '';
  lRegex.Create(Pattern, [roIgnoreCase]);
  if lRegex.IsMatch(Input) then
    for i := 0 to lRegex.Matches(Input).Count - 1 do
      Result := Result + lRegex.Matches(Input)[i].Value;
end;

El valor de búsqueda lo conviertes a un pattern válido. Por ej, "abc" podría ser "[a]|[b]|[c]". De esa manera encontrará "acab" de "acabo"

Ejemplo colores hexadecimales:
Texto de busqueda: "#0123456789ABCDEF"
Pattern: "[#]|[0]|[1]|[2]|[3]|[4]|[5]|[6]|[7]|[8]|[9]|[A]|[b]|[C]|[D]|[E]|[F]" (Que podría resumirse en "[#]|[0-9]|[A-F]")
Resultados
Código:

ORIGEN      RESULTADO
-#ffff00.,  #ffff00
-#e5e500[]  #e5e500
-#cccc00`^  #cccc00
-#b2b200{}  #b2b200
-#ff0000%  #ff0000
-#e50000$  #e50000
-#cc0000"  #cc0000
-#b20000!  #b20000
-#0000ffq  #0000ff
-#1919ffw  #1919ff
-#3232ffr  #3232ff
-#4c4cfft  #4c4cff


aguml 26-02-2021 23:15:14

Pero yo no quiero filtrar, lo que quiero es que si el formato no es válido no se pegue nada de nada.
Podría usar strspn para ello pero si la vcl tiene algo así me ahorro de añadir la librería string solo para eso.

ecfisa 28-02-2021 00:41:10

Hola.

No conozco alguna función de la VCL que haga lo que buscas. Y si deseas prescindir de la librerá string, tendrías que hacer una función en C que lo realize, vg.r.:

Código PHP:

/* 
   devuelve la posición del caracter que no está
   en la máscara, o -1 si todos los caracteres coinciden
   con la máscara 
*/
.
int buscar(char *mskchar *str)
 {
  
int ijx;
  for (
i=0str[i] != '\0'i++) {
    
0;
    for(
j=0msk[j] != '\0'j++)
      if (
msk[j] == str[i]) 1;
    if (!
x) return i;
  }
  return -
1;


Por ejemplo:
Código PHP:

printf("\n%d\n",buscar("abc""acaba")); 

devuelve -1
y
Código PHP:

printf("\n%d\n",buscar("abc""acabo")); 

devuelve 4


Saludos :)

aguml 03-03-2021 11:08:47

Bueno, al final lo he pensado mejor y voy a hacer que imprima solo caracteres válidos pero la cosa es que consigo filtrarlo pero me lo muestra al final de lo que pego con Ctrl + V en vez de sustituir lo que pego por lo filtrado. Tengo esto:
Código PHP:

void __fastcall TForm1::EditValue1KeyPress(TObject *SenderSystem::WideChar &Key)
{
    if(
Key == 0x16){
        if(
Clipboard()->HasFormat(CF_TEXT)){
            
String CBText Clipboard()->AsText;
            
EditValue1->Text SuprimirCaracteresInvalidos(CBText.UpperCase());
        }
    }else if((
Key '0' || (Key '9' && (Key 'A' || Key 'F'))) && Key != '\b' && Key != 0x03 && Key != 0x18)
        
Key NULL;
}
//---------------------------------------------------------------------------

String TForm1::SuprimirCaracteresInvalidos(String input)
{
    
int ij;
    
String output "";
    
String mask "0123456789ABCDEF";

    for(
1input.Length() > && input.Length(); i++){
        for(
j=1mask.Length(); j++){
            if(
input[i] == mask[j]){
                
output += (WideString)input[i];
            }
        }
    }
    return 
output;


Además también me falta que al pegar con el menú contextual tenga el mismo comportamiento. El menú contextual o popup no lo he creado yo, es el de Windows y no se como hacer eso.

aguml 03-03-2021 20:17:31

Lo del menú contextual lo he solucionado con mi propio popupmenu y gestionando ahí pero lo de Ctrl+V no lo consigo.


La franja horaria es GMT +2. Ahora son las 11:19:27.

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