Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: BlackZeroX en 12 Enero 2011, 22:55 pm



Título: [ANSI C] Split(), strlen(), mid(), Instr(), strcpy().
Publicado por: BlackZeroX en 12 Enero 2011, 22:55 pm
.
Esta es la version de split() ya esta corregida debugeada y sirve en todo caso.

Quien no sepa usar Vectores en C esta muerto ( ** ), es decir Puntero a Puntero.

Corregido por segunda vez:

Código
  1.  
  2. #include<stdlib.h>
  3. #include<stdio.h>
  4.  
  5. #ifndef bool
  6. typedef enum bool { false, true } bool;
  7. #endif
  8.  
  9. unsigned int rectific_num(unsigned int vval,unsigned int vmin,unsigned int vmax);
  10. bool fix_numbers_range(unsigned int* vIndexIni,unsigned int* vIndexEnd, unsigned int* vLen, unsigned int vMin, unsigned int vMax);
  11. unsigned long strlen(char* string);
  12. unsigned long instr(unsigned long start,char* string1,char* string2);
  13. char* mid(char* str, unsigned int start, unsigned int len);
  14. char* strcpy(char* str_dest,char* str_src);
  15. char** split(char* str, char* delimiter, long* limit);
  16.  
  17. int main()
  18. {
  19.  
  20.    long lim=-1;
  21.    long i=0;
  22.    char **array = split((char*)".Este.es.Hola.Mundo.Hola.mundo.",(char*)".",&lim);
  23.  
  24.    if ( array != 0 )
  25.    {
  26.        printf("Index\tValue\n",lim);
  27.        for ( i=0 ; i <= lim ;i++ )
  28.        {
  29.            printf("%d\t%s\n",i,array[i]);
  30.            free (array[i]);
  31.        }
  32.        free(array);
  33.    }
  34.    getchar();
  35.    return 0;
  36. }
  37.  
  38. unsigned int rectific_num(unsigned int vval,unsigned int vmin,unsigned int vmax)
  39. /**
  40.     Corrige [vVal] con respecto a un minimo y a un maximo valor.
  41.     By BlackZeroX ( http://Infrangelux.sytes.net/ )
  42. **/
  43. {
  44.    if (vval < vmin)
  45.        return vmin;
  46.    else if ( vval > vmax )
  47.        return vmax;
  48.    else
  49.        return vval;
  50. }
  51.  
  52. bool fix_numbers_range(unsigned int* vIndexIni,unsigned int* vIndexEnd, unsigned int* vLen, unsigned int vMin, unsigned int vMax)
  53. /**
  54.     Corrige los rangos de [vIndexIni],[vIndexEnd], [vLen] con respecto a un minimo y a un maximo valor.
  55.     [vLen] corresponde a la distancia entre [vIndexIni] y [vIndexEnd].
  56.     Se retorna false solo si [vMax] es menor que que [vIndexIni] o que [*vLen] es igual o menor a [0]
  57.     By BlackZeroX ( http://Infrangelux.sytes.net/ )
  58. **/
  59. {
  60.    if ( vMax >= *vIndexIni && *vLen != 0 )
  61.    {
  62.        *vIndexIni = rectific_num(*vIndexIni,vMin,vMax);
  63.        *vIndexEnd = rectific_num(*vIndexIni + *vLen,*vIndexIni,vMax);
  64.        *vLen= *vIndexEnd - *vIndexIni+1;
  65.        return ( (*vLen > 0) ? true: false);
  66.    } else {
  67.        return false;
  68.    }
  69. }
  70.  
  71. unsigned long strlen(char* string)
  72. /**
  73.     Retorna la longitud de [string]
  74.     By BlackZeroX ( http://Infrangelux.sytes.net/ )
  75. **/
  76. {
  77.    unsigned long i=0;
  78.    while (*(string++)) i++;
  79.    return i;
  80. }
  81.  
  82. char* strcpy(char* str_dest,char* str_src)
  83. /**
  84.     Copia [*str_src] a [*str_dest].
  85.     Retorna el puntero a [str_dest]
  86.     By BlackZeroX ( http://Infrangelux.sytes.net/ )
  87. **/
  88. {
  89.    char *copyreturn = str_dest;
  90.    while(*(str_dest++)=*(str_src++));
  91.    return copyreturn;
  92. }
  93.  
  94. unsigned long instr(unsigned long start,char* string1,char* string2)
  95. /**
  96.     [Start] indica la posicion inicial donde se empesara a buscar en [string1]
  97.     Retorna la posicion de [*string2] en [*string1].
  98.     By BlackZeroX ( http://Infrangelux.sytes.net/ )
  99. **/
  100. {
  101.    unsigned long  q,c,limit;
  102.    q=c=limit=0;
  103.    long ls2len=0;
  104.  
  105.    ls2len = strlen(string2) - 1;
  106.  
  107.    if ( ls2len >= 0 )
  108.    {
  109.        limit = strlen(string1)-ls2len;
  110.  
  111.        if ( limit > 1 )
  112.        {
  113.            q = start-1;
  114.            while ( q < limit )
  115.            {
  116.                while ( string1[q+c] == string2[c] )
  117.                    if ( (c++) == (unsigned long)ls2len )
  118.                        return q+1;
  119.                q+=c+1;
  120.                c=0;
  121.            }
  122.        }
  123.    } else if (*string1 > '\0') {
  124.        return 1;
  125.    }
  126.    return 0;
  127. }
  128. char* mid(char* str, unsigned int start, unsigned int len)
  129. /**
  130.     Se obtiene el fragmento deseado de [*str]
  131.     [Start] Indica desde donde se empesara
  132.     [Len] Indica la distancia.
  133.     Retorna el puntero al clon del fragmento deseado de [*str]
  134.     By BlackZeroX ( http://Infrangelux.sytes.net/ )
  135. **/
  136. {
  137.    char* pch_t = 0;
  138.    unsigned int ul_str=strlen(str);
  139.    unsigned int ul_end=start+len;
  140.    start--;
  141.    if ( fix_numbers_range(&start,&ul_end,&len,0,ul_str) == true )
  142.    {
  143.        if ( (pch_t = (char*)malloc(sizeof(char)*len)) != 0 )
  144.        {
  145.            for (ul_str=0;ul_str < (len-1) ;start++,ul_str++ )
  146.                pch_t[ul_str] = str[start];
  147.            pch_t[len-1]='\0';
  148.        }
  149.    } else {
  150.        if ( (pch_t = (char*)malloc(sizeof(char))) != 0 )
  151.            pch_t[0]='\0';
  152.    }
  153.    return pch_t;
  154. }
  155.  
  156. char** split(char* str, char* delimiter, long* limit)
  157. /**
  158.     Separa a [*str] cada vez que se encuentre a [*delimiter] con un limite definido en [*limit]
  159.     Si [*limit] = -1 se crea un Maximo mayor a [-1] en el indice del vector retornado
  160.     Si [*limit] > -1 Se indica y establece un indice mayor [pero no fijo] del indice mayor del vector retornado
  161.     En ambos casos [*limit] retorna el Indice maximo del vector retornado por la funcion y la funcion retorna el puntero a el vector retultante.
  162.     En casos contrarios no crea un vector y retorna 0 y [*limit] = [-1]
  163.     By BlackZeroX ( http://Infrangelux.sytes.net/ )
  164. **/
  165. {
  166.    unsigned int ui_lp  =1;
  167.    unsigned int ui_inc =1;
  168.    unsigned int ui_lns =0;
  169.    unsigned int ui_del =0;
  170.    unsigned long ui_ub =0;
  171.    char **pi_out       =0;
  172.  
  173.    if ( *limit >= -1 )
  174.    {
  175.        if ( strlen(delimiter) == 0 )
  176.            delimiter = (char*)" ";
  177.        ui_lns = strlen(str);
  178.        ui_del = strlen(delimiter);
  179.        pi_out = (char**)malloc(sizeof(char*));
  180.        for(;pi_out!=0;)
  181.        {
  182.            if ( ui_ub == *limit )
  183.            {
  184.                pi_out[ui_ub] = mid(str, ui_lp,ui_lns);
  185.                ui_ub = *limit;
  186.                break;
  187.            }
  188.            ui_inc = instr(ui_inc, str, delimiter);
  189.            if ( ui_inc == 0 )
  190.            {
  191.                pi_out[ui_ub] = mid(str, ui_lp,ui_lns);
  192.                break;
  193.            }
  194.            pi_out[ui_ub] = mid(str, ui_lp, ui_inc - ui_lp);
  195.            pi_out = (char**)realloc(pi_out,sizeof(char*)*(++ui_ub+1));
  196.            ui_lp = ui_inc + ui_del;
  197.            ui_inc = ui_lp;
  198.        }
  199.        *limit = ui_ub;
  200.        return pi_out;
  201.    }
  202.    *limit=-1;
  203.    return 0;
  204. }
  205.  
  206.  

Nota.: Si alguien ve algun fallo por favor de no golpearme gracias!¡.

Temibles Lunas!¡.


Título: Re: [ANSI C] Split(), strlen(), mid(), Instr()
Publicado por: Littlehorse en 12 Enero 2011, 23:44 pm
El propósito de los comentarios es aclarar el código y no lo contrario. Si quieres poner créditos los puedes agregar al principio, pero poner spam en los comienzos de cada función sinceramente invitan a no seguir leyendo el código.

Por otro lado, el tipo de dato bool no existe en C, solo en C++, y viendo que estas utilizando las cabeceras de C, deberías definir el tipo de dato bool por tu cuenta. No he leido el resto del código; utilizar typedefs ayuda a que el código sea mas comprensible a primera vista.

Saludos





Título: Re: [ANSI C] Split(), strlen(), mid(), Instr(), strcpy().
Publicado por: leogtz en 13 Enero 2011, 01:28 am
Siempre retornas 1 en el main() eso es incorrecto, para el sistema operativo tu programa no funciona bien.

Código
  1. unsigned long strlen(char* string)
  2. {
  3.    unsigned long i=0;
  4.    while (*string++)
  5.    i++;
  6.    return i;
  7. }


Título: Re: [ANSI C] Split(), strlen(), mid(), Instr(), strcpy().
Publicado por: BlackZeroX en 13 Enero 2011, 01:43 am
.
Les agradezco sus comentarios pero acabo de ver un error, y ahorita solo me intriga que me salte este error.

Código
  1.  
  2. int main()
  3. {
  4.  
  5.    long lim=-1;
  6.    long limback=lim;
  7.    char **array = split((char*)"Este es un hola mundo desde InfrAngeluX-Soft",(char*)"u",&lim);
  8.  
  9.    if ( array != 0 )
  10.    {
  11.        limback=lim;
  12.        for (; lim>-1 ;lim-- )
  13.            printf ("%d \t %s \n", lim, array[lim] );
  14.  
  15.        for (; limback>0 ;limback-- )
  16.            free (array[limback]);
  17.        free(array);
  18.    }
  19.    getchar();
  20.    return 0;
  21. }
  22.  
  23.  

Código:
Heap block at 003E1750 modified at 003E175E past requested size of 6

Nota: seguire viendo por que me salta...

Dulces Lunas!¡.


Título: Re: [ANSI C] Split(), strlen(), mid(), Instr(), strcpy().
Publicado por: Psyke1 en 13 Enero 2011, 02:09 am
Hola Black! :D
Parece que te estás pasando ya a Cpp eh? ;)

Me gusta tu función Instr(), me recuerda a la que hice yo hace días en vb6 :silbar: :
Código
  1. unsigned long instr(unsigned long start,char* string1,char* string2)
  2. /*
  3.     [Start] indica la posicion inicial donde se empesara a buscar en [string1]
  4.     Retorna la posicion de [*string2] en [*string1].
  5.     By BlackZeroX ( http://Infrangelux.sytes.net/ )
  6. */
  7. {
  8.    unsigned long  q,c,limit;
  9.    q=c=limit=0;
  10.    long ls2len=0;
  11.  
  12.    ls2len = strlen(string2) - 1;
  13.  
  14.    if ( ls2len >= 0 )
  15.    {
  16.        limit = strlen(string1)-ls2len;
  17.  
  18.        if ( limit > 1 )
  19.        {
  20.            q = start-1;
  21.            while ( q < limit )
  22.            {
  23.                while ( string1[q+c] == string2[c] )
  24.                    if ( (c++) == (unsigned long)ls2len )
  25.                        return q+1;
  26.                q+=c+1;
  27.                c=0;
  28.            }
  29.        }
  30.    } else if (*string1 > '\0') {
  31.        return 1;
  32.    }
  33.    return 0;
  34. }

Código
  1. Option Explicit
  2. Option Base 0
  3.  
  4. Private Function myInstr&(ByVal Start&, ByVal String1$, ByVal String2$)
  5. Dim bvString1() As Byte, bvString2() As Byte
  6. Dim ls2Len&, lLimit&
  7. Dim Q&, C&
  8.    ls2Len& = ((Len(String2$)) - &H1)
  9.    If ls2Len& > -1 Then
  10.        lLimit& = ((Len(String1$)) - ls2Len&)
  11.        If lLimit& > 1 Then
  12.            bvString1 = (VBA.StrConv(String1$, vbFromUnicode))
  13.            bvString2 = (VBA.StrConv(String2$, vbFromUnicode))
  14.            Q& = (Start& - &H1)
  15.            Do While (Q& < lLimit&)
  16.                Do While (bvString1(Q& + C&) = bvString2(C&))
  17.                    'Debug.Print ChrW$(bvString1(Q& + C&)); ChrW$(bvString2(C&))
  18.                    C& = C& + &H1
  19.                    If ((C& - &H1) = ls2Len&) Then
  20.                        myInstr& = Q& + &H1
  21.                        Exit Function
  22.                    End If
  23.                Loop
  24.                Q& = (Q& + C&) + &H1
  25.                C& = &H0
  26.            Loop
  27.        End If
  28.    End If
  29. End Function
http://goo.gl/Pv2Be

 :xD
Un día de estos que no estés ocupado te tengo que preguntar dudas por msn... :P

DoEvents! :P


Título: Re: [ANSI C] Split(), strlen(), mid(), Instr(), strcpy().
Publicado por: BlackZeroX en 13 Enero 2011, 02:12 am
.
Ya corregi el error el problema era con la funcion mid(), TODO ya funciona como deberia de ser.

@ Leo Gutiérrez.
Puse la comparacion con el caracter nulo solo para tener la menor cantidad de advertencias de mi IDE/Compilador.

P.D.: Si Rana es el mismo solo que lo tube que traducir, fue la que mas me gusto.

Dulces Lunas!¡.


Título: Re: [ANSI C] Split(), strlen(), mid(), Instr(), strcpy().
Publicado por: 08l00D en 13 Enero 2011, 15:49 pm
Por otro lado, el tipo de dato bool no existe en C, solo en C++
Saludos

En realidad si existe en C.. se implemento a partir del estandar C99..
se puede utilizar como _Bool ... o bool (incluyendo <stdbool>, donde esta definido)
aunque igual siempre es mejor definirlo para no joder la compatibilidad con compiladores viejos..
Código
  1.  
  2. unsigned long strlen(char* string)
  3. /**
  4.     Retorna la longitud de [string]
  5.     By BlackZeroX ( http://Infrangelux.sytes.net/ )
  6. **/
  7. {//no esta mal pero deberias restarle 1 a i antes de retornarla asi no incluye el valor te terminador de cadena, asi el que use tu implementacion de la funcion no tenga que restarle 1 al valor cada vez que la use...
  8.    unsigned long i=0;
  9.    while (*(string++) != '\0') i++;
  10.    return i;
  11. }
  12.  
  13. char* strcpy(char* str_dest,char* str_src)
  14. /**
  15.     Copia una string a otra [*str_src] a [*str_dest].
  16.     Retorna el puntero a [str_dest]
  17.     By BlackZeroX ( http://Infrangelux.sytes.net/ )
  18. **/
  19. {
  20.    while( (*(str_dest++)=*(str_src++) == '\0' ) ); // MAL... la comparacion esta mal .. tenes que comparar si la cadena es distinta a '\0' no igual.... cuando copias tambien esta mal ... ya que estarias copiando el resutado de la comparacion ..la precedencia del operador == es mayor al de asignacion... necesitas parentesis..
  21.    return (str_dest);
  22. }
  23.  
  24.  
  25.  
Por lo demas no lo vi en detalle ... pero vi que los punteros devueltos por malloc los comparas por 0 .. lo cual en teoria no esta mal ya que el compilador se da cuenta que el 0 esta siendo utilizada en un contexto de puntero y hace la conversion a NULL implicitamente.. pero no es una buena practica en C... utiliza siempre NULL.. al igual que cuando inicialices tus punteros...
ah y otra cosa cuando tenes una expresion como *cadena++  los parentesis no son necesarios ... el operador ++ tiene mayor precedencia que el de desreferencia...

Saludos


Título: Re: [ANSI C] Split(), strlen(), mid(), Instr(), strcpy().
Publicado por: Littlehorse en 13 Enero 2011, 20:29 pm
Citar
En realidad si existe en C
No, en C++ bool es un tipo de dato primitivo aparte. En C, desde C99 como bien decís, se define mediante macros en stdbool.h, pero es al día de hoy que se sigue definiendo aparte no solo por retrocompatibilidad, también por claridad de código.

Citar
pero no es una buena practica en C... utiliza siempre NULL.. al igual que cuando inicialices tus punteros...

No esta establecido que sea una mala practica no utilizar NULL. Es simplemente una cuestión de estilo que se suele aplicar mas que nada en código critico donde se requiera dejar bien en claro que se esta tratando con punteros, pero no mas que eso.

Citar
an integer constant expression with the value 0, or such an expression cast to type void *, is called a null pointer constant. If a null pointer constant is converted to a pointer type, the resulting pointer, called a null pointer, is guaranteed to compare unequal to a pointer to any object or function.


Personalmente me molesta bastante leer NULL por todos lados cuando esta mas que claro que se trata de punteros. Si se necesita dejar en claro que es un puntero no me parece mal, pero tampoco exagerar.
En C++ directamente es lo contrario, el mismo creador recomienda utilizar 0 en lugar de NULL.


Saludos


Título: Re: [ANSI C] Split(), strlen(), mid(), Instr(), strcpy().
Publicado por: BlackZeroX en 13 Enero 2011, 20:59 pm
Código
  1.  
  2. unsigned long strlen(char* string)
  3. /**
  4.     Retorna la longitud de [string]
  5.     By BlackZeroX ( http://Infrangelux.sytes.net/ )
  6. **/
  7. {//no esta mal pero deberias restarle 1 a i antes de retornarla asi no incluye el valor te terminador de cadena, asi el que use tu implementacion de la funcion no tenga que restarle 1 al valor cada vez que la use...
  8.    unsigned long i=0;
  9.    while (*(string++) != '\0') i++;
  10.    return i;
  11. }
  12.  
  13.  


Muchas gracias por "tu corrección", pero por otro lado la funcion y objetivo es colo contar caracteres sin el char NULL por ende esta correcto

Código
  1.  
  2. printf("%d\n",strlen((char*)"hola"));
  3. /*
  4.     tiene que devolver una longitud de 4 caracteres que es lo que interesa, el '\0' al final no nos interesa.
  5.     * Salida 4.
  6. */
  7.  
  8.  

En strcpy() gracias me hiciste ver un error de hecho, y de hecho ni hiba a poner la igualdad a '\0' ( ya que se obvia ) pero como dije arriba solo puse dichas comparaciones para evitar la mayor cantidad de Advertencias que me tiraba mi IDE/Compilador. aun que me tira una de unsigned long y un long ( esta la he estado ignorando ) ya que como se que un long abarca un buen numero..., y por otro lado ya se como se evaluan los operadores unitarios.

Gracias por lo de NULL, solo una duda mas si pongo (char*)0 tambien vale?, en mi forma de pensar es correcto pero desearia ver que piensan otros ya que no me deseo encerrar! en una conjetura¡.

P.D.: El objetivo de estos codigos para mi es mejorar la comprension, sintaxis ( a tal grado de que ya no use tanto la web tal y como lo hago ya con vb6 q ya puedo hacer codigo de forma fluida usando las APIS del sistema. ), y evitar horrores de sintasys y demás cosas, ¿no voy tan perdido vdd? xP.

Dulces Lunas!¡.
.


Título: Re: [ANSI C] Split(), strlen(), mid(), Instr(), strcpy().
Publicado por: Littlehorse en 14 Enero 2011, 00:20 am
Citar
Gracias por lo de NULL, solo una duda mas si pongo (char*)0 tambien vale?, en mi forma de pensar es correcto pero desearia ver que piensan otros ya que no me deseo encerrar! en una conjetura¡.
Dependiendo del caso legal es, pero correcto no. Utiliza NULL en casos donde sea importante que el programador detecte a primera vista que se esta tratando de un puntero, para los otros casos puedes usar 0 perfectamente.
En el caso de C++, con 0 basta y sobra.

Código
  1. #ifndef NULL
  2. #ifdef _cpp
  3. #define NULL 0
  4. #else /* not cpp */
  5. #define NULL ((void *)0)
  6. #endif
  7. #endif


Saludos


Título: Re: [ANSI C] Split(), strlen(), mid(), Instr(), strcpy().
Publicado por: 08l00D en 14 Enero 2011, 01:03 am
No, en C++ bool es un tipo de dato primitivo aparte. En C, desde C99 como bien decís, se define mediante macros en stdbool.h, pero es al día de hoy que se sigue definiendo aparte no solo por retrocompatibilidad, también por claridad de código.
_Bool como puse arriba es una palabra reservada por tanto nuevo tipo... y te podes dar cuenta por 2 cosas no se necesita incluir ningun archivo de cabecera (que tenga un typedef, definicion de constante, enumeracion, etc) para poder declarar variables con _Bool y la otra es que las palabras reservadas(luego del estandar) suelen llevar como primer caracter el guion bajo.. al igual que _Complex _Imaginary .. tambien introducidos en C99...
bool en stdbool.h si es una macro... no dije que no lo fuera


No esta establecido que sea una mala practica no utilizar NULL. Es simplemente una cuestión de estilo que se suele aplicar mas que nada en código critico donde se requiera dejar bien en claro que se esta tratando con punteros, pero no mas que eso.

Saludos
Si tenes razon, lo dije sin ser demasiado objetivo... en lo personal no me gusta dejar al compilador que haga ese tipo de conversiones (de constantes a punteros) por que hay situaciones en donde el compilador no es capaz de realizar la conversion...
por ejemplo.. en el paso de un argumento a una funcion que espera un puntero, si la funcion no tiene prototipo el cual no es obligatorio en C, se le esta pasando un int ... en vez de (void *)(0) ...
ademas para mi le da mas legibilidad al codigo...es lo mismo que lo de true o false.. gustos personales


Título: Re: [ANSI C] Split(), strlen(), mid(), Instr(), strcpy().
Publicado por: Littlehorse en 14 Enero 2011, 02:35 am
Citar
_Bool como puse arriba es una palabra reservada por tanto nuevo tipo... y te podes dar cuenta por 2 cosas no se necesita incluir ningun archivo de cabecera (que tenga un typedef, definicion de constante, enumeracion, etc) para poder declarar variables con _Bool

Que sea una palabra reservada no implica que sea un nuevo tipo, "for" es una palabra reservada y hasta donde se no es un tipo de dato  ;D.
En todo caso si es como decís, realmente dudo mucho que no haya un typedef, pero ya mirare cuando haya tiempo. Igualmente por ahora te tomo la palabra ya que para comprobarlo tendría que instalar GCC y no puedo en este momento. En Vs el soporte a C99 es menor y en C++ _Bool no es mas que un typedef de bool.

Citar
en lo personal no me gusta dejar al compilador que haga ese tipo de conversiones (de constantes a punteros) por que hay situaciones en donde el compilador no es capaz de realizar la conversion...

Intenta buscar 3 ejemplos en el que el compilador no sea capaz de realizar la conversión de 0 a NULL y veras que en ninguno el problema radica exclusivamente en utilizar o no utilizar NULL.

Un ejemplo claro es el que expones:

Citar
en el paso de un argumento a una funcion que espera un puntero, si la funcion no tiene prototipo el cual no es obligatorio en C, se le esta pasando un int ... en vez de (void *)(0) ...

Si no tenes un prototipo de función declarado partís de un error inicial. Usar o no usar NULL es secundario ya que ese no es exclusivamente el problema, el problema radica en la traba que le pones al compilador.

Código
  1. int main()
  2. {
  3.  
  4. func(); //Ups me olvide de pasarle parametros. Es que no habia prototipo ;D
  5.  
  6. return 0;
  7. }
  8.  
  9. int func(char *ptr)
  10. {
  11.  
  12. if(ptr)
  13. {
  14. printf("No es NULL"); //...
  15. *ptr='a'; //Crash
  16. }
  17. else
  18. printf("NULL");
  19. }

Y este es solo uno de mil ejemplos que no tienen nada que ver con usar o no usar NULL.

Saludos!