Documentos de Académico
Documentos de Profesional
Documentos de Cultura
6.1 Introduccin..... 1 6.2 Funciones estndar.... 2 6.3 Entrada y salida de datos.. 4 6.4 Funciones definidas por el usuario... 10 6.5 Pasaje de parmetros por valor... 12 6.6 Pasaje de parmetros por referencia.. 13 6.7 Punteros.15
INTRODUCCIN
FUNCIONES ESTANDAR
Una funcin en C es un segmento de cdigo independiente que realiza completamente una determinada tarea de un programa. Ventajas del uso de funciones: Permite modularizar programas. Ahorra memoria y tiempo de desarrollo Oculta datos y procesos.
Elementos de una funcin: Nombre: Identificador por el que la funcin es invocada Argumentos: Datos que se le pasan a la funcin para que pueda operar Valor de retorno: resultado de ejecutarse la funcin.
Una declaracin de una funcin es la especificacin tipos de los parmetros formal (en C) del prototipo. tipo del resultado int suma (int , int ); Una definicin de una funcin es la implementacin de datos internos y sentencias que la forman. int suma ( int a , int b) { t su a t t int resultado; res= a+b; return resultado; } En C una funcin debe de ser declarada antes de ser invocada. Las funciones estndar de C son las que forman parte de las libreras que se incluyen con el compilador. Estas funciones realizan sentencias que el lenguaje no es capaz de realizar. Como todas las funciones en C deben de ser declaradas antes de poder ser utilizadas (el compilador debe de conocer el prototipo durante el proceso de traduccin.)
Funcionalidad for testing error codes reported by library functions for adapting to different cultural conventions for computing common mathematical functions for defining several useful types and macros for performing input and output for performing a variety of operations for manipulating several kinds of strings for converting between various time and date formats
Para poder usar una funcin de una librera estndar hay que incluir el fichero que contiene la definicin de prototipos y tipos que maneje esa funcin. Por ejemplo: un programa que calcule el seno de un ngulo necesitara: #include <math.h> #define PI 3.1416 void main (void) { double angulo; // valor del angulo expresado en grados double anguloRadianes; // valor del angulo expresado en radianes double resultado; // aqu ira la lectura del nmero anguloRadianes = angulo * PI /180; resultado = sin (anguloRadianes); // aqu se mostrara el resultado } printf printf() es lo que se denomina una funcin estndar de C, es decir, una funcin que est incluida con el compilador. Para poder usarla dentro de un programa hay que decir en el mismo como es su forma: eso se hace incluyendo la lnea #include <stdio.h> al principio. De momento dejaremos esto as y lo explicaremos dentro de ms sobre printf.
Para poder trabajar o llamar a una funcin estndar hay que conocer que necesita y qu hace. De la funcin printf hay que saber: Su nombre cada vez que se coloca printf en un programa le estamos diciendo al compilador de C que queremos usar esta funcin. Lo que se quiere imprimir, que ir entre los parntesis En general, la expresin (nmeros o texto) que va entre los parntesis de una funcin se llaman parmetros de la funcin. Por ejemplo, si en matemticas se quiere calcular el valor de Frmula en MathML: Logaritmo de tres equis al cuadrado , el parmetro de la funcin logaritmo sera Frmula en MathML: Tres equis al cuadrado . En lenguaje C, algunas funciones necesitan que le demos datos para poder hacer su trabajo y otras no. Por ejemplo, printf necesita el texto que hay que mostrar por pantalla (el cual se entrecomilla), pero para la funcin principal main no es obligatorio. Qu hace y cmo funciona printf() escribe texto en la pantalla del computador. Los detalles de funcionamiento aparecen en el manual del compilador que se est usando. El manual nos dice, por ejemplo, que si colocamos el cdigo \n dentro del parmetro de printf(), se imprimir un salto de lnea. Un compilador suele tener decenas de funciones estndar, aunque su nmero exacto y los detalles concretos de funcionamiento de las funciones estndar de C dependen de cada compilador.
#include <stdio.h> Este archivo define tres streams estndar: stdin, stdout y stderr, que utilizan entrada y salida basada en caracteres y son abiertas automticamente. Por defecto stdin y stderr estn direccionadas a la pantalla, y stdin al teclado. 2. E/S bsica en C Estas operaciones se hacen mediante las funciones getchar() y putchar(): int getchar() lee un carcter desde stdin int putchar(char c) escribe el carcter 'c' en stdout Se dispone tambin de otras funciones, tales como getline(), etc. 3. E/S formateada en C Las funciones printf() y scanf() permiten aplicar formato a los datos de E/S, como por ejemplo, cantidad de decimales, justificacin de texto, conversin a maysculas/minsculas, numeracin hexadecimal, etc. Ambas funciones toman al menos dos argumentos (pueden ser ms): 1. La cadena de formato 2. Los datos a enviar a la salida, en el caso de printf() o a recibir de la entrada, en el caso de scanf() La cadena de formato es un literal encerrado ente comillas dobles ( y ) precedida de un smbolo '%'. La tabla siguiente muestra especificadores frecuentemente utilizados: Especificador c i,d x,X Significado Un carcter (char) Nmero entero (int o double) Nmero hexadecimal (0-9 A-F)
Especificador s f m.n k
Significado Cadena de caracteres (char *) Nmero de punto flotante (float o double) M cifras enteras y n decimales Ajuste de texto a la izquierda Nmero de cifras de un nmero entero
La cadena de formato puede incluir literales y caracteres especiales tales como '\n' '\t' '\0' 4. Ejemplos printf() printf(%-1.3f\n, 3.1415927); 3.141 printf(IVA: 21,5%%\n); IVA: 21,5% 5. Ejemplos scanf() En esta funcin, el primer argumento es la cadena de formato, al igual que en printf(), y el segundo la direccin de las variables que recibirn los datos: char string[80]; scanf(``%s'',string); 6. 3. Entrada/salida con Streams en C++ 1. Definicin: un stream en C++ es un objeto mediante el cual un programa puede insertar o extraer datos utilizando los operadores de insercin << y de extraccin >> o funciones. Los datos pueden ser tipos fundamentales (int, char, double, etc.), o cadenas de caracteres. 2. Streams predefinidos Por defecto, la salida asignada a un programa es la pantalla, y en C++ est representada por el stream cout a la que se denomina salida estndar. Las definiciones necesarias para su uso estn contenidas en el archivo de encabezamiento iostream. Caracteres, nmeros y variables pueden insertarse en cout mediante el operador de insercin <<. Ejemplo: cout << Hola!; // muestra una cadena de texto en la pantalla cout << 120; // muestra un nmero en pantalla cout << x; // muestra el valor de la variable x en pantalla Nueva lnea Tabulacin Carcter nulo (fin de cadena)
El operador de insercin << puede concatenarse: cout << Nombre: << nom << Edad: << ed; Suponiendo que la variable nom contenga la cadena Carla y la variable ed contenga el entero 23, la salida en pantalla ser: Nombre: Carla Edad: 23 Para separar las lneas en pantalla pueden usarse dos mtodos: agregar \n o usar el manipulador endl: cout << Nombre: << nom << \n << Edad: << ed; o cout << Nombre: << nom << endl << Edad: << ed; En ambos casos la salida ser: Nombre: Carla Edad: 23 La entrada estndar de un programa C++ es el teclado, y est representado por el stream cin. El operador de extraccin >> permite obtener caracteres o nmeros desde el teclado: int temperatura; cin >> temperatura; Es importante recordar que cin slo procesa la entrada desde el teclado una vez que el usuario puls la tecla Enter. El tipo de la variable que recibe datos determina cmo se interpretan los datos ingresados por teclado. El operador de insercin puede concatenarse, por ejemplo: cin >> a; cin >> b; es equivalente a: cin >> a >> b; La librera iostream provee dos streams predefinidas ms: cerr, que es la salida estndar de errores y clog, la salida estndar de registro o logging.
3. Streams especiales: archivos C++ provee tres streams especficas para leer y escribir caracteres desde y hacia un archivo en disco: 1. ifstream para leer caracteres desde un archivo 2. ofstream para escribir caracteres en un archivo 3. fstream para leer y escribir caracteres en un archivo Estas clases derivan de istream y ostream, las clases bsicas de entrada/salida definidas en iostream, y estn especialmente diseadas para interactuar con archivos en almacenamiento no voltil (disco, pen drive, etc.). 4. Utilizacin Un ejemplo sencillo de uso de ofstream: #include <iostream> #include <fstream> using namespace std; int main () { ofstream myfile; myfile.open ("salida.txt"); myfile << "Escribiendo en archivos.\n"; myfile.close(); return 0; } Este programa crea (o abre, si existe) un archivo llamado salida.txt y escribe una cadena de texto en su interior. 5. Apertura de un archivo Para utilizar un objeto ifstream, ofstream o fstream debe llevarse a cabo la vinculacin del stream al archivo fsico mediante una operacin de apertura mediante la funcin open(), que toma dos argumentos: nombre del archivo y modo de apertura. El primer parmetro es una cadena de caracteres (const char *) terminada en '\0' y opcionalmente el segundo, que una constante que determinar el uso que pretendemos hacer del archivo segn la siguiente tabla: Modo ios::in Significado El archivo se abre para operaciones de lectura (slo extraccin de
caracteres) ios::out ios::binary ios::app ios::trunc El archivo se abre para operaciones de escritura (slo insercin de caracteres) El archivo se abre en modo binario (su contenido no es texto sino bytes) Las operaciones de insercin tienen lugar al final del archivo, esto es, preservando su contenido inicial Si el archivo abierto existe, se descarta la totalidad de datos que contiene al momento de la apertura
Los modos pueden combinarse utilizando el operador OR '|': ofstream arch; arch.open( datos.txt, ios::out | ios::app | ios::binary); En este caso, datos.txt se abre para escribir datos binarios, preservando su contenido actual. En todos los casos, la funcin is_open() permite verificar si un archivo est disponible para operar sobre el: if( arch.is_open(){ // se puede operar } else cout << Archivo cerrado; 6. Cierre de un archivo Para garantizar que las operaciones realizadas efectivamente se reflejen en el archivo en disco, cuando se termina de trabajar sobre l debe ejecutar una operacin de cierre mediante la funcin close(): arch.close(); 4. Manipuladores La librera estndar iostream provee un conjunto de funciones llamadas manipuladores que, utilizados en conjunto con los operadores << y >> permiten modificar el comportamiento de los streams. La tabla siguiente muestra algunas frecuentemente utilizadas: Manipulador endl ends flush skipws Propsito Nueva lnea (Enter) Inserta un carcter de fin de cadena (\0) Vaca el buffer de un stream Salta espacios y tabulaciones
uppercase
Transforma a maysculas
10
#include <stdio.h> main () { int num; printf (\nTeclee un nmero entero: ); scanf (%d, &num); cuadrado (num); } /* Definicin de la funcin cuadrado() */ cuadrado (int x) { printf (\nEl cuadrado de %d es %d\n, x, x * x); } Es la declaracin de la funcin cuadrado(). Dentro de los parntesis se pone la variable que recibir el valor pasado a cuadrado() y de qu tipo es. As, si se teclea el valor 6, se almacena en num y al hacer la llamada cuadrado (num), la variable num se copia en la variable x, que es con la que trabaja internamente la funcin cuadrado(). Es importante mantener claros dos trminos: 1. El trmino Argumento se refiere a la variable usada al llamar la funcin. 2. El trmino Parmetro Formal se refiere a la variable de una funcin que recibe el valor de los argumentos. Tambin es importante tener claro que la copia de variables se hace slo en una direccin: del argumento al parmetro formal. Cualquier modificacin del parmetro formal realizado dentro de la funcin no tiene ninguna influencia en el argumento. Hay que tener en cuenta es que el tipo de argumento que se utiliza para llamar a una funcin debe ser el mismo que el del parmetro formal que recibe el valor. As, no debe llamarse a la funcin cuadrado con un argumento de tipo float. Un ejemplo que utiliza una funcin que devuelve un valor. El siguiente programa lee dos nmeros enteros del teclado y muestra su producto en pantalla. Para el clculo se usa una funcin que recibe los dos nmeros y devuelve el producto de ambos. #include <stdio.h> main () {
11
int a, b, producto; printf (\nTeclee dos nmeros enteros: ); scanf (%d %d, &a, &b); producto = multiplica (a, b); printf (\nEl resultado es %d, producto); } /* Definicin de la funcin multiplica() */ multiplica (int x, int y) { return (x * y); }
Declaramos dos variables de tipo int en el main, mostramos sus valores, llamamos a la funcin y volvemos a mostrarlos de la siguiente manera:
12
Y veramos en pantalla:
Donde vemos que, en efecto no se modificaron los valores. Pero agreguemos un printf al final de la funcin para ver si se haban modificado o no los valores:
Y obtenemos:
Donde vemos que, en efecto se modificaron los valores de x e y dentro de la funcin pero que no se modificaron las variables originales ya que al hacer el pasaje por valor se trabaja con la copia de las mismas.
13
Luego hacemos el llamado a la funcin de la misma manera, pero pasando las direcciones de memoria de x e y:
Donde vemos que esta vez s se modific el contenido de las variables en cuestin.
14
PUNTEROS
Cmo se organiza la memoria asociada a un programa? Como una coleccin de posiciones de memoria consecutivas. En ellas se almacenan los distintos tipos de datos, que ocupan, por ejemplo: 1 char = 1 byte 1 int = 2 bytes 1 float = 4 bytes Un puntero no es ms que una variable esttica cuyo contenido es una direccin de memoria. Los punteros, por lo tanto, guardan en dos o cuatro posiciones de memoria, la direccin de un conjunto de celdas.
p donde: pc es un puntero a carcter char *pc; c es una variable de tipo carcter char c;
Inicialmente un puntero no apunta a ningn sitio. En C el valor NULL se reserva para indicar que el puntero est vaco (equivalente al nil de la teora). Operadores asociados a punteros &: me da la direccin de un objeto en la memoria. Slo sirve para posiciones de memoria (puede apuntar a variables o a vectores, pero no a constantes o expresiones). Ejemplo: /* prog1.c*/ pc = &c; printf (\nNo tiene lo mismo %c que %d, c, pc); /* Ojo, %d para pc*/ *: me da el contenido de una posicin de memoria (generalmente almacenada en un puntero). Se le llama tambin operador indireccin. Por lo tanto es equivalente: printf (\nTiene lo mismo %d que %d, &c, pc); /* Direcciones */ printf (\nTiene lo mismo %c que %c, c, *pc); /* Caracteres */
15
Un puntero siempre est asociado a objetos de un tipo slo puede apuntar a objetos (variables o vectores) de ese tipo. int *ip; /* Slo puede apuntar a variables enteras */ char *c; /* Slo puede apuntar a variables carcter */ double *dp, /* dp slo puede apuntar a variables reales */ atof (char *); /* atof es una funcin que devuelve un real dada una cadena que se le pasa como puntero a carcter*/ Los operadores * y & son unarios y tienen ms prioridad a la hora de evaluarlos que los operadores binarios. /* prog2.c */ int y, *ip; y = 12; printf (\nValor de y %d, de ip %d, y, ip); /*sin asignar ip */ ip = &y; *ip = *ip + 10; printf (\nValor de y %d, de *ip %d y de ip %d, y, *ip, ip); y = *ip + 10; printf (\nValor de y %d, de *ip %d, y, *ip); *ip += 1; printf (\nValor de y %d, de *ip %d, y, *ip); Es necesario utilizar parntesis cuando aparecen en la misma expresin que otros operadores unarios como ++ o --, ya que en ese caso se evaluaran de izquierda a derecha. ++*ip; (*ip)++; Dado que los punteros son variables, tambin pueden usarse como asignaciones entre direcciones. As: int *ip, *iq; iq = ip; /* Indica que iq apunta a donde apunte el puntero ip. */ 2 Los punteros y los argumentos a funciones Recordemos la equivalencia: Cdigo Algortmico parmetro dato Equivalente C paso por valor Ejemplo en C int scanf (%d, &entero)
16
paso por referencia/ valor int scanf (%d, &entero) devuelto por una funcin paso por referencia int scanf (%d, &entero)
En C, por defecto, todos los parmetros a las funciones se pasan por valor (la funcin recibe una copia del parmetro, que no se ve modificado por los cambios que la copia sufra dentro de la funcin). Ejemplo: Intercambio de dos valores {VERSION ERRONEA} intercambia (int a, int b) { int tmp; tmp = a; a = b; b = tmp } {VERSION CORRECTA} intercambia (int *a, int *b) { int tmp; tmp = *a; *a = *b; *b = tmp }
Para que un parmetro de una funcin pueda ser modificado, ha de pasarse por referencia, y en C eso slo es posible pasando la direccin de la variable en lugar de la propia variable. Si se pasa la direccin de una variable, la funcin puede modificar el contenido de esa posicin (no as la propia direccin, que es una copia). 3 Punteros y vectores En C los punteros y los vectores estn fuertemente relacionados, hasta el punto de que el nombre de un vector es en s mismo un puntero a la primera (0-sima) posicin del vector. Todas las operaciones que utilizan vectores e ndices pueden realizarse mediante punteros. int v[10]; 1 v[0] 3 v[1] 5 v[2] 7 v[3] 9 v[4] 11 v[5] 13 v[6] 15 v[7] 17 v[8] 19 v[9]
v: designa 10 posiciones consecutivas de memoria donde se pueden almacenar enteros. int *ip; Designa un puntero a entero, por lo tanto puede acceder a una posicin de memoria. Sin embargo, como se ha dicho antes v tambin puede considerarse
17
como un puntero a entero, de tal forma que las siguientes expresiones son equivalentes: ip = &v[0] x = *ip; *(v + 1) v+I 4 Aritmtica de punteros El compilador C es capaz de adivinar cul es el tamao de una variable de tipo puntero y realiza los incrementos/decrementos de los punteros de la forma adecuada. As: int v[10], *p; p = v; /* p Apunta a la posicin inicial del vector*/ /* p + 0 Apunta a la posicin inicial del vector*/ /* p + 1 Apunta a la segunda posicin del vector*/ /* p + i Apunta a la posicin i+1 del vector*/ p = &v[9]; /* p apunta ahora a la ltima posicin (dcima) del vector */ /* p - 1 Apunta a la novena posicin del vector*/ /* p - i Se refiere a la posicin 9 - i en v*/ Ejemplo de recorrido de un vector utilizando ndices y punteros. /* prog3.c*/ main(){ int v[10]; int i, *p; for (i=0; i < 10; i++) v[i] = i; for (i=0; i < 10; i++) printf ("\n%d", v[i]); p = v; for (i=0; i < 10; i++) printf ("\n%d", *p++); /* Tras cada p++ el puntero seala a la siguiente posicin en v */ } C realiza las mismas operaciones con independencia del tipo de la variable. De esta forma, si tenemos dos variables que son punteros: int *ip, vi[10]; /* Necesita dos posiciones para representar un entero */ ip = v x = v[0]; v[1] &v[i]
18
char *cp, vc[10]; /* Necesita una posicin para representar un carcter */ ip = &vi[0]; cp = &vc[0]; Las expresiones: ip + 1, ip++ Apunta al siguiente elemento (dos posiciones): vi[1] cp + 1, cp++ Apunta al siguiente elemento (una posicin): vc[1] Diferencia entre puntero y nombre de vector: Mientras que un puntero es una variable y puede intervenir en asignaciones o incrementos, el nombre del vector no es una variable, por lo tanto, no pueden realizarse operaciones del tipo: int v[10], *a; v = a; v++; Dado que el nombre del vector es un puntero, puede utilizarse para pasar un vector como parmetro de una funcin (lo que permite modificar el contenido de esas posiciones de memoria adyacentes, o lo que es lo mismo, los elementos del vector). char palabra[10]; scanf (%s, palabra); /* Modifica las posiciones de memoria */ sort (palabra, 0, strlen(palabra)); /* sort va a modificar el contenido del vector, por lo tanto se pasar la direccin del primer elemento = palabra = &palabra[0]. strlen es una funcin de la librera estndar, cuyo macro es: (int strlen (char *)) La funcin nos devuelve la longitud de un vector de caracteres */ Recordatorio: Los vectores de caracteres terminan en el carcter \0. Ejemplo 1: Realizar una funcin que sea equivalente a strlen. int longitud (char *) char cadena[20]; gets(cadena); printf (\nLa longitud de la cadena %s es %d, cadena, longitud(cadena)); Ejemplo 2: Realizar una funcin equivalente que permita realizar a := b, cuando ambas son cadenas. copia (char *, char *) char cadena[20], *copiada;
19
printf (\nDame la primera cadena); gets (cadena); copia (cadena, copiada); printf (\nLa segunda cadena es %s, copiada); Solucin a 1): main(){ char cadena[20]; int longitud(); printf ("\nDame una cadena (maximo 20): "); gets(cadena); printf ("\nLa cadena %s mide %d ", cadena, longitud(cadena)); } int longitud(char *s){ int l; l = 0; while (*s++ != '\0') l++; return l; } Solucin a 2): main(){ char uno[20], dos[20]; printf ("\nDame una cadena:"); gets(uno); copia(uno, dos); printf ("\nLa copia de %s\n es %s\n", uno, dos); } copia (char *s, char *p) { while (*s) *p++ = *s++; *p = '\0'; }
20