La mayor parte de los programas de computo que resuelven problemas de la vida real son mucho mayores que los programas que hemos visto. La experiencia ha mostrado que la mejor forma de desarrollar y mantener un programa grande es construirlo a partir de piezas menores o mdulos, siendo cada uno de ellos mas fcil de manipular que el programa original. Esta tcnica se conoce como divide y vencers . C fue diseado para hacer funciones eficientes y fciles de usar. Los programas C consisten generalmente de varias funciones pequeas en vez de pocas grandes.
PROGRAMACION EN LENGUAJE C
ALGORITMOS Y LENGUAJES DE PROGRAMACION Pgina 3
FUNCIONES ESTANDAR El lenguaje C, C++ contiene numerosas funciones, cuando se emplean funciones de esta biblioteca estandar, se incrementa la transportabilidad de los programas. Las funciones estandar se dividen en grupos, todas las funciones que pertenecen al mismo grupo estan declaradas en el archivo de cabecera (aquel que dice xxx.h), la letra "h" significa header en ingls y es lo que se llama cabecera. Para incluir alguna funcin perteneciente a estas cabeceras debemos escribir lneas de cdigo como se muestra de ejemplo: #include He disenado esta tabla para que estudiemos las bibliotecas de funciones, obviamente son las que he encontrado en mis libros y sistemas.
Nombre de Biblioteca Descripcion assert.h Es proporcionar una definicion de la macro assert, que imprime un mensaje de error y aborta el programa alloc.h Existen funciones para asignar, liberar memoria, u obtener informacion de bloques de memoria. ctype.h Son funciones que nos permiten conocer la naturaleza de un caracter, o bien para convertir de mayusculas a minusculas y viceversa; y valores enteros a codigos ASCII. dir.h Esto permite ordenar, crear, modificar, mover y eliminar directorios errno.h Representa los numeros de error, despues que ocurre un error se puede consultar el valor de la varianble del sistema deerrno para obtener mas informacion sobre ese error. float.h Define los limites de los tipos de coma flotante limits.h Define los limites de los diferentes tipos de enteros math.h Contiene las funciones matematicas estandar utilizadas en C y C++ PROGRAMACION EN LENGUAJE C
ALGORITMOS Y LENGUAJES DE PROGRAMACION Pgina 4
setjmp.h Define el tipo de jmp_buf para algunas funciones. signal.h Contiene funciones de estado. stdarg.h Define funciones que pueden ser llamadas con diferentes numeros de argumentos, de modo que se pueda escribir f(a) y f(a,b). stdef.h Se definen algunos tipos especiales stdio.h Incorporan las funciones de Entrada - Salida E/S estandar, tipos y macros stlib.h Declara funciones que son utiles para diferentes propositos, en especial de busqueda y ordenacion. string.h Este archivo contiene funciones para manejo de cadenas de caracteres. time.h Contiene funciones relativas a fechas y horas
FUNCIONES DEFINIDAS POR EL USUARIO Un programa en C++ se forma por una coleccin de funciones. Todos los programas se construyen a partir de una o ms funciones que se integran para crear una aplicacin. Todas las funciones contienen uno o ms estatutos C++ y se crean generalmente para realizar una nica tarea La definicin de una funcin se realiza escribiendo primero el tipo del valor de retorno de la funcin, despus el nombre de la funcin, posteriormente entre parntesis las variables que utilizar dicha funcin (parmetros) y finalmente las instrucciones de la funcin. Las funciones definidas por el usuario se invocan por su nombre y los parmetros opcionales que se puedan tener. Todas las funciones tienen nombre y una lista de valores que recibe. Se puede asignar cualquier nombre a la funcin, pero normalmente se procura que dicho nombre describa el propsito de la funcin. Una declaracin de funcin indica al compilador el nombre de la funcin que se est invocando en el programa. Si la funcin no se defina, el compilador informa de un error. PROGRAMACION EN LENGUAJE C
ALGORITMOS Y LENGUAJES DE PROGRAMACION Pgina 5
Por ejemplo: double promedio( int a, int b, int c) {return (a + b + c ) / 3.0;} Declara a la funcin promedio, la cual recibe tres valores enteros y calcula y regresa el promedio de ellos. int suma( int a, int b) {return (a + b);} Declara a la funcin suma, la cual recibe dos valores enteros y calcula y regresa la suma de ellos. PASO POR REFERENCIA O POR VALOR. Como vimos las funciones por lo general reciben parmetros, stos hasta el momento fueron pasados a la funcin mediante el "paso por valor" que consiste en hacer un copia del argumento, para que la funcin trabaje con la copia y no con el argumento original. Esto significa que si la funcin modificara el valor, el original no se alterara ya que estamos manejando una copia. Esto resulta bastante til para asegurarnos de que la funcin no modifique nuestros argumentos de manera accidental. Pero surgen dos problemas: 1. Podramos querer modificar el argumento original y no una copia. 2. Con mucha cantidad de variables (o estructuras como veremos) el paso por valor (copiando) puede resultar un gasto excesivo de memoria. Para resolver estos problemas contamos con las referencias y punteros, por el momento nos ocuparemos de las referencias. Una referencia a una variable es un "alias" de la variable. Para indicarle a C++ que estamos hablando de una referencia y no una variable anteponemos al nombre el caracter ampersand (&). Por ejemplo una referencia llamada refPresupuesto apuntando a un valor double se escribira as: PROGRAMACION EN LENGUAJE C
ALGORITMOS Y LENGUAJES DE PROGRAMACION Pgina 6
double &refPresupuesto Si quisieramos que una funcin trabaje con la variable original y no con una copia podramos indicarle a la funcin que reciba el parametro como una referencia, veamos un ejemplo: //Paso por referencia #include <iostream> using std::cout; using std::cin; using std::endl; void elevarCuadrado (int &); //prototipo de funcion que recibe una referencia a un int int main() { int x = 0; //Declaracio e inicializacion en 0. cout << "Ingrese x para elevarlo al cuadrado" << endl; cin >> x; cout << "antes de elevarse es " << x <<endl; elevarCuadrado(x); //Notar que la llamada no es diferente a un paso por valor. cout << "x despues de elevarse es " << x << endl;//muestra el valor modificado por la funcion return 0; } void elevarCuadrado (int &y ) //funcion que no devuelve nada (void) y recibe una referencia a un int en este caso (x) { y = y*y; //La funcion no devuelve ningun valor, pero modifica el argumento original (x) //ya que estamos trabajando con una referencia. }
Cuando una funcin se declara anteponiendo la palabra reservada void le estamos diciendo a C++ que esa funcin no devolvera valor alguno. Como se comenta en el cdigo, en la llamada de la funcin es importante notar que no hay manera de darse cuenta si el parametro es pasado por referencia (modificable) o si es por valor (se le enva una copia a la funcin). Paso por referencia constante PROGRAMACION EN LENGUAJE C
ALGORITMOS Y LENGUAJES DE PROGRAMACION Pgina 7
Adems de poder modificar el valor, aqu obtenemos la ventaja de no realizar una copia de la variable en cuestin. Sin embargo podramos querer obtener esta ventaja (de aprovechar memoria), pero no perder la proteccin de la variable (que la original no pueda ser modificada por la funcin). Este problema se resuelve, declarando en la funcin una referencia constante, con la palabra reservada const. Esto hara que se pase el argumento por valor, pero que no se permita la modificacin de la variable original. Si al cdigo anterior le agregasemos la palabra const en el prototipo y en la declaracin, e intentasemos compilarlo generaramos un error, ya que el compilador nos avisa que no se puede modificar el valor al que apunta la referencia, lo cual es muy til para detectar errores. El cdigo quedara as y pueden probarlo: //Paso por referencia constante. #include <iostream> using std::cout; using std::cin; using std::endl; void elevarCuadrado (const int &); //prototipo de funcion que recibe una referencia a un int int main() { int x = 0; //Declaracio e inicializacion en 0. cout << "Ingrese x para elevarlo al cuadrado" << endl; cin >> x; cout << "antes de elevarse es " << x <<endl; elevarCuadrado(x); //Notar que la llamada no es diferente a un paso por valor. cout << "x despues de elevarse es " << x << endl; return 0; } void elevarCuadrado (const int &y ) //funcion que no devuelve nada (void) y recibe una referencia a un int en este caso (x) { y = y*y; // Error no se puede modificar ya que es constante.
} Aviso del compilador: refConstEj.cpp: In function void elevarCuadrado(const int&): refConstEj.cpp:19: error: assignment of read-only reference y PROGRAMACION EN LENGUAJE C
ALGORITMOS Y LENGUAJES DE PROGRAMACION Pgina 8
PUNTEROS Cada variable de un programa tiene una direccin en la memoria del ordenador. Esta direccin indica la posicin del primer byte que la variable ocupa. En el caso de una estructura es la direccin del primer campo. En los ordenadores actuales la direccin de inicio se considera la direccin baja de memoria. Como en cualquier caso las variables son almacenadas ordenadamente y de una forma predecible, es posible acceder a estas y manipularlas mediante otra variables que contenga su direccin. A este tipo de variables se les denomina punteros. Los punteros C son el tipo ms potente y seguramente la otra clave del xito del lenguaje. La primera ventaja que obtenemos de los punteros es la posibilidad que nos dan de poder tratar con datos de un tamao arbitrario sin tener que moverlos por la memoria. Esto puede ahorrar un tiempo de muy importante en algunos tipos de aplicaciones. Tambin permiten que una funcin reciba y cambie el valor de una variable. Recordemos que todas las funciones C nicamente aceptan parmetros por valor. Mediante un puntero a una variable podemos modificarla indirectamente desde una funcin cualquiera. Un puntero se declara de la forma: tipo *nombre; float *pf; PLANETA *pp; char *pc; Para manipular un puntero, como variable que es, se utiliza su nombre; pero para acceder a la variable a la que apunta se le debe preceder de *. A este proceso se le llama indireccin. Accedemos indirectamente a una variable. Para trabajar con punteros existe un operador, &, que indica 'direccin de'. Con l se puede asignar a un puntero la direccin de una variable, o pasar como parmetro a una funcin. void prueba_puntero ( void ) { long edad; long *p; PROGRAMACION EN LENGUAJE C
ALGORITMOS Y LENGUAJES DE PROGRAMACION Pgina 9
p = &edad; edad = 50; printf("La edad es %ld\n", edad ); *p = *p / 2; printf("La edad es %ld\n", edad ); } void imprimir_string ( char string[] ) { char *p; for ( p = string; *p != '\0'; p++ ) imprimir_char(*p); } Definimos un vector de N_PLA componentes de tipo PLANETA. Este tipo est formado por un registro. Vemos que en la funcin de inicializacin del vector el puntero a la primera componente se inicializa con el nombre del vector. Esto es una caracterstica importante de C. La direccin de la primera componente de un vector se puede direccionar con el nombre del vector. Esto es debido a que en la memoria del ordenador, los distintos elementos estn ordenados de forma ascendente. As, SSolar se puede utilizar como &SSolar[0]. A cada iteracin llamamos a una funcin que nos inicializar los datos de cada planeta. A esta funcin le pasamos como argumento el puntero a la componente en curso para que, utilizando la notacin ->, pueda asignar los valores adecuados a cada campo del registro. Debemos fijarnos en el incremento del puntero de control de la iteracin, p++. Con los punteros se pueden realizar determinadas operaciones aritmticas aunque, a parte del incremento y decremento, no son muy frecuentes. Cuando incrementamos un puntero el compilador le suma la cantidad necesaria para que apunte al siguiente elemento de la memoria. Debemos fijarnos que esto es aplicable slo siempre que haya distintas variables o elementos situados consecutivamente en la memoria, como ocurre con los vectores. PROGRAMACION EN LENGUAJE C
ALGORITMOS Y LENGUAJES DE PROGRAMACION Pgina 10
De forma similar se pueden utilizar funciones que tengan como parmetros punteros, para cambiar el valor de una variable. Veamos: void intercambio ( void ) { int a, b; a = 1; b = 2; swap( &a, &b ); printf(" a = %d b = %d\n", a, b ); } void swap ( int *x, int *y ) { int tmp; tmp = *x; *x = *y; *y = tmp; } La sintaxis de C puede, a veces, provocar confusin. Se debe distinguir lo que es un prototipo de una funcin de lo que es una declaracin de una variable. As mismo, un puntero a un vector de punteros, etc... int f1(); funcin que devuelve un entero int *p1; puntero a entero int *f2(); funcin que devuelve un puntero a entero int (*pf)(int); puntero a funcin que toma y devuelve un entero int (*pf2)(int *pi); puntero a funcin que toma un puntero a entero y devuelve un entero int a[3]; vector de tres enteros int *ap[3]; vector de tres punteros a entero PROGRAMACION EN LENGUAJE C
ALGORITMOS Y LENGUAJES DE PROGRAMACION Pgina 11
int *(ap[3]); vector de tres punteros a entero int (*pa)[3]; puntero a vector de tres enteros int (*apf[5])(int *pi); vector de 5 punteros a funcin que toman un puntero a entero y devuelven un entero. En los programas que se escriban se debe intentar evitar declaraciones complejas que dificulten la legibilidad del programa. Una forma de conseguirlo es utilizando typedef para redefinir/renombrar tipos. typedef int *intptr; typedef intptr (*fptr) ( intptr ); fptr f1, f2;
CONCLUSION Tanto C como C++ son lenguajes de programacin de propsito general. Todo puede programarse con ellos, desde sistemas operativos y compiladores hasta PROGRAMACION EN LENGUAJE C
ALGORITMOS Y LENGUAJES DE PROGRAMACION Pgina 12
aplicaciones de bases de datos y procesadores de texto, pasando por juegos, aplicaciones a medida, etc En la informacin mostrada anteriormente se detallo algunos de los conceptos bsicos del programa en lenguaje c. Solo fue para reafirmar los conocimientos obtenidos durante el curso de l materia de algoritmos y lenguajes de programacin.