You are on page 1of 17

APUNTADORES Un apuntador es una variable que contiene la direccin de una variable.

Los apuntadores se utilizan mucho en C, en parte a que ellos son en ocasiones la nica forma de expresar una operacin, y en parte debido a que por lo general llevan un cdigo ms compacto y eficiente de lo que se puede obtener en otras formas. Para declarar un apuntador para una variable entera hacer: int *apuntador;

Se debe asociar a cada apuntador un tipo particular. Por ejemplo, no se puede asignar la direccin de un short int a un long int. Para tener una mejor idea, considerar el siguiente cdigo: main() { int x = 1, y = 2; int *ap; ap = &x; y = *ap; x = ap; *ap = 3; } Cuando se compile el cdigo se mostrar el warning: assignment makes integer from pointer without a cast . siguiente mensaje:

Con el objetivo de entender el comportamiento del cdigo supongamos que la variable x esta en la localidad de la memoria 100, y en 200 y ap en 1000. Nota: un apuntador es una variable, por lo tanto, sus valores necesitan ser guardados en algn lado. int x = 1, y = 2; int *ap; ap = &x; 100 x 1 200 y 2 1000 ap 100

Las variables x e y son declaradas e inicializadas con 1 y 2 respectivamente, ap es declarado como un apuntador a entero y se le asigna la direccin de x (&x). Por lo que ap se carga con el valor 100. y = *ap;

100 x 1

200 y 1

1000 ap 100

Despus y obtiene el contenido de ap. En el ejemplo ap apunta a la localidad de memoria 100 -- la localidad de x. Por lo tanto, y obtiene el valor de x -- el cual es 1. x = ap;

100

200

1000 ap 100

x 100 y 1

Como se ha visto C no es muy estricto en la asignacin de valores de diferente tipo (apuntador a entero). As que es perfectamente legal (aunque el compilador genera un aviso de cuidado) asigna el valor actual de ap a la variable x. El valor de ap en ese momento es 100. *ap = 3; 100 x 3 200 y 1 1000 ap 100

Finalmente se asigna un valor al contenido de un apuntador ( *ap). Importante: Cuando un apuntador es declarado apunta a algn lado. Se debe inicializar el apuntador antes de usarlo. Por lo que: main() { int *ap; *ap = 100; } puede generar un error en tiempo de ejecucin o presentar un comportamiento errtico. El uso correcto ser: main() { int *ap; int x; ap = &x; *ap = 100; }

Con los apuntadores se puede realizar tambin aritmtica entera, por ejemplo: main() { float *flp, *flq; *flp = *flp + 10; ++*flp; (*flp)++; flq = flp; } NOTA: Un apuntador a cualquier tipo de variables es una direccin en memoria -- la cual es una direccin entera, pero un apuntador NO es un entero. La razn por la cual se asocia un apuntador a un tipo de dato, es por que se debe conocer en cuantos bytes esta guardado el dato. De tal forma, que cuando se incrementa un apuntador, se incrementa el apuntador por un ``bloque'' de memoria, en donde el bloque esta en funcin del tamao del dato. Por lo tanto para un apuntador a un char, se agrega un byte a la direccin y para un apuntador a entero o a flotante se agregan 4 bytes. De esta forma si a un apuntador a flotante se le suman 2, el apuntador entonces se mueve dos posiciones float que equivalen a 8 bytes. Utilizacin de apuntadores Las funciones son llamadas para su ejecucin desde cualquier parte del cdigo, teniendo en cuenta que antes deben haber sido declaradas (y por supuesto definidas). La llamada de una funcin se produce mediante el uso de su nombre en una sentencia, pasando una lista de argumentos que deben coincidir en nmero y tipo con los especificados en la declaracin (en otro caso se producira una conversin de tipos o resultados inesperados). Llamadas por valor y por referencia En general, se pueden pasar argumentos a las funciones de dos formas, por valor y por referencia. La llamada por valor copia el valor de un argumento en el parmetro formal de la funcin. De esta forma, los cambios en los parmetros de la funcin no afectan a las variables que se usan en la llamada (es la llamada ms usual, es decir, en general no se pueden alterar las variables usadas para llamar a la funcin). La llamada por referencia copia la direccin del argumento en el parmetro. Dentro de la funcin se usa la direccin para acceder al argumento usado, significando que los cambios hechos a los parmetros afectan a la variable usada en la llamada. Es posible simular una llamada por referencia pasando un puntero al argumento, entonces, al pasar la direccin, es posible cambiar el valor de la variable usada en la llamada. Un puntero o apuntador es una variable que referencia una regin de memoria; en otras palabras es una variable cuyo valor es una direccin de memoria. Si se tiene una variable ' p ' de tipo puntero que contiene una direccin de memoria en la que se encuentra almacenado un valor ' v '

se dice que ' p ' apunta a ' v '. El programador utilizar punteros para guardar datos en memoria en muchas ocasiones, de la forma que se describe a continuacin. [Memoria] . | . | . | ----- |---------| | p |---->| v | ----- |---------| | . | | . | | . | | | | Los punteros son de amplia utilizacin en programacin y muchos lenguajes permiten la manipulacin directa o indirecta de los mismos. La razn de ser principal de los punteros reside en manejar datos alojados en la zona de memoria dinmica o heap (aunque tambin se pueden manipular objetos en la zona esttica), bien sean datos elementales, estructuras (struct en C) u objetos pertenecientes a una clase (en lenguajes Orientados a Objetos). Gracias a esta propiedad, los punteros permiten modelar un grafo, en donde los elementos de ste son los datos residentes en memoria y las relaciones entre los elementos son los propios apuntadores. En nuevos lenguajes de alto nivel, los punteros se han tratado de abstraer. De tal forma que en el lenguaje C# slo pueden ser usados en zonas de cdigo delimitadas como "inseguras", Cuando C pasa argumentos a funciones, la pasa por valor, es decir, si el parmetro es modificado dentro de la funcin, una vez que termina la funcin el valor pasado de la variable permanece inalterado. Hay muchos casos que se quiere alterar el argumento pasado a la funcin y recibir el nuevo valor una vez que la funcin ha terminado. Para hacer lo anterior se debe usar una llamada por referencia, en C se puede simular pasando un puntero al argumento. Con esto se provoca que la computadora pase la direccin del argumento a la funcin. Existe una relacin estrecha entre los punteros y los arreglos. En C, un nombre de un arreglo es un ndice a la direccin de comienzo del arreglo. En esencia, el nombre de un arreglo es un puntero al arreglo. Como se puede observar en el ejemplo la sentencia a[t] es idntica a ap+t. Se debe tener cuidado ya que C no hace una revisin de los lmites del arreglo, por lo que se puede ir fcilmente ms all del arreglo en memoria y sobrescribir otras cosas. Sin embargo los apuntadores y los arreglos son diferentes: Un apuntador es una variable. Se puede hacer ap = a y ap++. Un arreglo NO ES una variable. Hacer a = ap. y a++ ES ILEGAL. Este parte es muy importante, asegrese haberla entendido. Con lo comentado se puede entender como los arreglos son pasados a las funciones. Cuando un arreglo es pasado a una funcin lo que en realidad se le est pasando es la localidad de su elemento inicial en memoria.

Referenciacin La referenciacin es la obtencin de la direccin de una variable. En C y C++ esto se hace a travs del operador &, aplicado a la variable a la cual se desea saber su direccin. Ntese que se trata de un operador unario. Ejemplo: Cdigo C y C++ int x = 25; cout << "La direccin de x es: " << &x << endl; Este cdigo imprime un valor del estilo 0x4fffd34. Este valor puede variar durante cada ejecucin del programa, debido a que el programa puede reservar distintos espacios de memoria durante cada ejecucin. Declaracin de apuntadores Para declarar un apuntador se especifica el tipo de dato al que apunta, el operador, y el nombre del apuntador. La sintaxis es la siguiente:

<tipo de dato apuntado> *<identificador del apuntador>

A continuacin se muestran varios ejemplos: Cdigo C y C++ int *ptr1; // Apuntador a un dato de tipo entero (int) char *cad1, *cad2; // Dos apuntadores a datos de tipo carcter (char) float *ptr2; // Apuntador a un dato de tipo punto-flotante (float)

Asignacin de apuntadores Se pueden asignar a un apuntador direcciones de variables a travs del operador de referenciacin (&) o direcciones almacenadas en otros apuntadores. Ejemplos: Cdigo C y C++ int i = 5; int *p, *q; p = &i; // Se le asigna a p la direccin de i q = p; // Se le asigna a q la direccin almacenada en p (la misma de i) Desreferenciacin de apuntadores La desreferenciacin es la obtencin del valor almacenado en el espacio de memoria donde apunta un apuntador. En C y C++ esto se hace a travs del operador, aplicado al apuntador que contiene la direccin del valor. Ntese que se trata de un operador unario.

Ejemplos: Cdigo C y C++ int x = 17, y; int *p; p = &x; cout << "El valor de x es: " << *p << endl; // Imprime 17 y = *p + 3; // A y se le asigna 20

Apuntadores y Funciones Cuando C pasa argumentos a funciones, los pasa por valor, es decir, si el parmetro es modificado dentro de la funcin, una vez que termina la funcin el valor pasado de la variable permanece inalterado. Hay muchos casos que se quiere alterar el argumento pasado a la funcin y recibir el nuevo valor una vez que la funcin ha terminado. Para hacer lo anterior se debe usar una llamada por referencia, en C se puede simular pasando un puntero al argumento. Con esto se provoca que la computadora pase la direccin del argumento a la funcin. Para entender mejor lo anterior consideremos la funcin swap() que intercambia el valor de dos argumentos enteros:

void swap(int *px, int *py); main() { int x, y; x = 10; y = 20; printf("x=%d\ty=%d\n",x,y); swap(&x, &y); printf("x=%d\ty=%d\n",x,y); } void swap(int *px, int *py) { int temp; temp = *px; /* guarda el valor de la direccion x */ *px = *py; /* pone y en x */ *py = temp; /* pone x en y */ }

Apuntadores y arreglos Existe una relacin estrecha entre los punteros y los arreglos. En C, un nombre de un arreglo es un ndice a la direccin de comienzo del arreglo. En esencia, el nombre de un arreglo es un puntero al arreglo. Considerar lo siguiente: int a[10], x; int *ap; ap = &a[0]; x = *ap; /* ap apunta a la direccion de a[0] */ /* A x se le asigna el contenido de ap (a[0] en este caso) */

*(ap + 1) = 100; /* Se asigna al segundo elemento de 'a' el valor 100 usando ap*/ Como se puede observar en el ejemplo la sentencia a[t] es idntica a ap+t. Se debe tener cuidado ya que C no hace una revisin de los lmites del arreglo, por lo que se puede ir fcilmente ms alla del arreglo en memoria y sobreescribir otras cosas. C sin embargo es mucho ms stil en su relacin entre arreglos y apuntadores. Por ejemplo se puede teclear solamente: ap = a; en vez de ap = &a[0]; y tambin *(a + i) en vez de a[i], esto es, &a[i] es equivalente con a+i. Y como se ve en el ejemplo, el direccionamiento de apuntadores se puede expresar como: a[i] que es equivalente a *(ap + i) Sin embargo los apuntadores y los arreglos son diferentes: Un apuntador es una variable. Se puede hacer ap = a y ap++. Un arreglo NO ES una variable. Hacer a = ap y a++ ES ILEGAL.

Este parte es muy importante, asegrese haberla entendido. Con lo comentado se puede entender como los arreglos son pasados a las funciones. Cuando un arreglo es pasado a una funcin lo que en realidad se le esta pasando es la localidad de su elemento inicial en memoria. Por lo tanto: strlen(s) es equivalente a strlen(&s[0]) Esta es la razn por la cual se declara la funcin como: int strlen(char s[]); y una declaracin equivalente es int strlen(char *s); ya que char s[] es igual que char *s. La funcin strlen() es una funcin de la biblioteca estndar que regresa la longitud de una cadena. Se muestra enseguida la versin de esta funcin que podra escribirse:

int strlen(char *s) { char *p = s; while ( *p != '\0' ) p++; return p - s; } Se muestra enseguida una funcin para copiar una cadena en otra. Al igual que en el ejercicio anterior existe en la biblioteca estndar una funcin que hace lo mismo. void strcpy(char *s, char *t) { while ( (*s++ = *t++) != '\0' ); } En los dos ltimos ejemplos se emplean apuntadores y asignacin por valor. Nota: Se emplea el uso del carcter nulo con la sentencia while para encontrar el fin de la cadena. Direcciones invlidas y la direccin NULL Normalmente, un apuntador inicializado adecuadamente apunta a alguna posicin especifica de la memoria. Sin embargo, algunas veces es posible que un apuntador no contenga una direccin valida, en cuyo caso es incorrecto desreferenciarlo (obtener el valor al que apunta) porque el programa tendr un comportamiento impredecible y probablemente errneo, aunque es posible que funcione bien. Un apuntador puede contener una direccin invlida debido a dos razones: 1. Cuando un apuntador se declara, al igual que cualquier otra variable, el mismo posee un valor cualquiera que no se puede conocer con antelacin, hasta que se inicialice con algn valor (direccin). Ejemplo: Cdigo C y C++ float *p; cout << "El valor apuntado por p es: " << *p << endl; // Incorrecto *p = 3.5; // Incorrecto 2. Despus de que un apuntador ha sido inicializado, la direccin que posee puede dejar de ser vlida sise libera la memoria reservada en esa direccin, ya sea porque la variable asociada termina su mbito o porque ese espacio de memoria fue reservado dinmicamente y luego se libero. Ejemplo: Cdigo C y C++ int *p, y; void func() { int x = 40; p = &x; y = *p; // Correcto *p = 23; // Correcto } void main() { func(); y = *p; // Incorrecto

*p = 25; // Incorrecto }

Si se intenta desreferenciar un apuntador que contiene una direccin invlida pueden ocurrir cosas como las siguientes: Se obtiene un valor incorrecto en una o ms variables debido a que no fue debidamente inicializada la zona de memoria que se accede a travs de la direccin en cuestin. Esto puede ocasionar que el programa genere resultados incorrectos. Si casualmente la direccin es la misma de otra variable utilizada en el programa, o est dentro del rango de direcciones de una zona de memoria utilizada, existe el riesgo de sobre escribir datos de otras variables. Existe la posibilidad de que la direccin est fuera de la zona de memoria utilizada para almacenar datos y ms bien est, por ejemplo, en la zona donde se almacenan las instrucciones del programa. Al intentar escribir en dicha zona, fcilmente puede ocurrir que el programa genere un error de ejecucin y el sistema operativo lo detenga, o que el programa no responda y deje al sistema operativo inestable. En muchos casos el sistema operativo detecta el acceso inadecuado a una direccin de memoria, en cuyo caso detiene abruptamente el programa.

Cuando no se desea que un apuntador apunte a algo, se le suele asignar el valor NULL, en cuyo caso se dice que el apuntador es nulo (no apunta a nada). NULL es una macro tpicamente definida en archivos de cabecera como stdef.h y stdlib.h. Normalmente, en C++ se encuentra disponible sin incluir ningn archivo de cabecera. NULL se suele definir en estas libreras as: Cdigo C y C++ #define NULL 0 Un apuntador nulo se utiliza para proporcionar a un programa un medio de conocer cuando un apuntador contiene una direccin vlida. Se suele utilizar un test condicional para saber si un apuntador es nulo o no lo es, y tomar las medidas necesarias. El valor NULL es muy til para la construccin de estructuras de datos dinmicas, como las listas enlazadas, matrices esparcidas, etc. Es igualmente incorrecto desreferenciar el valor NULL por las mismas razones presentadas previamente.

Fallas comunes con apuntadores A continuacin se muestran dos errores comunes que se hacen con los apuntadores. No asignar un apuntador a una direccin de memoria antes de usarlo int *x *x = 100;

lo adecuado ser, tener primeramente una localidad fsica de memoria, digamos int y; int *x, y; x = &y; *x = 100; Indireccin no vlida

Supongamos que se tiene una funcin llamada malloc() la cual trata de asignar memoria dinmicamente (en tiempo de ejecucin), la cual regresa un apuntador al bloque de memoria requerida si se pudo o un apuntador a nulo en otro caso. char *malloc() -- una funcin de la biblioteca estndar que se ver ms adelante. Supongamos que se tiene un apuntador char *p Considerar: *p = (char *) malloc(100): *p = 'y'; Existe un error en el cdigo anterior. Cul es? El * en la primera lnea ya que malloc regresa un apuntador y *p no apunta a ninguna direccin. El cdigo correcto deber ser: p = (char *) malloc(100); Ahora si malloc no puede regresar un bloque de memoria, entonces p es nulo, y por lo tanto no se podr hacer: *p = 'y'; Un buen programa en C debe revisar lo anterior, por lo que el cdigo anterior puede ser reescrito como: p = (char *) malloc(100): /* pide 100 bytes de la memoria */ /* pide 100 bytes de la memoria */

if ( p == NULL ) { printf("Error: fuera de memoria\n"); exit(1); } *p = 'y';

10

CADENAS En matemticas o en programacin, una cadena de caracteres, palabra, ristra de caracteres o frase (string en ingls) es una secuencia ordenada de longitud arbitraria (aunque finita) de elementos que pertenecen a un cierto alfabeto. En general, una cadena de caracteres es una sucesin de caracteres (letras, nmeros u otros signos o smbolos).

Funciones de manejo de cadenas y caracteres El uso ms comn de un array unidimensional en C es la cadena. C no tiene incorporado un tipo de datos de cadena sino que soporta cadenas utilizando arrays unidimensionales de caracteres. Una cadena se define como un array de caracteres con un carcter de terminacin nulo (\0). El hecho de que la cadena deba terminar en un carcter nulo significa que para declarar un array de caracteres, es necesario que sea de un carcter ms que la cadena ms larga que tenga que contener para dejar sitio al carcter nulo. En una constante de cadena, el compilador pone automticamente un carcter nulo de terminacin. Para leer una cadena es necesario utilizar la funcin gets() con el archivo de cadena stdio.h. Para utilizar gets(), se le llama utilizando un array de caracteres sin ningn ndice. La funcin gets lee caracteres hasta que se pulsa intro. El retorno de carro no se almacena pero lo reemplaza por un carcter nulo que termina la cadena. A la hora de desarrollar una funcin con algn parmetro de tipo string hay que tener en cuenta todo lo dicho para las tablas o vectores numricos. En la llamada a la funcin, para referirse al parmetro real, nunca se deben utilizarlos corchetes. Sirvan como ejemplos las llamadas a las funciones gets y strlen efectuadas en el epgrafe anterior. En el prototipo y en la definicin de la funcin hay que indicar que el parmetro formal es una cadena de caracteres, aunque no es necesario especificar su longitud. Para ello, bastar con utilizar [ ], esto es, los corchetes vacos. Ejemplo: la funcin strlen A continuacin se muestra el prototipo y una posible definicin de la funcin strlen, que, como ya se ha visto, recibe una cadena de caracteres como parmetro de entrada y devuelve un entero. Este nmero es la posicin en la que se encuentra el carcter \0 dentro del string, o lo que es lo mismo, el nmero de caracteres tiles que tiene la cadena de entrada. El prototipo de la funcin strlen podra ser el siguiente: int strlen (char cad[]); Como se acaba de recordar, no es necesario especificar el nmero de elementos del string,ni en el prototipo ni en la definicin de la funcin. Aunque podra haberse indicado un tamao para la cadena de caracteres, en este caso se ha utilizado cad [ ], lo que ofrece una gran ventaja: sea cual sea el tamao con el que se haya definido la cadena que se le pase como parmetro (cadena[30], nif[10], nombre[N], ...), la funcin strlen servir para calcular su tamao til. Una posible definicin o cuerpo de la funcin strlen es la que se presenta a continuacin: int strlen (char cad[]) { int i; i = 0; while (cad[i] != '\0') {

11

i = i + 1; } return (i); } Puede observarse que, dado que el valor que conviene buscar y devolver en la funcin coincide con la posicin en la que se encuentra el carcter \0, lo nico que hay que hacer es inicializar un ndice (i) e incrementarlo hasta encontrar el primer valor en el que la tabla, indexada en i, contenga el carcter de final de cadena. Evidentemente, si esa posicin no existiera, es decir, si ninguna de las posiciones del string tuviera el \0, entonces la implementacin aqu presentada dara problemas. No obstante, se ha supuesto desde un primer momento que dicha situacin no puede tener lugar, bien porque se ha inicializado la En C no existe un tipo predefinido para el manejo de cadenas de caracteres como en otros lenguajes, sino que tienen que declararse como arreglos de caracteres. Lo que distingue a una cadena de caracteres, con respecto a un arreglo de caracteres cualquiera, es que la cadena de caracteres tiene como ltimo carcter al carcter nulo \0. Por ejemplo, si se declara el arreglo: char cadena[8]; Podemos asignar los siguientes valores a cada uno de sus elementos: cadena[0] = 'A' cadena[1] = 'R' ; cadena[2] = 'R' ; cadena[3] = 'E' ; cadena[4] = 'G cadena[5] = 'L' ; cadena[6] = 'O' ; cadena[7] = '\0';

Al contener el carcter nulo, el arreglo cadena ser reconocido por las funciones y objetos diseados para manipular cadenas de caracteres. Para manejar un arreglo de cadenas de caracteres se debe declarar como un arreglo bidimensional de elementos de tipo char, como puede observarse en el listado

12

#include <iostream.h> #include <conio.h> void main() { unsigned short int calif[10]; char nombre[10][21]; // Se declara un arreglo bidimensional // para 10 nombres de 20 caracteres por // nombre mas un caracter para el nulo. clrscr(); for( int x=0 ; x < 10 ; x++) { gotoxy(10,x+1); cout << "NOMBRE [" << x << "] = " ; cin >> nombre[x]; gotoxy(45,x+1); cout << "CALIFICACION [" << x << "] = " ; cin >> calif[x]; } } En el listado se inicia con el subndice 0 para no desperdiciar el primer elemento del arreglo. Adems, se debe recordar que el subndice del ltimo elemento del arreglo es igual al tamao de la dimensin menos 1.

13

Funciones bsicas para el manejo de cadenas Todas las funciones para manejo de cadenas tienen su prototipo en: #include <string.h> Las funciones ms comunes son descritas a continuacin: char *strcpy(const char *dest, const char *orig) -- Copia la cadena de caracteres apuntada por orig (incluyendo el carcter terminador '\0') al vector apuntado por dest. Las cadenas no deben solaparse, y la de destino, debe ser suficientemente grande como para alojar la copia. int strcmp(const char *s1, const char *s2) -- Compara las dos cadenas de caracteres s1 y s2. Devuelve un entero menor, igual o mayor que cero si se encuentra que s1 es, respectivamente, menor que, igual a, o mayor que s2. char *strerror(int errnum) -- Devuelve un mensaje de error que corresponde a un nmero de error. int strlen(const char *s) -- Calcula la longitud de la cadena de caracteres. char *strncat(char *s1, const char *s2, size_t n) -- Agrega n caracteres de s2 a s1. int strncmp(const char *s1, char *s2, size_t n) -- Compara los primeros n caracteres de dos cadenas. char *strncpy(const char *s1, const char *s2, size_t n) -- Copia los primeros n caracteres de s2 a s1. strcasecmp(const char *s1, const char *s2) -- versin que ignora si son maysculas o minsculas de strcmp(). strncasecmp(const char *s1, const char *s2, size_t n) -- versin insensible a maysculas o minsculas de strncmp() que compara los primeros n caracteres de s1.

El uso de muchas funciones es directo, por ejemplo: char *s1 = "Hola"; char *s2; int longitud; longitud = strlen("Hola"); (void) strcpy(s2,s1); /* long = 4 */

Observar que tanto strcat() y strcopy() regresan una copia de su primer argumento, el cual es el arreglo destino. Observar tambin que orden de los argumentos es arreglo destino seguido por arreglo fuente lo cual a veces es una situacin para hacerlo incorrectamente.

La funcin strcmp() compara lexicogrficamente las dos cadenas y regresa: Menor que cero -- si s1 es lxicamente menor que s2; Cero -- si s1 y s2 son lxicamente iguales; Mayor que cero -- si s1 es lxicamente mayor que s2;

14

Las funciones de copiado strncat(), strncmp() y strncpy() son versiones ms restringidas que sus contrapartes ms generales. Realizan una tarea similar, pero solamente para los primeros n caracteres. Observar que el caracter de terminacin NULL podra ser violado cuando se usa estas funciones, por ejemplo: char *s1 = "Hola"; char *s2 = 2; int longitud = 2; (void) strncpy(s2, s1, longitud); /* s2 = "Ho" */ donde s2 no tiene el terminador NULL.

Bsqueda en cadenas La biblioteca tambin proporciona varias funciones de bsqueda en cadenas. char *strchr(const char *s, int c) -- Devuelve un puntero a la primera ocurrencia del carcter c en la cadena de caracteres s. char *strrchr(const char *s, int c) -- Encuentra la ltima ocurrencia del caracter c en la cadena. char *strstr(const char *s1, const char *s2) -- Localiza la primera ocurrencia de la cadena s2 en la cadena s1. char *strpbrk(const char *s1, const char *s2) -- Regresa un apuntador a la primera ocurrencia en la cadena s1 de cualquier carcter de la cadena s2, o un apuntador nulo si no hay un caracter de s2 que exista en s1. size_t strspn(const char *s1, const char *s2) -- Calcula la longitud del segmento inicial de s1 que consta nicamente de caracteres en s2. size_t strcspn(const char *s1, const char *s2) -- Regresa el nmero de caracteres al principio de s1 que no coinciden con s2. char *strtok(char *s1, const char *s2) -- Divide la cadena apuntada a s1 en una secuencia de ``tokens'', cada uno de ellos esta delimitado por uno o ms caracteres de la cadena apuntada por s2.

Las funciones strchr() y strrchr() son las ms simples de usar, por ejemplo: char *s1 = "Hola"; char *resp; resp = strchr(s1,'l'); Despus de la ejecucin, resp apunta a la localidad s1 + 2. La funcin strpbrk() es una funcin ms general que busca la primera ocurrencia de cualquier grupo de caracteres, por ejemplo: char *s1 = "Hola"; char *resp;

15

res = strpbrk(s1,"aeiou"); En este caso, resp apunta a la localidad s1 + 1, la localidad de la primera o. La funcin strstr() regresa un apuntador a la cadena de bsqueda especificada o un apuntador nulo si la cadena no es encontrada. Si s2 apunta a una cadena de longitud cero (esto es, la cadena ""), la funcin regres s1. Por ejemplo: char *s1 = "Hola"; char *resp; resp = strstr(s1,"la"); la cual tendr resp = s1 + 2. La funcin strtok() es un poco ms complicada en cuanto a operacin. Si el primer argumento no es NULL entonces la funcin encuentra la posicin de cualquiera de los caracteres del segundo argumento. Sin embargo, la posicin es recordada y cualquir llamada subsecuente a strtok() iniciar en sa posicin si en estas subsecuentes llamadas el primer argumento no es NULL. Por ejemplo, si deseamos dividir la cadena s1 usando cada espacio e imprimir cada ``token'' en una nueva lnea haramos lo siguiente: char s1[] = "Hola muchacho grande"; char *t1; for ( t1 = strtok(s1," "); t1 != NULL; t1 = strtok(NULL, " ") ) printf("%s\n",t1); Se emplea un ciclo for en una forma no regular de conteo: En la inicializacin se llama a la funcin strtok() con la cadena s1. Se termina cuando t1 es NULL. Se esta asignando tokens de s1 a t1 hasta la terminacin llamando a strtok() con el primer argumento NULL.

Prueba y conversin de caracteres <ctype.h> Una biblioteca relacionada #include <ctype.h> la cual contiene muchas funciones tiles para convertir y probar caracteres individuales. Las funciones ms comunes para revisar caracteres tienen los siguientes prototipos: int isalnum(int c) -- Verdad si c es alfanumrico. int isalpha(int c) -- Verdad si c es una letra. int isascii(int c) -- Verdad si c es ASCII. int iscntrl(int c) -- Verdad si c es un caracter de control. int isdigit(int c) -- Verdad si c es un dgito decimal. int isgraph(int c) -- Verdad si c es un caracter imprimible, exceptuando el espacio en blanco.

16

int islower(int c) -- Verdad si c es una letra minscula. int isprint(int c) -- Verdad si c es un caracter imprimible, incluyendo el espacio en blanco. int ispunct(int c) -- Verdad si c es un signo de puntuacin. int isspace(int c) -- Verdad si c es un espacio int isupper(int c) -- Verdad si c es una letra mayscula. int isxdigit(int c) -- Verdad si c es un dgito hexadecimal.

Las funciones para conversin de caracteres son: int toascii(int c) -- Convierte c a ASCII o un unsigned char de 7 bits, borrando los bits altos. int tolower(int c) -- Convierte la letra c a minsculas, si es posible. int toupper(int c) -- Convierte la letra c a maysculas, si es posible. El uso de estas funciones es directo y por lo tanto, no se dan ejemplos. Operaciones con la memoria <memory.h> Finalmente se ver un resumen de algunas funciones bsicas de memoria. Sin embargo, no son funciones estrictamente de cadenas, pero tienen su prototipo en #include <string.h>: void *memchr(void *s, int c, size_t n) -- Busca un caracter en un buffer. int memcmp(void *s1, void *s2, size_t n) -- Compara dos buffers. void *memcpy(void *dest, void *fuente, size_t n) -- Copia un buffer dentro de otro. void *memmove(void *dest, void *fuente, size_t n) -- Mueve un nmero de bytes de un buffer a otro. void *memset(void *s, int c, size_t n) -- Pone todos los bytes de un buffer a un caracter dado. El uso de estas funciones es directo y parecido a las operaciones de comparacin de caracteres (excepto que la longitud exacta (n) de todas las operaciones deber ser indicada ya que no hay una forma propia de terminacin). Observar que en todos los casos bytes de memoria son copiados, por lo que la funcin sizeof() ayuda en estos casos, por ejemplo: char fuente[TAM], dest[TAM]; int ifuente[TAM],idest[TAM];

memcpy(dest, fuente, TAM); /* Copia chars (bytes) OK */ memcpy(idest,ifuente,TAM*sizeof(int)); /* Copia arreglo de enteros */ La funcin memmove() se comporta de la misma forma que memcpy() excepto que las localidades de la fuente y el destino podran traslaparse. La funcin memcmp() es similar a strcmp() excepto que unsigned bytes son comparados y se devuelve cero si s1 es menor que s2, etc.

17