Cristian Blanco www.cristianblanco.es Tema III: Caracteres y cadenas Pagina:1 de 9 Tema III-(a) CARACTERES Y CADENAS DE CARACTERES El tipo de dato carácter Los caracteres son datos predefinidos de tipo char ocupan 1 byte de longitud. Para indicar que se quiere trabajar un carácter literal este debe ir encajado entre comillas simples, es decir 'a', 'z' etc. Existe una correspondencia entre caracteres y enteros. Todo carácter es pasado a su formato entero y al trabajar con él, según el tipo de formato en la función de presentación (si aparece como “%c” ó “%d”) se trata como un carácter o como un entero . Como ejemplo podemos ver los siguientes programas: #include <stdio.h> // programa para códigos ASCII, codificación decimal en 8 bits int main() { int t; for(t=65;t<=200;t++) { printf("letra: %c numero %d\n",t,t); } } #include <stdio.h> // programa para códigos ASCII // t es un entero que recorre de'a' -> 'z' int main() { int t; // fijarse que el bucle va de 'a' a 'z' for(t='a';t<='z';t++) { printf("letra: %c numero %d\n",t,t); } } Cristian Blanco www.cristianblanco.es Tema III: Caracteres y cadenas Pagina:2 de 9 Cadenas de caracteres Para trabajar con frases y palabras existe un tipo de dato estructurado que son las cadenas de caracteres y que no son más que agrupamientos de varios caracteres sobre un solo nombre e indicando su extensión. La forma de declararlos es : Ejemplo: char m[20]; Definimos una cadena de hasta 20 caracteres denominada m los caracteres individuales pueden ser manejados como m[0]….m[19] Siempre que leemos una cadena el compilador coloca un carácter nulo (terminador) denominado “\0” al final del mismo para indicar que la cadena termina, por tanto debemos reservar espacio en la definición para los caracteres "reales" mas uno que será el terminador de la cadena. El nombre de la cadena es tratado por el compilador como un puntero a la dirección del comienzo de dicha cadena, es decir es lo mismo &m[0] que m. Debido a lo anterior cuando pasemos cadenas como parámetros en una función pueden aparecer como: Int función(char *cad….) Int función (char []) Ambas declaraciones son válidas y, cuando dicha función se llama no hay que indicar paréntesis ni dimensión, pues el prototipo de la función, ya sabe que ese parámetro es una cadena. Al ser el nombre de una cadena su dirección de memoria, las cadenas de caracteres se pasan como parámetros siempre por referencia. El siguiente ejemplo muestra cómo definir una función cuyos parámetros son cadenas y como llamarla: Cristian Blanco www.cristianblanco.es Tema III: Caracteres y cadenas Pagina:3 de 9 /*Ejercicio de cadenas*/ #include <stdio.h> #include<string.h> int posicion(char *,char *); int main() { char cad[500]; char buscado[20]; int valor; printf("Dame la frase:\n"); gets(cad); printf("la frase donde buscamos es:\n%s\n",cad); printf("dame la cadena a buscar.-\n"); gets(buscado); valor=posicion(cad,buscado); if (valor!=0) /* el valor cierto es cualquiera el falso es cero*/ printf ("El resultado es: %d",valor); else printf("La cadena no se encuentra"); }// fin del main() // mas adelante entenderemos la función posición cuado veamos strstr (librería string.h) int posicion(char *cad,char *buscado) { // entrada : cad cadena donde se busca // entrada : buscado cadena buscada // salida : int posicion lugar del caracter donde empieza la cadena // si no se encuntra devuelve cero char *p1; int valor=0; p1=strstr(cad,buscado); if (p1 !=NULL) { /* strstr de vuelve un puntero en p1 (direccion) como las variables cadenas son punteros cad es direccion con lo cual si hacemos la diferencia tendremos la posicion relativa de buscado en en cad) */ valor=p1-cad+1; } return valor; }//fin de posicion Cristian Blanco www.cristianblanco.es Tema III: Caracteres y cadenas Pagina:4 de 9 Los caracteres de una misma cadena se almacenan en posiciones consecutivas de memoria. Esto es útil para usar determinadas funciones que devuelven la posición en memoria de un carácter de una cadena y que más adelante veremos. Mas adelante al final del tema, en el apéndice 1 veremos las funciones más importantes que contiene la librería de funciones para manejo de caracteres, y cadenas. (Todas son ANSI C) Los ficheros de cabecera que contienen estas funciones son <ctype.h> <stdlib.h> <string.h> Además de éstas existen dos funciones nuevas para leer y escribir cadenas estas son: gets(cadena) y puts(cadena). Una lee una cadena desde el teclado y la almacena en cadena y la otra imprime en la pantalla la cadena almacenada en cadena. gets(cadena) permite la entrada de cadenas con espacios en blanco entre medio, mientras que scanf no lo hace. Ambas están definidas en el fichero de cabecera <stdio.h> Debido al tratamiento que da C al buffer del teclado pudieran presentarse problemas a la hora de leer distintos tipos de datos numéricos y de texto porque el carácter de fin de entrada “\n”(enter), se queda en el buffer y hacer que una entrada quedara vacía. Es por ello necesario utilizar la función fflush(stdin) que limpia el buffer de entrada también. Si probáis este programa suprimiendo la llamada a fflush(stdin) comprobaréis que hay problemas en la entrada de datos. #include<stdio.h> // uso de fflush(stdin); para limpiar el buffer de teclado int main() { int t,j; char cad[30]; for (t=1;t<=3;t++) { printf("dame numero:"); scanf("%d",&j); fflush(stdin);// sin esta llamada a esta función el programa no funciona printf("dame cadena:"); gets(cad); } } Cristian Blanco www.cristianblanco.es Tema III: Caracteres y cadenas Pagina:5 de 9 Apéndice (1) Funciones ANSI C para manejo de caracteres y cadenas Cristian Blanco www.cristianblanco.es Tema III: Caracteres y cadenas Pagina:6 de 9 Cristian Blanco www.cristianblanco.es Tema III: Caracteres y cadenas Pagina:7 de 9 Cristian Blanco www.cristianblanco.es Tema III: Caracteres y cadenas Pagina:8 de 9 Apéndice(2).-Funciones para números aleatorios Será necesario muchas veces hacer simulaciones de los programas realizados con gran cantidad de datos, generalmente numéricos, para probar su eficiencia, como es lógico no vamos a meter a mano dos o tres mil datos, sino que usaremos unas funciones que nos permitirán generar números al azar en el rango que nosotros deseemos, estas son: rand() srand(time(NULL)) Estas funciónes necesita declarar la librería <stdlib.h> y <time.h> respectivamente Ejemplo: x=rand() % 30; almacenará en x un numero entero entre 0 y 29 Si lo que se desea es generar números entre un rango desde a hasta b tendremos que usar la función de la siguiente forma: x=rand() % (b-a+1)+a, de esta forma la función genera un número desde 0 hasta b-a, y al sumarle a quedarán entre a y b Ejemplo: Si deseo generar un número al azar entre 0 y 36, el caso de una ruleta de casino, tomando a=0 b=36 el uso de la función seria: x=rand()% 37; Si quisiéramos números entre 5 y 10 el uso de la función sería: x=rand() %6+5; y así sucesivamente para cada intervalo deseado. No obstante esta función tiene un "problema" y es el que siempre que se ejecutase el programa empezaría con el mismo número al azar y repetiría la misma secuencia de números con lo cual el término aleatorio no es correcto, es por ello que existe otra función, para "barajar" o "remover" la secuencia de números, basada en un calculo con los milisegundos del reloj del procesador esta es srand(time(NULL)); si llamamos a esta función antes de empezar a usar rand() la serie de números será distinta, en cada ocasión que los generemos. Cristian Blanco www.cristianblanco.es Tema III: Caracteres y cadenas Pagina:9 de 9 He aquí un ejemplo de genracion de 10 numeros al azar con srand con lo que alteramos la serie cada vez que ejecutamos, si obviaramos dichas llamada a esa función observad que los resultados de los números son siempre iguales: /* ejemplo de generacion de nums aleatorios */ #include <stdio.h> #include <stdlib.h> #include <time.h> int main () { int iSecret, t; /* alteramos la secuencia de azar */ srand ( time(NULL) ); /* generamos 10 numeros al azar Entre 1 y 10000*/ for (t=1;t<=10;t++) { iSecret = rand() % 10000 + 1; printf ("aleatorio %d\n",iSecret); fflush(stdout); } printf ("Valor maximo del numero aleatorio %d\n",RAND_MAX); return 0; }