• isNumeric (Crecreacion de la funcion de VB6).

 #314479  por BlackZeroX
 16 Ago 2011, 22:29
Se estan realizando varios retos en el foro elhacker.net he participado en en el reto de recrear la funcion isnumeric, pero en vb6. la siguiente funcion tiene una alternativa para vb6 mas rapida que la funcion nativa de vb6.

Antes de Le digo que se trabajan las funciones a nivel Bit.

Funcion en VB6
Código: [ Debe registrarse para ver este enlace ]

http://foro.elhacker.net/programacion_visual_basic/reto_reemplazo_de_funcion_isnumeric-t336067.0.html;msg1652210#msg1652210

y aqui les dejo la traduccion en C (Esta configurada para trabajar con las Strings de VB6)
Código: [ Debe registrarse para ver este enlace ]

/**
    @Autor          BlackZeroX
    @Web            http://infrangelux.sytes.net/blog/
    @Reference      http://foro.elhacker.net/programacion_visual_basic/reto_reemplazo_de_funcion_isnumeric-t336067.0.html;msg1652210#msg1652210
    @Description    Libreria para verificar si una Cadena de texto ANSI/UNICODE es numerica con los siguientes formatos:
                    * ###e[+/-]###  {+/-646.45e+546,45}.
                    * ###d[+/-]###  {+/-646.45d+546,45}.
                    * Base 16       {&H4561abcdef}.
                    * Base 10       {+/-456,541.456,545}.
    @Returns        0 si la cadena no contiene ningun formato.
                    1 si la cadena pertenece a algun tipo de formato numerico.
**/

#define PUNTO_DECIMAL     0x10000
#define SIGNO_SRC         0x20000
#define NUMBER_HEX        0x40000
#define NUMBER_HEX_ZERO   0x80000
#define NUMBER_HEX_FLAGS  (NUMBER_HEX | NUMBER_HEX_ZERO)
#define NUMBER_POW        0x100000
#define NUMBER_POW_FINISH 0x200000
#define NUMBER_POW_FLAGS  (NUMBER_POW | NUMBER_POW_FINISH)
#define NUMBER_OF_OK      0x400000
#define NUMBER_OF_FINISH  0x800000
#define NUMBER_OF_FLAGS   (NUMBER_OF_OK | NUMBER_OF_FINISH)

DLL_EXPORT int __stdcall IsNumericA (char *pStr) { return IsNumericEx(pStr, 1); }
DLL_EXPORT int __stdcall IsNumericW (char *pStr) { return IsNumericEx(pStr, 2); }
int IsNumericEx (char *pStr, int iStep) {
unsigned int i       = 0x0,  //  For()
             iLn     = 0x0,  //  Longitud de pStr.
             iData   = 0x0;  //  Xor, Switcher, Contador (QWord).

    if (!pStr)
        return 0;

    iLn = *((int*)(pStr - 0x4));

    if (!iLn)
        return 0;

    for (i = 0; i < iLn; i += iStep) {
        if ((iData & NUMBER_HEX) == NUMBER_HEX) {
            if (((*pStr >= 0x30) && (*pStr <= 0x39)) ||
               ((*pStr >= 0x61) && (*pStr <= 0x66)) ||
               ((*pStr >= 0x41) && (*pStr <= 0x46))) {  //  Numeros Hexadecimales
                if ((iData & NUMBER_OF_FLAGS) == 0x0)   //  Ceros a la izquierda
                    iData |= (*pStr == 0x30) ? NUMBER_HEX_ZERO : NUMBER_OF_OK;

                switch (iData & NUMBER_OF_FLAGS) {
                    case NUMBER_OF_OK:
                        iData++;
                        if ((iData & 0xFF) == 0x11)
                            return 0;   //  QWord (Max Double)
                        iData |= NUMBER_OF_OK;
                        if ((iData | NUMBER_HEX_FLAGS) == NUMBER_HEX_FLAGS)
                            iData ^= NUMBER_HEX_ZERO;
                        break;

                    case NUMBER_OF_FINISH:
                    case NUMBER_OF_FLAGS:
                        return 0;
                        break;
               }
            } else {
                switch ((int)(*pStr)) {
                    case 0x9:
                    case 0xA:
                    case 0xB:
                    case 0xC:
                    case 0xD:
                    case 0x24:
                    case 0x20:
                    case 0xA0:  //   Espacios en Blanco
                        if ((iData | NUMBER_HEX_FLAGS) == NUMBER_HEX_FLAGS)
                            iData = ((iData ^ NUMBER_HEX_ZERO) | NUMBER_OF_OK);
                        if ((iData & NUMBER_OF_FLAGS) == NUMBER_OF_OK)
                            iData |= NUMBER_OF_FINISH;
                        break;

                    case 0x0:    //  NULL Indica que se termina la cadena.
                        if ((iData & NUMBER_OF_FLAGS) == NUMBER_OF_FINISH)
                            return 0;
                        i = iLn; //  Exit For.
                        break;

                    default:
                        return 0;
                        break;
                }
            }
        } else {
            if ((*pStr >= 0x30) && (*pStr <= 0x39)) {
                iData |= NUMBER_OF_OK;
                if ((iData & NUMBER_OF_FINISH) == NUMBER_OF_FINISH)
                    return 0;
                if ((iData & NUMBER_POW_FLAGS) == NUMBER_POW)
                    iData |= NUMBER_POW_FINISH;

            } else {
                switch ((int)*pStr) {
                    case 0x0:    //  NULL Indica que se termina la cadena.
                        if ((iData & NUMBER_POW_FLAGS) == NUMBER_POW)
                            return 0;
                        i = iLn;    //  Exit For.
                        break;

                    case 0x2E:   //  "."  Solo 1
                        if (((iData & NUMBER_POW_FLAGS) == NUMBER_POW) ||
                           ((iData & NUMBER_OF_FINISH) == NUMBER_OF_FINISH) ||
                           ((iData & PUNTO_DECIMAL) == PUNTO_DECIMAL))
                            return 0;
                        iData |= PUNTO_DECIMAL;
                        break;

                    case 0x2B:
                    case 0x2D: //  "+|-" Solo 1
                        if ((iData & NUMBER_POW_FLAGS) == NUMBER_POW)
                            iData |= NUMBER_POW_FINISH;

                        else
                            if (((iData & NUMBER_OF_OK) == NUMBER_OF_OK) ||
                               ((iData & PUNTO_DECIMAL) == PUNTO_DECIMAL) ||
                               ((iData & SIGNO_SRC) == SIGNO_SRC))
                            return 0;

                        if ((iData & NUMBER_OF_FINISH) == NUMBER_OF_FINISH)
                            return 0;

                        iData |= SIGNO_SRC;
                        break;

                    case 0x2C:
                        if ( !((iData & NUMBER_OF_OK) == NUMBER_OF_OK) ||
                              ((iData & NUMBER_POW_FLAGS) == NUMBER_POW))
                            return 0;
                        break;

                    case 0x9:
                    case 0xA:
                    case 0xB:
                    case 0xC:
                    case 0xD:
                    case 0x24:  //  Solo se permiten al inicio de un Numero (Espacios en Blanco).
                        if (((iData & PUNTO_DECIMAL) == PUNTO_DECIMAL) ||
                           ((iData & NUMBER_OF_FINISH) == NUMBER_OF_FINISH) ||
                           ((iData & NUMBER_OF_OK) == NUMBER_OF_OK) ||
                           ((iData & NUMBER_POW_FLAGS) == NUMBER_POW))
                            return 0;
                        break;

                    case 0xA0:
                    case 0x20: //  Se permiten al Inicio/final de un numero.
                        if ((iData & NUMBER_OF_OK) == NUMBER_OF_OK)
                            iData |= NUMBER_OF_FINISH;
                        else
                            if (((iData & PUNTO_DECIMAL) == PUNTO_DECIMAL) ||
                               ((iData & NUMBER_POW_FLAGS) == NUMBER_POW))
                                return 0;
                        break;

                    case 0x26:   //  Es un Numero Hexadecimal
                        if (((iData & NUMBER_OF_FINISH) == NUMBER_OF_FINISH) ||
                           ((iData & NUMBER_OF_OK) == NUMBER_OF_OK) ||
                           ((iData & SIGNO_SRC) == SIGNO_SRC) ||
                           ((iData & PUNTO_DECIMAL) == PUNTO_DECIMAL) ||
                           ((iData & NUMBER_POW_FLAGS) == NUMBER_POW))
                            return 0;

                        i++;
                        pStr += iStep;

                        if ((*pStr == 0x48) || (*pStr == 0x68)) {
                            iData |= NUMBER_HEX;
                            iData ^= 0xFF000000;
                        } else {
                            --i;
                            pStr -= iStep;
                        }
                        break;

                    case 0x44:
                    case 0x45:
                    case 0x64:
                    case 0x65:     //  Numeros en Formato ###e-###, ###e+###
                        if (((iData & NUMBER_OF_FINISH) == NUMBER_OF_FINISH) ||
                           ((iData & NUMBER_POW) == NUMBER_POW))
                            return 0;
                        if ((iData & NUMBER_OF_OK) == NUMBER_OF_OK) {
                            iData |= NUMBER_POW;
                            if ((iData & SIGNO_SRC) == SIGNO_SRC)
                                iData ^= SIGNO_SRC; //  Permitimos nuevamente los signos "+" y "-".
                        } else {
                            return 0;
                        }
                        break;

                    default:
                        return 0;
                        break;

                }   //  switch()
            }   //  if()
        }   //  if()
        pStr += iStep;
    }   //  For()

    switch (iData & NUMBER_OF_FLAGS) {
        case NUMBER_OF_OK:
        case NUMBER_OF_FLAGS:
            return 1;
            break;

        default:
            switch (iData & NUMBER_HEX_FLAGS) {
                case NUMBER_HEX_FLAGS:
                    return 1;
            }
    }

    return 0;
}

Dulces Lunas!¡.