funciones de tratamiento de cadenas.doc

Upload: omar-rosales

Post on 06-Jul-2018

213 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    1/17

    Funciones de tratamiento de cadenas

    Es interesante recordar que todo lo que "sobra", esto es, lo que está más allá del primer espacio en blanco, queda almacenado y disponible para la siguiente sentencia de lectura.La función gets() captura todo lo restante, y después se imprime mediante puts(). Hay que

    ser precaidos a la !ora de "dear" restos en el tampón. Lo meor es eliminar posiblesrestos antes de pasar a la lectura siguiente, empleandofflus!(stdin) o bien fpurge(stdin).

    El arc!io de encabe#ado string.! contiene numerosas funciones relacionadas con eltratamiento de caracteres. $éase a continuación una tabla de funciones %tiles&

    '  Funciones de concatenación '

    Encabezado Descripción

    c!ar strcat (c!ar s, const c!ar s*)+

    Esta función aade s* a s y pone un -/- alfinal del resultado+ se supone

    que s contiene espacio suficiente para eltotal de caracteres (los de s, los de s* yel -/-). 0roporciona como resultado unpuntero de s

    c!ar strncat (c!ar s, const c!ar s*, si#e1tn)+

     2náloga a la anterior, pero aade a s unmá3imo de n caracteres de s*. 0roporcionacomo resultado un puntero de s

    '  Funciones de comparación '

    Encabezado Descripción

    int memcmp (const oid s, const oid s*,si#e1t n)+

    4ompara byte por byte las dos cadenas cuyadirección se proporciona, suponiendo queambas tuieran n bytes de longitud. 5i ambasseries de bytes son iguales, la funciónproporciona el alor /. 5i no son iguales, lafunción deuele la diferencia entre los dosprimeros bytes distintos. La comparación esnumérica, sin tener en cuenta el ordenalfabético internacional, lo cual produceresultados e3traos cuando las cadenascontienen signos diacr6ticos.

    int strcmp (const c!ar s, const c!ar s*)+

    Esta función compara byte por byte las

    cadenas de caracteres sealadaspor s y s*. El resultado es&

    • negatio si s es menor que s*

    • nulo si s y s* son iguales

    • positio si s es mayor que s*

    int strcoll (const c!ar s, const c!ar s*)+ Esta función sire para comparar doscadenas, y !ace uso de la secuencia

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    2/17

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    3/17

    s*.

    c!ar strstr (const c!ar s, const c!ar s*)+ Esta función busca la primera apariciónde s* dentro de s, sin tener en cuenta elcarácter de fin de cadena. 5i s* se encuentraen s, la función proporciona un un punterodel primer byte de s*dentro de s. 5i no se

    encuentra s* dentro de s, se proporciona elpuntero nulo.

    c!ar strto9 (c!ar s, const c!ar s*)+ Esta función e3trae subcadenas (tokens)de s. Los separadores de subcadenas sonlos caracteres que contenga s*. La primerasubcadena se proporciona (mediante unpuntero) cuando se llamaa strto9()empleando s y s* comoparámetros. La segunda subcadena (ysiguientes) se obtienen mediante llamadasa strto9() con el puntero nulo como primer argumento, y con la cadena de separadorescomo segundo argumento (ésta se puedemodificar en las distintas llamadas). 4uandoya no quedan más subcadenas, la funciónproporciona el puntero nulo. :bsérese lanotable utilidad de esta función para lalectura de arc!ios de te3to con formatodelimitado. :bsérese también que, una e#inocada la cadena por primera e#, seadmiten cambios en el delimitador especificado (;que es una cadena< 5epueden emplear delimitadores "compleos",formados por m%ltiples caracteres.)

    Ejercicio 1: Leer una palabra y escribirla al revés.

    Para leer una palabra, contar las letras y escribirla al revés, lo primero que hay

    que hacer es pedir la palabra y almacenarla. Una vez que tenemos la palabra en

    un array, para contar el número de letras se chequea letra por letra (bucle while)

    sumando 1 cada vez. Este bucle inaliza cuando el car!cter le"do es #$%# que indicael inal de la palabra. Este car!cter, como ya se ha dicho antes, es introducido por 

    la unci&n scanf( ) de manera autom!tica. Para escribir la palabra al revés, basta

    con leerla empleando un bucle que cuente hacia atr!s.

    'uarda este prorama como alreves.c.

    Solución comentada del Ejercicio 1.

    http://maxus.fis.usal.es/fichas_c.web/10xx_PAGS/1003.htmlhttp://maxus.fis.usal.es/fichas_c.web/10xx_PAGS/1003.htmlhttp://maxus.fis.usal.es/fichas_c.web/10xx_PAGS/1003.htmlhttp://maxus.fis.usal.es/fichas_c.web/10xx_PAGS/1003.html

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    4/17

    e presenta a continuaci&n el prorama alreves.c que lee una palabra del teclado,

    la almacena en una array de *% posiciones y lueo la escribe al reves.

    /* fichero alreves.c *//* Este programa lee una palabra y la escribe al revés */#include void main (void)  char c! palabra"$%&  int i&  printf('eclee una palabra de menos de letras+n')&  scanf(',s'! palabra)&  i - &  hile(palabra"i% 0- 1+1)  &  printf(',s tiene ,d letras.+n'! palabra! i)&  printf(',s escrita al revés es '! palabra)&  hile (i >- )  printf(',c'! palabra"i22%)&3

    Comentario+ a orma de almacenar el array leyéndolo del teclado es mediante

    la unci&n scanf(). ueo, mediante un bucle while se determina el número de

    letras. a orma de chequear la condici&n de inal del bucle es por

    reconocimiento del car!cter \0 que tienen todas las cadenas de caracteres al inal.

    a cadena se podr"a haber rellenado de otra manera, como se ver! en el E-ercicio

    siuiente. ambién el número de caracteres de la cadena se puede determinar

    mediante otra orma+ llamando a la unci&n de libreriastrlen(char*).

    Una vez que ya conocemos el número de caracteres de la cadena, no tenemos

    m!s que escribir el array al revés, con un bucle con un contador decreciente.

    Ejercicio 2: Leer una rase !l"nea# y escribirla al revés.

    /as!ndote en el prorama anterior, realiza un prorama que lea una l"nea y acontinuaci&n la escriba al revés. a dierencia principal con el E-ercicio anterior

    est! en que una l"nea puede contener varias palabras. a unci&n scanf(), tal

    como se ha utilizado en el E-ercicio anterior, s&lo lee la primera palabra de la

    rase, pues la lectura se detiene al llear al primer car!cter en blanco. En los

    0puntes de se suieren dos ormas de leer l"neas completas, una con la

    http://www1.ceit.es/Asignaturas/Informat2/C/ejerres/prac07/alreves.chttp://www1.ceit.es/Asignaturas/Informat2/C/ejerres/prac07/alreves.c

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    5/17

    unci&n scanf() y otra con la macro getchar(). Puedes utilizar cualquiera de las

    dos.

    e suerimos que pruebes el prorama con una de las siuientes rases

    (llamadas palíndromos)+ 2dabale arroz a la zorra el abad23 2a ti no bonita2.

    'uarda el prorama con el nombre frase.c.

    Solución comentada del Ejercicio 2.

    e presenta a continuaci&n una posible soluci&n al E-ercicio *. En esta soluci&n

    se va a presentar otra orma de leer un array del teclado. a soluci&n m!s sencilla

    a este e-ercicio hubiera sido sustituir la l"nea scanf(" %s", palabra); del

     prorama alreves.c por scanf(" %[!n", frase);

    /* fichero frase.c */#include void main(void)  char c! frase"$%&  int i! n&  printf('4ntrodu5ca una frase de menos de $ letras.+n')&  printf('6ara finali5ar pulse 78+n')&  i - &  hile((c-getchar())0-E9:)   frase"i% - c&

      i&  3  frase"i% - 1+1&  printf('+n')&  for (n-i& n>-& n22)  putchar(frase"n%)&  printf('+n')&3

    Comentario+ En este caso, la lectura del array se realiza mediante un

     bucle while cuya condici&n de e-ecuci&n es la de encontrar un car!cter distinto

    del carácter fin de fichero (E45). uando en vez de leer la rase desde un

    ichero, ésta se introduce desde teclado, el car!cter equivalente al E45es control#$ , que también se suele denotar como $ .

    Una vez almacenada la rase en el array, se procede a escribirla al revés de la

    misma orma que se hac"a en el prorama anterior. En este caso se ha utilizado la

    macro de librer"a ptchar(c); en luar de printf(), de modo que la rase se escribe

    car!cter a car!cter con dicha macro.

    http://www1.ceit.es/Asignaturas/Informat2/C/ejerres/prac07/frase.chttp://www1.ceit.es/Asignaturas/Informat2/C/ejerres/prac07/frase.c

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    6/17

    Ejercicio $: %ransormar un te&to.

    El siuiente prorama lee un te6to cualquiera y lo escribe al revés transormando

    las mayúsculas en minúsculas y viceversa. Para esto último basta tener en cuentaque la dierencia entre el c&dio 077 de una letra mayúscula y el de la misma

    letra en minúscula es un número constante. 8ay que tener cuidado para no

    modiicar los caracteres de estilo tales como espacio en blanco (# #), tabulador

    (#$t#), coma, ... 'uarda el prorama como inverso.c.

    En se utiliza la constante simb&lica E45 para indicar el inal de un ichero

    (esta constante est! deinida en el ichero stdio.h). u valor numérico es (91) y

    equivale también a &control'$  ($ ) cuando se introduce el te6to desde teclado.

    Solución comentada del Ejercicio $.

    e presenta a continuaci&n el listado correspondiente al E-ercicio : tal y como se

     present& en el enunciado de la pr!ctica.

    /* fichero inverso.c *//* Este programa convierte las mayusculas en minusculas y viceversa *//* y escribe el te;to cambiado al reves */#include void main(void)  int ch&  char te;to"$%& /* limite de caracteres del te;to */  int i! n! dif&  dif - 1a1211&  printf('4ntrodu5ca un te;to.+n')&  printf('6ulse 78 para finali5ar+n')&  i - &  hile ((ch - getchar()) 0- E9:)   if ((ch>-1a1)==(ch-11)==(ch-& n22)  printf(',c'! te;to"n%)&3

    http://www1.ceit.es/Asignaturas/Informat2/C/ejerres/prac07/inverso.chttp://www1.ceit.es/Asignaturas/Informat2/C/ejerres/prac07/inverso.c

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    7/17

    Comentario+ En este prorama se utiliza la orma de introducir la cadena como

    ya se hizo en el prorama frase.c. Para cambiar las mayúsculas a minúsculas y

    viceversa hay que chequear el car!cter y ver si es alabético o no. Una vez que se

    sabe que es un car!cter alabético, hay que saber que el c&dio 077

    correspondiente a la 202 es el ;< y el correpondiente a la 2a2 es el =>, es decir, la

    dierencia entre ambos es :*.

    En luar de teclear el te6to cada vez, crea un ichero de te6to llamado teto y

    redirecciona la entrada con el operador (?) cuando vayas a e-ecutar el prorama,

    de la siuiente manera+

    +a?@AB?.B>inverso < te;to$

    Ejercicio ': (odiicar el Ejercicio $.

    @odiica el prorama anterior de manera que el te6to oriinal se lea del

    ichero teto, que inicialmente ser! una copia del ichero teto utilizado en el

    E-ercicio anterior. Para leer car!cter a car!cter puedes utilizar la unci&n  getf() y,

    una vez modiicado el te6to se puede escriber mediante ptf() o fprintf(), a

    continuaci&n del te6to oriinal, en el mismo ichero teto. lama a este

     prorama invers.c.

    Solución comentada del Ejercicio '.

    /* fichero invers.c */#include #include void main(void)  int ch&  char te;to"$%&  int i! n! dif&  :4CE *fi&  fi - fopen('te;to.d'!'r')&  dif - 1a1 2 11&  i - &  hile ((ch - getc(fi)) 0- E9:)   if ((ch >- 1a1)==(ch - 11)== ch

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    8/17

      te;to"i% - 1+1&  for (n-i& n>-& n22)  putc(te;to"n%! fi)&  fclose(fi)&3

    Comentario+ El prorama es idéntico al anterior con la salvedad del mane-o deicheros. 8ay que declarar un puntero al ichero mediante la declaraci&n +-

    *fi;. Este puntero se utilizar! a la laro del prorama para desinar el ichero. En

     primer luar, este ichero hay que abrirlo mediante la instrucci&n fopen, en la que

    se deinen el nombre del ichero y el tipo. En el resto del prorama lo único que

    cambia son las instrucciones de entrada y salida+ ptc sustituye

    a ptchar  y getc sustituye a getchar .

    Ejercicio ): *rdenar alabéticamente.

    El siuiente prorama pide diez palabras y las ordena alabéticamente. 'u!rdalo

    como ordena.c. a ran novedad que presenta este prorama es la reserva

    din!mica de memoria mediante la unci&n malloc().

    Pensemos por un momento en el ob-etivo de este prorama+ queremos que lea

    diez palabras, las almacene y pueda compararlas para ordenarlas. AB&nde

     podemos almacenar una palabraC 4bviamente en un array de caracteres. AD diez

     palabrasC Podr"amos utilizar diez arrays, pero ya que queremos relacionarlas

    entre s" resulta mucho m!s útil emplear una matriz de caracteres, que no es m!sque un array de arrays. ada palabra se almacenar"a en una ila de la matriz.

    0hora bien, no todas las palabras tendr!n el mismo número de letras, lo que nos

    hace intuir que no hay por qué reservar espacio para una matriz rectanular, sino

     para una matriz de diez ilas donde cada una de ellas tendr! las posiciones de

    memoria necesarias para almacenar todos los caracteres que componen la palabra

    m!s uno (para el car!cter #$%#). olviendo a insistir+ sabemos que necesitamos una

    matriz de 1% ilas pero de número de columnas variable. El procedimiento es

    muy sencillo+ leemos la palabra, vemos cu!nto ocupa y entonces reservamos el

    espacio necesario. a palabra le"da se almacena temporalmente en una variable

    array au6iliar que hemos llamado temp+,, que permite almacenar palabras dehasta veinte letras.

    eamos qué hacen e6actamente las siuientes intrucciones del prorama+

    char **cadena&

    Esta intrucci&n declara cadena como un doble puntero ( o puntero a puntero).

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    9/17

    cadena - malloc($*si5eof(char*))&

    Esta intrucci&n reserva memoria para un vector de punteros, llamado

    también cadena+ ,. Este vector contiene diez posiciones de memoria, cada una de

    las cuales contiene un puntero a char. a unci&n malloc(), como se recordar!,

    tiene como valor de retorno un puntero al primer elemento de la zona reservada yse almacena en cadena que ya se declar& en la instrucci&n antes comentada. Por

    lo tanto cadena apunta a cadena+0,, que a su vez apuntar! lueo al primer

    car!cter de la primera palabra.

    ector de punteros +

    scanf(',s'! temp)&

    Esta intrucci&n lee una palabra y la almacena en el array temp+ ,.

    cadena"i% - malloc((strlen(temp)$)*si5eof(char))&

    Esta instrucci&n reserva la memoria necesaria, en bytes, para la palabra

    almacenada en temp+ , (incluyendo el car!cter #$%#). El valor de retorno, que es la

    direcci&n del primer car!cter de la palabra, se almacena en el puntero cadena+i,.

    &lo nos queda por comentar que el aloritmo que se siue para ordenar las

     palabras es an!loo al que se utiliz& para ordenar un con-unto de números.

    Solución comentada al Ejercicio 1.

    /* fichero ordena.c *//* Este programa pide die5 palabras y las ordena por orden alfabetico */#include #include void main(void)  char **cadena& /* declaraciDn de puntero a matri5 de caracteres */  int i! &  int n&

      char temp"%& /* declaraciDn del array au;iliar dondealmacenaremos temporalmente cada palabra */

      char *au;& /* decalaracion de puntero a carFcter! au;iliar */  printf(',s,s+n'! 'Este programa ordena die5 palabras'!

    'introducidas por teclado.')&  printf('4ntrodu5ca las die5 palabras+n')&  cadena - malloc($*si5eof(char*))&  for (i-& i

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    10/17

      cadena"i% - malloc((strlen(temp)$)*si5eof(char))&  strcpy(cadena"i%! temp)&  3  for (i-& i

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    11/17

      char **cadena! *au;&  int i! ! n&  char temp"%&  printf(',s,s+n'! 'Este programa ordena die5 nombres'!

    'introducidos por teclado.')&  printf('4ntrodu5ca los die5 nombres+n')&  cadena - (char**)malloc($*si5eof(char*))&

      for (i-& i

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    12/17

    void main(void)  int nIblancos - ! c! nIdigitos - &  int nIletras - ! nInulineas - ! nIotros - &  hile ((c - getchar()) 0- E9:)  if (c -- 1 1)  nIblancos&

      else if (c>-11 == c-1a1 == c-11 == c

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    13/17

    3

    onstruye tu propio ichero de comprobaci&n de este prorama que contena un

    m"nimo de *% palabras en un m"nimo de F l"neas. Beber! contener también alún

    tabulador. Esta ichero se llamar! palabras.

    Solución comentada del Ejercicio .

    El listado de éste prorama es como siue+

    /* fichero contador.c */#include void main(void)

      char c&  int pass! numIpal&  numIpal - &  pass - &  printf('4ntrodu5ca un te;to.+n')&  printf('6ulse 78 para finali5ar+n')&  hile( (c - getchar()) 0- E9: )   if ( ((c >- 1a1)==(c - 11)==(c

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    14/17

    *.1 i pass 00 1 siniica que estaba uera de palabra y he entrado en una, por lo

    que hacemos nm/pal 20  (incrementamos una palabra en el contador) y pass

    0  (estamos dentro de palabra).

    *.* i pass 00  siniica que est!bamos metidos en una palabra y que seuimos

    dentro de ella. Go hacemos nada.

    : i el car!cter no es alabético, chequeo si he salido o no de una palabra

    (chequeo pass).

    :.1 7 pass00  siniica que el car!cter anterior era alabético y, por tanto, he

    salido de una palabra+ hacemos pass 0 1 porque ahora nos hemos salido de ella.

    :.* i pass 00 1 siniica que no est!bamos en ninuna palabra y que seuimos

    sin estar, por tanto no hacemos nada.

    Ejercicio : 3n icero secreto.

    El siuiente prorama lee un te6to y lo escribe en clave. Escribirlo en clave no es

    m!s que sumar una cantidad al número en c&dio 077 que corresponde a cada

    car!cter. Esta cantidad o clave se ha de teclear en cada e-ecuci&n del prorama.

    Solución comentada al Ejercicio .

    /* fichero secreto.c *//* Este programa encripta un te;to */#include void main(void)  char ch&  int n&  printf('4ntrodu5ca la clave ')&  scanf(',d'! =n)&

      getchar()&  printf('4ntrodu5ca los caracteres.+n')&  printf('6ulse 78 para finali5ar+n')&  hile((ch - getchar()) 0- E9:)  if (ch -- 1+n1)  printf(',c'! ch)&  else  printf(',c'! chn)&3

    http://www1.ceit.es/Asignaturas/Informat2/C/ejerres/prac07/secreto.chttp://www1.ceit.es/Asignaturas/Informat2/C/ejerres/prac07/secreto.c

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    15/17

    Ejercicio 10: 4ro5ramar unciones an6lo5as a strlen!#7 strcpy!#7 strcat!# y

    strcmp!#.

    Healiza una prorama principal que utilice varias cadenas de caracteres y llame aunas unciones proramadas por ti que realicen las mismas tareas

    que strlen( ), strcpy( ), strcat ( ) strcmp( ). Beber!s llamar a tus unciones con un

    nombre distinto a las que e6isten en la librer"a de . e suerimos los siuientes

    nombres+

    strlen! # cuenta8caracteres! #

    strcpy! # copia8cadenas! #

    strcat! # concatena8cadenas! #

    strcmp! # compara8cadenas! #

    'uarda estas unciones en un ichero an!loo a string.h y al que

    llamar!s misfnc.h e incluye en el encabezamiento del prorama principal la

    instrucci&n+

    #include 'misfunc.h'

    El prorama principal se llamar! cadenas.c.

    Solución comentada del Ejercicio 10.

    /* fichero cadenas.c */#include #include 'misfunc.h'unsigned cuentaIcaracteres(char*)&char* copiaIcadenas(char*!char*)&char* concatenaIcadenas(char*!char*)&int comparaIcadenas(char*!char*)&void main(void)

      char car$"$% - 'Esto es una cadena de caracteres'&  char car@"$% - 'Esto es una cadena de caracteres'&

    char car"$%&  printf(',d+n'! cuentaIcaracteres(car$))&  copiaIcadenas(car$!car)&  printf(',s+n'!car)&  printf(',s+n'!concatenaIcadenas(car$!car))&

    printf(',d+n'!comparaIcadenas(car$!car))&  printf(',d+n'!comparaIcadenas(car!car@))&

    http://www1.ceit.es/Asignaturas/Informat2/C/ejerres/prac07/cadenas.chttp://www1.ceit.es/Asignaturas/Informat2/C/ejerres/prac07/cadenas.c

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    16/17

    3unsigned cuentaIcaracteres(char* carac)  unsigned i-&  hile (carac"i% 0- 1+1)  i&  return i&

    3

    Comentario+ a unci&n centa/caracteres() cuenta los caracteres de la cadena

    detectando el car!cter o marca de inal de cadena. Por lo dem!s, esta unci&n es

    muy sencilla.

    char* copiaIcadenas(char* carac$! char* carac)  int i-&  hile ((carac"i%-carac$"i%) 0- 1+1)

    i&  return carac$&3

    Comentario+ a unci&n copia/cadenas() anterior tiene como punto interesante

    el copiar el car!cter antes de compararlo con la marca de in de cadena. Para ello

    la asinaci&n debe ir entre paréntesis, de modo que se realice antes de comparar

    con el car!cter de in de cadena. Be este modo se asuura que dicho car!cter es

    también copiado por la unci&n.

    char* concatenaIcadenas(char* carac$! char* carac)  int i-! -&

      hile (carac$"i% 0- 1+1)&

      hile (carac"% 0- 1+1)carac$"i% - carac"%&

      carac$"i% - 1+1&  return carac$ &3

    Comentario+ e detecta primero el inal de la cadana carac[  . Bespués se van

    copiando a continuaci&n todos los caracteres de carac[   y inalmente se aIade

    el car!cter in de cadena.

    int comparaIcadenas(char* carac$! char* carac)

    int i - ! dif&  hile (carac$"i% 0- 1+1)   dif - carac$"i% 2 carac"i%&

    if (dif -- )  i&  else

    return (dif)&

  • 8/17/2019 Funciones de tratamiento de cadenas.doc

    17/17

      3  if (carac"i% -- 1+1)  return()&3

    Comentario+ Para comparar las dos cadenas, lo que hacemos es recorrer la

     primera de ellas (carac), hasta que encontramos el caracter !1. Bentro de este bucle lo que hacemos es restar posiciones equivalentes de las dos cadenas.

    Hecuérdese que un car!cter se puede mane-ar como car!cter o se puede

    considerar su equivalencia en 077. 0s", si restamos los dos caracteres, lo que

    en realidad estamos haciendo es restar su equivalente en 077. Por tanto, si la

    dierencia entre los dos caracteres es cero, siniica que son iuales. El bucle

    continua hasta que encuentra dos caracteres distintos con lo cual no se cumple la

    sentencia if ( dif 00 1) y se e-ecutaretrn(dif); con lo cual se devuelve un valor

    distinto de cero y, por tanto, las cadenas son distintas. i se llea al inal de la

     primera cadena y en esa posici&n se tiene que la seunda cadena acaba también

    (carac[i 0 3!13 ) es que las cadenas son iuales y se devuelve un cero.