Anda di halaman 1dari 25

Definicin de Variables: Para definir una constante o una variable en C en primer lugar debemos plantearnos que tipos de datos

queremos que almacene y su longitud. Hay que tener tambin en cuenta que al definir una variable lo que hacemos es asignar una direccin o serie de direcciones de memora al nombre de una variable. Estamos por lo tanto ocupando memoria con varibales, lo que debera invitarnos a liberar dicha memoria si no vamos a utilizarla en nuestro programa. es muy comn encontrar programas bien escritos que ocupan demasiada memoria con variables que no son realmente necesarias o con variables que reservan ms espacio del que realmente necesitan. Es importante entender el rango de validez de una variable. Una variable es valida dentro de la funcin en la que ha sido definida, en cualquier otra funcin la variable, aunque se llame igual, no se vera afectada por los cambios que realizemos sobre la misma. Pero Cmo puedo definir y utilizar variables que afecten a todo el programa?, para definiremos estas variable fuera de main y con ello tendremos variables de alcance global. Los tipos bsicos de C son: char int float double Un nico Byte, capaz de almacenar un carcter. Almacena un entero por lo general del tamao mximo del O.S. Almacena un valor de coma flotante de precisin simple Almacena un valor de coma flotante de precisin doble

Estos tipos bsicos tienen adems unos modificadores: short Un nico Byte, capaz de almacenar un carcter. long Almacena un entero por lo general del tamao mximo del O.S. signed, Almacena un valor y su signo, Almacena un valor sin signo, lo que permite unsigned almacenar un mayor numero de enteros positivos const Almacena un valor constante La definicin de variables esta ligada a la capacidad de: Ordenador (Relacin entre memoria y CPU) O.S. Compilador La Constante es la unidad de informacin mnima de C, para pode definir una constante debemos escribir al principio del fichero lo siguiente: #define PI 3,141592 /*Para definir nmero bsta con esta estructura */ #define SI 'YES' /* Para definir texto empleamos las comillas simples */ Como vemos para definir constantes no es necesario emplear ";" al final de la linea de definicin. Pero con esto no tenemos nada en nuestro programa. Ahora deberemos llamar a dicha macro desde nuestro programa: superficie = PI * radio * radio; Bueno ya hemos llamado a nuestra macro aunqeu ahora nos falta definir las dems variables: #include <stdio.h> /* Llama a la libreria con la funcin printf y scanf */ #define PI 3,141592 /*Para definir nmero bsta con esta estructura */ main () { float radio, superficie; printf("\nIntroduzca el radio del circulo:\n"; scanf("%f", &radio); superficie = PI * radio * radio;

printf("\n La superficie del radio %f es %f", radio, superficie) exit(0); } Acabamos de ver el primer programa completo de C. Pero tiene un fallo, buscalo. Supongo que ya lo habras encontrado, si es as enhoraburena. A continuacin vamos a analizar como se deben definir las variables y cules deben ser los nombres de las msmas: int numero; /* Define un entero de nombre nmero*/ int numero[32]; /*Define una matriz de enteros de 32 valores */ const int pi = 3.141592 /*Define una variable de valor constante pi y que toma por definicin ese valor y no se puede cambiar*/ int numeros[4][4]; /*Define una matriz de 16 elementos */ En las lneas anteriores hay un error? Entonces si no se puede cambiar porque estamos empleando del "define" anterior?, como se diferencia este del anterior mtodo de definicin de constantes. Tenemos en primer lugar que con el "define", nosotros lo que preparamos es una macro para que despues el precompilador haga una sustitucin de todas las variables definidas con este mtodo por sus valores, no son por lo tanto variables y hay que verlas cuando las empleemos como una sustitucin por el valor que representan. Por otro lado tenemos que con "const", lo que estamos definiendo es una variable a la que se accede slo si es necesario y que no se puede cambiar, una vez definida. Veamos como trata C los carcteres: char nombre; /*Define una variable de tipo caracter de un nico carcter */ char nombre[32]; /*Define una variable de tipo caracter de 32 caracteres */ char ciudad[Pamplona]; /* Define un vector de caracteres de 8 carcteres */ char ciudad[32] = 'Pamplona'; /*Define un vector de caracteres de 32 carcteres e inserta Pamplona */ Vamos a estudiar a continuacin como trata C los float y double: float numero; /* Define un decimal de nombre numero*/ double numero[32]; /*Define una matriz de decimales de 32 valores */ const float pi = 3.141592 /*Define una variable de valor constante pi y que toma por definicin ese valor y no se puede cambiar*/ double numeros[4][4]; /*Define una matriz de 16 elementos */ float sum=0.; double factor=0.21e-6; /* Como vemos double soporta elevar los valores */ Por ltimo vamos a ver que es un vector del tipo enum. Con un vector del tipo enum los que conseguimos es almacenar enumeraciones de constantes. Si no se indica lo contrario el primer valor de la enumeracin vale 0..N. Asi: enum meses { JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC}; enum mese {JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC}; enum boleano { NO, YES}; Hemos hablado de como se definen las variables, pero no hemos dicho nada de los nombres validos para las variables, debemos dedicar un momento a pensar en ello. Las variables deben empezar siempre por un caracter vlido y nunca por un nmero, deben tener menos de 8 caracteres aunque en algunos casos son 32. p.e.: Vlidos Invlidos x 4th y12 "x" VALOR no-juego _valor tampoco juego suma_1 12 variable 'y'

Por ltimo debemos hacer algunas apreciaciones de los nombres de las variables, deben ser represntativos y fciles de memorizar. Vlidos Invlidos horaTD> tiempo media valor VALOR_MAXIMO MUCHO usuario mas12 Una vez hemos visto como podemos definir variables y como podemos definir matrices vamos a ver que operadores lgicos, matemticos o de bit tenemos en C para operar sobre dichas matrices y variables. Los operadores que vamos a describir a continuacin son los de ANSI C, por ello pueden variar de un compilador a otro, si bien sern comunmente aceptados. Operadores: (),[],->,. izquierda a derecha ! ~,++,--,+,-,*,& derecha a izquierda *,/,% izquierda a derecha +,izquierda a derecha <<,>> izquierda a derecha <,<=,>,>= izquierda a derecha ==,!= izquierda a derecha & izquierda a derecha ^ izquierda a derecha | izquierda a derecha && izquierda a derecha || izquierda a derecha ?: derecha a izquierda =,+=,-=,*=,/=,%=,&=,^=,|=,<< =,>>= derecha a izquierda A continuacin vamos a analizar con un poco ms de detalle algunos de ellos: int a,b; a = 20; b = 18; a++; /* Suma uno a 'a'*/ b--;/*Resta uno a 'b'*/ b = b + a; /suma a y b y devulve el valor en b*/ b += a; /*suma a y b y devulve el valor en b*/ a = b*a; /* Multiplica a y b y lo devuelve en a*/ a *= b; /* Multiplica a y b y lo devuelve en a*/ a = b / a; /* Divide a entre y lo devuelve en a */ a /=b ; /* Es lo mismo que decir a = a / (b) */ Veamos tambin como funcionan los siguientes: int a,b,c; a=5; b=6; c=8; if (a > b) a += b; if (a < b) a =b; if (a == b && c != a) c=a; if (a == b || a == c) a=b=c; c = (a >b)?a:b;

Tabla de caracteres ANSI. Tabla de palabras reservadas en C: auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch unsigned while void union

Estructuras de control: A continuacin vamos a hacer una revisin dealgunas de las estructuras de control ms importantes en C. Una estructura de control es una orden que permite a un programa en C saltar de una funcin a otra o seguir un camino lgico distinto.

If then else:
#include main () { float radio, superficie; printf("\nIntroduzca el radio del circulo:\n"; scanf("%f", &radio); if (radio == 0) { printf (" Error cero no es un valor\n"); exit(0); } else if (radio <= 0) { printf("Error no se admiten valores } %f es %f", radio, superficie) } } exit(0); else { superficie = PI * radio * radio; printf("\n La superficie del radio exit(0);

negativos\n");

Como vemos es una estructura de control condicional que se basa en el valor que se le pasa entre parntesis para poder llevar a cabo la operacin que se le indica entre llaves. En esta estructura se analiza el contenido de los parntesis, si este es cierto devuelve 'true' y ejecuta los parntesis, si no lo es devuelve 'false' y pasa al siguiente punto de funcin.

Switch:

#include main () { int valor; printf("\nIntroduzca un numero:\n"; scanf("%i", &valor); switch(valor) { case '1': print f("Has escrito %i", valor); break; case '2': printf("Hola break; default: printf("Los valores break; }

....\n");

validos son 1 y 2 y no %i", valor); exit(0); }

Switch como su nombre indica es un interruptor que lo que hace es realizar una accin u otra segn la instruccin recibida. Tenemos los case con los que podemos controlar cada caso particular y default con el que controlamos las excepciones.

While:
#include main () { int valor; printf("\nIntroduzca un numero:\n"; scanf("%i", &valor); while (valor > 0) { printf ("%i es un numero } exit(0); } valor--;

positivo", valor);

Con un bucle while lo que buscamos es que se realize una operacin mientras se cumpla la condicin entre parntesis. Es un bucle muy empleado para poder realizar una accin continuamente, como revisar puertos de red o recoger la entrada de un aparato conectado. Para estos casos se suele usar con:
#include main () { int valor;

printf("\nIntroduzca un numero:\n"; scanf("%i", &valor); while (<>) { positivo", valor); } exit(0); } printf ("%i es un numero valor--;

For:
#include main () { int valor, i; printf("\nIntroduzca un numero:\n"; scanf("%i", &valor); for (i =0;i < valor; i++) { valor); Printf ("%i es un numero positivo", } exit(0); }

Tenemos una gran potencia con los bucles For, con ellos podemos realizar en una linea lo que en la mayoria de los While nos llevaria ms de tres. Es adems ms simple de rastrear errores que los bucles while. A continuacin vamos a ver la definicin de funciones: Definir una funcin en C requiere de haber comprendido todo lo anterior, si en este momento tiene alguna duda debera volver hacia atras y repasar los tipos, los modificadores y las estrucutras de control. C basa toda su arquitectura en funciones, as un programa de C es ejecutable si existe una funcin main(), y las librerias son en definitiva programas sin esta funcin. Tenemos que las funciones se definen asi:
tipo de retorno nombre (declaracin de argumentos) {

declaraciones e instrucciones }

Tipo de retorno: es el tipo que vamos a devolver con el return de la funcin. Debe ser de un tipo bsico o declarado. (int, double, etc.) Nombre: Se aplica lo mismo que a la definicin de variables.

Argumentos: Son las variables que debe recibir la funcin para poder realizarse. Declaraciones e instrucciones que componen en s msma la funcin.
#include <stdio.h> double factorial(int *x) { int i; double fac=1; /*Calculamos el factorial*/ for (i=1; i<=(*x); i++) fac=fac*i; return fac; } main () { int numero; double resultado; printf("\n CALCULO DE FACTORIALES \n"); printf("\nIntroduzca un numero entero:\n"); scanf("%i", &numero); resultado = factorial(&numero); printf("\El Factorial de %i es %f", numero, resultado); } exit(0);

Veamos ahora otra utilizacin de funciones, en este caso emplearemos dos ficheros y haremos el mismo programa anterior dividido en dos ficheros: factorial.c
double factorial(int *x) { int i; double fac=1; /*Calculamos el factorial*/ for (i=1; i<=(*x); i++) fac=fac*i; return fac; }

main.c
main () { int numero; double resultado;

printf("\n CALCULO DE FACTORIALES \n"); printf("\nIntroduzca un numero entero:\n"); scanf("%i", &numero); resultado = factorial(&numero); printf("\El Factorial de %i es %f", numero, resultado); } exit(0);

Una vez tenemos los dos ficheros lo que debemos hacer es compilar nuestro programa con los ficheros que le hemos pasado y obtener el resultado en un fichero externo:
$gcc main.c factorial.c -o factorial $./factorial

Hemos podido ver y estudiar como las funciones son muy importantes en nuestro programa y hemos podido ver tambin como afectan las funciones y su divisin en ficheros distintos lo que facilita tanto su reutilizacin como su mantenimiento.

Punteros
Un puntero es un tipo de dato consistente en una variable que almacena la direccin de memoria de otro elemento. Vamos a considerar a continuacin algunas caractersticas de la memoria de un ordenador. La memoria del ordenador se orgnazia en base a unas direcciones que diferencian a cada rango de memoria en el que se almacena un byte. Asi almacenameos un 5 en la direccin de memoria 2345. En C esto se realiza de forma transparente con lo que podremos asignar un valor a una variable sin sabe en que direccin de memoria lo tenemos almacenado.
int valor = 5;

Asi como un puntero es una variable que apunta a otra variable, ambas deben ser del mismo tipo, aunque se pueden emplear los conversores como atoi. Otro punto a tener en cuenta con los punteros es como se definen, para definir el puntero escribimos un nombre de variable vlido precedido de un asterisco "*":
int *valor;

Caben do operadores ms especficos con el puntero: el operador de direccin, representado por un ampersand "&", y el operador de contenido representado por un asterisco "*". Mucho cuidado con no confundir con el operador de definicin. El operador de direccin permite almacenar en un puntero la direccin de un elemento. Ese elemento deber ser el mismo que el definido por el puntero. Asi:
char *punt, dato; /*Definimos las variables*/ punt = &dato; /*Almacenamos la direccin de la variable dato dentro de punt*/ dato = 8; /* Almacenamos 8 en dato */ *punt = 8; /* Almacenamos 8 en dato*/

Esta ltima linea quiere decir "Almacenamos un 8 como contenido de la variable apuntada por punt".

Veamos a continuacin como empleamos los punteros en relacin a las matrices y los vectores: Como hemos dicho los punteros trabajan con direcciones de memoria, pero como se traduce esto en el caso de los vectores y las matrices que tienen varias direcciones de memoria:
int vector[4];/* definimos el vector de 4 columnas */ vector[3] = 7; /* Guardamos en la ltima posicin un 7 */

int *punt; /* definimos el puntero punt */ punt = &vector[0]; /* Asignamos al puntero la posicin 0 del vector */ vector[2] = 18; /*Asignamos a la tercera posicin del vector el valor 18 */ *(punt+2) = 18; /*Asignamos a la tercera posicin del vector apuntado por punt el valor 18 */

Veamos a continuacin como puedo inicializar a 0 un vector empleando solamente punteros:


for (i=0;i<4;i++) *(vector+i) = 0;

Veamos a continuacin como extrapolamos esto para las matrices:

char mat[2][2]; /* Definimosla matriz de caracteres con la que nos interesa trabajar */ char *matriz; /* Definimos un puntero de la matriz */ matriz = &mat[0][0]; /* Asignamos al puntero la posicin 0,0 de la matriz */ *(matriz +2+2) = 0; /*Asignamos 0 a la posicin 2,2 de la matriz */

La tabla que tenemos a continuacin nos sirve de ejemplo para entender como organiza la memoria de un ordenador el contenido de una matriz: ... 1832 1833 1834 1835 ... mat[0][0] mat[0][1] mat[1][0] mat[1][1] Los errores con los punteros y su tratamiento son sin lugar a dudas una de las causas por la que los punteros no gozan de gran aceptacin entre muchos programadores, veamos algunos de ellos:
char vector[4]; char *puntero; vector = puntero+1; /* Error--> Correccin : puntero = puntero+1; vector = puntero; /* Error--> Correccin : puntero = vector;

*/ */

Si hemos entendido bien los punteros podemos pasar a ver como funcionan los punteros con "dynamic memory allocation", esta manera nos permite reservar memoria sin definir una variable empleando las funciones definidas en el fichero de cabecera stdlib.h, asi con malloc(sizeof ( )) podemos reservar el tamao de la variable que queremos almacenar y con free() liberar esta reserva. Podremos ver un ejemplo de su utilizaciin en la seccin relacionada con los ficheros.

A continuacin tenemos un ejemplo prctico sobre la utilizacin de punteros:


#include <stdio.h> main () { int *punt, dato; /*Definimos las variables*/ punt = &dato; /*Almacenamos la direccin de la variable dato dentro de punt*/ *punt = 8; /* Almacenamos 8 en dato*/ printf ("Valor %i", dato); }

Estructuras
Un registro (struct) nos agrupa bajo un mismo nombre datos dedistinto tipo y nombre con el objetivo de facilitar el acceso a los msmos.
struct medida { char hora; char minutos; float temperatura; } registro;

registro.hora = 10; registro.minuto = 56; registro.temperatura = 36.8; if (registro.temperatura > TEMMAX) printf ("Fiebre\n");

Debemos tener en cuenta que los registros se pueden anidar:


struct med_diaria { char dia; char mes; int anyo; struct medida med_uno; struct medida med_dos; struct medida med_tres; } med_hoy; med_hoy.med_uno.hora=8; med_hoy.med_uno.minutos=3; med_hoy.med_uno.temperatura=36.5;

Veamos a continuacin un ejemplo completo:


#include <stdio.h> int main() { struct alumnado { int codigo; float parcial_1; float parcial_2; float media; } alumno;

printf("\n Codigo del alumno :"); scanf("%i", &(alumno.codigo)); printf("\n Nota del parcial 1 del alumno scanf("%f", &(alumno.parcial_1)); printf("\n Nota del parcial 2 del alumno scanf("%f", &(alumno.parcial_2)); printf("\n");

:"); :");

alumno.media = (alumno.parcial_1+alumno.parcial_2)/2; printf("La media del alumno %i es %f \n", alumno.codigo, alumno.media); }

A continuacin tenemos un ejemplo simple:


#include<time.h> #include<stdio.h> main() {

time_t now; time(&now); printf("It's %.24s.\n", ctime(&now)); return 0;

A continuacin tenemos un ejemplo intensivo en struct y punteros:


#include<time.h> #include<stdio.h> time_t comienzo, *ptiempo; int main(void){ struct tm *fecha; ptiempo = &comienzo; comienzo = time(ptiempo); fecha = localtime(&comienzo); switch(fecha->tm_wday) { case 0: printf ("Domingo\n");break; case 1: printf ("Lunes\n");break; case 2: printf ("Martes\n");break; case 3: printf ("Miercoles\n");break; case 4: printf ("Jueves\n");break; case 5: printf ("Viernes\n");break; case 6: printf ("Sabado\n");break; }

Ficheros
Para trabajar con ficheros en C es necesario implementar el fichero de cabecera stdio.h. Con este fichero podremos acceder a la mayora de las funciones relacionadas con los ficheros.

Tenemos que tener en cuenta que tenemos que abrir el fichero haciendo referencia a un puntero y aun tipo definido como FILE. Con esto preparamos una abstraccin que nos permite acceder al fichero de forma independiente de su tamao o formato. Hay que fijarse en algunos detalles, en primer lugar que fichero queremos abrir y para que, es decir para leer (r) o para escribir (w).Los modificadores que nos interesan son aquellos que afectan a la lectura y escritura de un fichero y estos son r,w y a. Por otro lado tenemos que conocer el formato del fichero al que queremos acceder: csv, txt, dbf, etc. y en funcin de este formato preparar una mscara de entrada o salida que nos permita trabajar con los datos. A continuacin vemos algunas de las funciones definidas en el fichero <stdio.h>:
char nombre[10] = "file"; fopen(nombre, "a"); /*Aade a un fichero existente*/ fopen(nombre, "w"); /*Escribe desde 0 en un fichero, si no existe lo crea, si existe borra su contenido y luego escribe*/ fopen(nombre, "r"); /*Lee el contenido de un fichero*/ fread(puntero,longitud,numelem,nombre); /* Donde tenemos que puntero es el puntero al que se va a transmitir, longitud es el tamao de la variable que queremos emplear, numelem es el numero de elemento a transmitir y nombre el fichero de origen*/ fwrite(puntero,longitud,numelem,nombre); /* Donde tenemos que puntero es el puntero al que se va a transmitir, longitud es el tamao de la variable que queremos emplear, numelem es el numero de elemento a transmitir y nombre el fichero de destino*/ feof(nombre); /* Detecta si quedan datos en nombre */ fclose(nombre); /* Cierra el fichero abierto nombre */ /*Recomendadoes para valores nicos o no diferenciables */ fprintf(nombre, valores); /* Donde nombre es el fichero de destino y valores son las variables que queremos almacenar */ fscanf(nombre, valores); /* Donde nombre es el fichero de y valores son las variables que queremos leer */

A continuacin podemos ver un ejemplo muy simple de las funciones anteriores:


#include<stdio.h> main() { FILE *file_esc, *file_lec; /*definimos los punteros a los ficheros*/ int dato; file_esc=fopen("nuevo.dat", "w"); /*Abrimos el fichero de escritura*/ file_lec=fopen("antiguo.dat", "r");/*Abrimos el fichero lectura*/ fscanf(file_lec, "%i", &dato); /* Leemos los datos que hemos recogido del fichero de lectura*/ while (!feof(file_lec)){ /* Mientras quede fichero leemos lo que hay en el fichero de origen y lo imprimimos en el destino*/ fprintf(file_esc, "%i\n",dato); fscanf(file_lec, "%i", &dato); } fclose (fich_esc);/*Cerramos el fichero de escritura*/ fclose (file_lec);/*Cerramos el fichero de lectura*/

A continuacin tenemos dos ejemplos que nos explican como podemos desarrollar todo el proceso de apertura, lectura, escritura, y cierre de un fichero. Como ejercicio se recomienda completar los comentarios que faltan asi como escribir una descripicin del programa:
/* Programa escribe.c */ #include<stdio.h> int main(int argc, char *argv[]) { char c; FILE *file_esc; char *nombre; struct struc{ int hora; int min; int medida; } *dato; dato=malloc(sizeof(struct struc)); nombre = argv[1]; file_esc=fopen(nombre, "a"); printf( "\n Introduca la hora:"); scanf( "%i", &(dato->hora)); printf( "\n Introduca el minuto:"); scanf( "%i", &(dato->min)); printf( "\n Introduca la medida:"); scanf( "%i", &(dato->medida)); fwrite(dato, sizeof(struct struc),1, file_esc); fclose(file_esc); exit(0); } /* Programa lee.c*/ #include<stdio.h> int main(int argc, char *argv[]) { FILE *file_lec; char *nombre; struct struc{ int hora;

int min; int medida; } *dato; dato=malloc(sizeof(struct struc)); nombre = argv[1]; file_lec=fopen(nombre, "r"); if( file_lec ==NULL ) { printf("\n El fichero de lectura no existe \n"); exit(EXIT_FAILURE); } fread(dato, sizeof(struct struc),1, file_lec); while(!feof(file_lec)) { printf("Hora %i, Minuto %i, Medida %i\n", dato->hora, dato->min, dato->medida); fread(dato, sizeof(struct struc),1, file_lec); } fclose(file_lec); exit(0); }

Errores:
A continuacin vamos a tratar algunos de los errores ms habituales de la programacin en C y vamos a intentar dar algunas claves para evitarlos y resolverlos: Los errores se pueden dividir en dos tipos bsicos, de compilacin y de ejecucin. Si bien no son los nicos pues tambin podemos encontrar errores de especificacin o diseo, nos centraremos solo en los primeros. Un error de compilacin siempre nos da la siguiente informacin: 1. Nombre del fichero donde se ha encontrado el error. 2. Linea del fichero donde se ha encontrado el error. 3. Mensaje de descripcin del error. Se deben por lo general a cuestiones sintcticas. La causa directa ms evidente del error es que no se compila el programa. Pero veamos algunas claves que nos pueden ayudar a encontrar los errores: - Nunca modiifcar un programa sin reflexionar sobre el posible error y sin leer completamente el mensaje de error.

- El error en una linea no significa que necesariamente se encuentre el error en dicha linea, sino simplemente que ah se ha reflejado para el compilador, aunque puede estar en cualquiera de las anteriores. - Es importante resolver los errores en el orden que aparecen. Resolviendo un error cada vez y volviendo a compilar, a no ser que los dems errores sean muy evidentes. - Siempre es recomendable tener varias copias del codigo, con el objetivo de no perdernos con los errores. - Es recomendable compilar en una ventana y tener el cdigo editado en otra como medio para poder rastrear el error sin perder tiempo en editar, cambiar, salir, compilar. - Es recomendable tener un editor abierto en el que poder anotar los errores. - Si finalmente no somos capaces de resolverlo debemos recordar que 4 ojos ven ms que dos y que un compaero o programador pueden darnos la clave de nuestro error. A continuacin vamos a analizar los errores en tiempo de ejecucin: Se pueden dividir en dos areas principales, los errores debioes a las condiciones anmalas del programa, como la falta de privilegios, errores de desbordamiento de memoria, errores en los parametros de entrada, etc. Son errores dficles de detectar, slo apareceran en stuaciones puntuales. Por otroa lado tenermos los errores de algoritmo, estos errore si que aparecen de una forma menos errtica y si son ms fciles de detectar y corregir, el autntico problema suele residir en que los programadores por lo general no escriben el algoritmo sino que lo reciben del exterior y slo lo emplean como se les ha pedido, con lo que suele ser difcil cambiarlos o corregirlos. Con esto no hemos resuelto todos los errores de C pero si los que ms dolor de cabeza producen al programador, veamos a continuacin como gestionar los errores que ms molestan e incluso sufren los usuarios, son los propios errores del programa: Quien no se ha enfrentado a errores del tipo:
Error tipo 11.

Tras un error de sistema. Veamos una funcin que deberia facilitar mucho la gestin de errores en los programas pues estandariza la respuesta a los usuarios:
mi_error (char numero[8], char mensaje[256]){ printf("Error %c: %c", numero, mensaje); }

Esta funcin se llamara con:

mi_error ("001", "Mensaje de error lo menos criptico posible. Con referncia al manual o a la documentacion");

Ficheros de Cabecera o Headers


En el siguiente tema vamos a intentar entender alguans de las claves que nos permitiran explicar mejor como podemos escribir programas que vayan ms alla de las 30 lineas, de las tres variables o que se escriban entre varias personas. En primer lugar debemos aprender a crear nuestros propios ficheros de cabecera "headers" y ver como podemos emplearlos. En especial para evitar definir varias veces las mismas variables, para emplearlos para facilitarnos el mantenimiento y reutilizacin del cdigo, o para hacer un diseo ms acorde con las necesidades de nuestros futuros usuarios. En primer lugar tenemos la dificultad de mantener el cdigo que escribimos, fruto de esta dificultad son las los errores irrastreables en tiempo de compilacin y las repeticiones de algoritmos que se dan en muchas ocasiones por no conocer todo el cdigo que nosotros o alguien del equipo ha escrito. En segundo lugar hay que evitar las repeticiones de lineas que el preprocesador pueda escribir por nostros, para ello emplearemos headers propio con las definiciones necesarias:
/* Fichero superficie.h */ #include<stdio.h> #define PI 3.141592 /* Fichero superficie.h */ #include "superficie.h" main () { float radio, superficie; printf("\nIntroduzca el radio del circulo:\n"; scanf("%f", &radio); if (radio == 0) { printf (" Error cero no es un exit(0); } else if (radio <= 0) { printf("Error no se admiten } radio %f es %f", radio, superficie) } } exit(0); else { superficie = PI * radio * radio; printf("\n La superficie del exit(0);

valor\n");

valores negativos\n");

Con este ejemplo podemos hacernos una idea de como pueden ayudarnos los ficheros de cabecera para poder ahorrar tiempo de escritura y que el preprocesador trabaje por nosotros. Pero por supuesto se pueden hacer muchas cosas ms, p.e.:
/* Fichero que actuara de una manera u otra dependiendo del O.S.*/

/* Fichero superficie.h */ #include<stdio.h> #define PI 3.141592 #ifndef OS #define OS LINUX /*Si no esta definida la variables OS la define como LINUX*/ #endif #undef OS /* Borra la definicin de OS*/

Variables y funciones externas


En primer lugar debemos plantearnos como gestionar los mdulos de nuestro programa, una vez nos lo hayamos planteado debemos dividir nuestro programa segn esas pautas, a contiunuacin damos algunas de las pautas que nos pueden ser tiles para dividir en mdulos nuestros programas: Dividir siempre el cdigo en bse a las funciones. Agrupar las funciones que empleen las mismas variables. Si no se pueden agrupar porque son muchas agruparlas por las funcionalidades que tienen. Nunca Seguir un criterio puramente basado en el tamao del fichero Dar nombre representativos a las funciones. A continuacin vamos a ver un ejemplo:
factorial.c double factorial(int *x) { int i; double fac=1; /*Calculamos el factorial*/ for (i=1; i<=(*x); i++) fac=fac*i; return fac; } main.c #include <stdio.h> main () { int numero; double resultado; printf("\n CALCULO DE FACTORIALES \n"); printf("\nIntroduzca un numero entero:\n"); scanf("%i", &numero); resultado = factorial(&numero); resultado); printf("\El Factorial de %i es %f", numero, exit(0);

Para compilar este programa emplearemos la siguiente linea: #gcc factorial.c main.c -o factorial Aunque tambin se puede hacer con la siguiente linea: #gcc -c factorial.c #gcc -c main.c #gcc main.o factorial.o -o factorial

Argumentos a main
A continuacin vamos a ver un ejemplo que nos permite entender como pasar argumentos a un programa. Estamos acostumbrados a ver como un programa recibe argumentos:
#vi hello.c

Y hemos visto como podemos tratar estos argumentos a un programa en ejemplos como este:
#include <stdio.h> int main(int argc, char { int i; if( argc< 3 ) { printf( %s \n", argv[0] ); } else if( argc > { for( i=0;i<argc { printf( argv[i] ); } *argv[])

"Este programa requiere de al menos un parametro: 3 ) ;i++ )

"Los argumentos de este programa son %s \n",

} else if (argc = 3) { for( i=0;i>argc ;i++ ) { printf( "Los argumentos de este programa son 3: %s \n", argv[i] ); } } }

Podemos imaginar una relacin entre lo anteriormente visto y el bucle switch.

Recursividad
Una funcin recursiva es aquella que se llama a s msma. Asi podemos encontrar muchas cosas recursivas en la resolucin de ecuaciones, el calculo de factoriales y otros. La utilizacin de recursividad en C es muy sencilla y se basa en llamar a la funcin dentro de s msma, adems C permite que se pasen parametros junto a la funcin. Hay qye tener algunas cosas en cuenta en las funciones recursivas: Toda funcin recursiva debe tener algn punto de finalizacin. La funcin debe tender a ese punto de finalizacin. Veamos a continuacin un ejemplo:
#include <stdio.h> float factorial(float N) { if (N == 0) return 1; else return N*factorial(N-1); } main () { float N; printf("\n CALCULO DE FACTORIALES \n"); printf("\nIntroduzca un numero entero:\n"); scanf("%f", &N); printf("\El Factorial es %f", factorial(N)); exit(0); }

Si bien la recursividad es muy explicada en estructura de datos, no es una herramienta tan comun como puede parecer. Descripcin de todas las funciones ANSI Existe alguna funcin ANSI que haga tal cosa? Esta pregunta es muy comn a la hora de desarrollar cualquier programa. A continuacin aparece una lista de todas las funciones estndar ANSI, ordenadas alfabticamente dentro de cada cabecera, junto con su formato y una breve descripcin de su utilidad. Cabecera ctype.h Este fichero de cabecera contiene declaraciones de funciones que permiten detectar dierentes subconjuntos de caracteres. isalnum() Devuelve un valor distinto de O si el carcter es una letra o un nmero.

isalpha() iscntrl() isdigit() isgraph() islower() isprint() ispunct() isespace() issuper() isxdigit() tolower() toupper()

Devuelve un valor distinto de cero si el carcter es una letra (mayscula o minscula). Devuelve un valor distinto de cero si el carcter es de control (FF, HT, CR, etc). Devuelve un valor distinto de cero si el carcter es un dgito. Devuelve un valor distinto de cero si el carcter es de espaciamiento (' ', CR, IIT, VT, etc). Devuelve un valor distinto de cero si el carcter es minscula. Devuelve un valor distinto de cero si el carcter es cualquier carcter de impresin excepto ' '. Devuelve un valor igual a cero si el carcter es de puntuacin. Devuelve un valor distinto de cero si el carcter es de excepto espacio, letras o dgitos. Devuelve un valor distinto de cero si el carcter es mayscula. Devuelve un valor distinto de cero si el carcter es un dgito hexadecimal (0..9, a..f, A..F). Devuelve la letra minscula correspondiente a la mayscula que recibe como parmetro. Devuelve la letra mayscula correspondiente a la minscula que recibc como parmetro. Cabecera locale.h

Esta cabecera contiene la declaracin de funciones que acceden a las propiedades locales de la mquina. setlocale() Devuelve un puntero a una cadena esttica que describe un nuevo local. Cabecera math.h Este fichero de cabecera contiene la declaracin de funciones de tipo matemtico. acos() Devuelve el ngulo cuyo coseno es x, en el rango [0,Pi] radianes. asin() Devuelve el ngulo cuyo seno es x, en el rango [-Pi/2, +Pi/2] raldiancs atan() Devuelve el ngulo de tangente x, en el rango [-Pi/2, +Pi/2] radianes. ataur() Devuelve el ngulo de tangente y/x, en el rango [-Pi, +Pi] radianes. ceil() Devuelve el valor entero ms pegueo no menor que el parmetro X. cos() Devuelvc el coseno de X para X en radianes. cosh() Devuelve el coseno hiperblico de X para X en radianes. exp() Devuelve el exponencial de x. fabs() Devuelve el valor absoluto de un float. floor() Devuelve el valor entero ms grande menor que X. fmod() Devuelve el resto de x/y. frexp() Determina una fraccin y un entero en base 2 que representa el valor de X. ldexp() Devuelve X.2^exp. log() Devuelve el logaritmo natural de X. loglO() Devuelve el logaritmo en base 10 de X. modf() Determina un entero I ms una fraccin f que representan el valor de t.

pow() sin() sinh() sqrt () tan() tanh()

Devuelve X elevado a la potencia Y. Devuelve el seno de X para X en radianes. Devuelve el seno hiperblico de X para X en radianes. Devuelve la raz cuadrada de X. Devuelve la tangente de X para X en radianes. Devuelve la tangente hiperblica de X para X en radianes. Cabecera setjmp.h

Este fichero de cabecera contiene la declaracin de funciones de control de flujo del programa. Causa un segundo retorno desde la ejecucin de la macro setjmp que almacena el longjmp() contexto actual. Cabecera signal.h Este fichero de cabecera contiene la declaracin de funciones det intercambio de seales de procesos con el entorno. raise() Envia la seal SIG y devuelve un O si la seal es recibida con xito. Especifica la nueva gestin para la seal SIG y devuelve la gestin previa si tiene signal() xito. Cabecera stdio.h Este fichero de cabecera contiene la declaracin de funcioncs de entrada y salida estndar. clearerr() Limpia los indicadores de error y fi de fichero para un flujo de datos. Cierra el fichero asociado: devuelve O en caso de xito, y EOF en caso contrario fclose() . Devuelve un valor distinto de O si el indicador de final de fichero est a 1 para feof() el flujo de datos. Devuelve un valor distinto de O si el indicador de error est a 1 para el flujo de ferror() datos. Escribe el buffer en el flujo de salida asociado. Devuelve O si tiene xito, EOF fflush() en caso contrario. Lee el siguiente carcter del flujo de datos de entrada. Devuelve EOF por final fgetc() de fichero o error. Almacena el indicador de posicin de fichero para un flujo de datos. Devuelve O fgetpos() si tiene xito. fgets() Lee una cadena hasta leer un retorno de carro, o llegar al final del flujo de datos. Abre el fichero de nombre especificado, lo asocia con un flujo de datos y fopen() devuelve un puntero a la variable controlada por el mecanismo de flujo de datos. Genera texto formateado, bajo el control de caracteres de formato especiales, y fprintf() lo escribe en el flujo de datos seleccionado. Escribe un carcter en el flujo de datos de salida y avanza el indicador de fputc() posicin del fichero. fputs() Escribe una cadena en el flujo de datos de salida. fread() Lee N caracteres del flujo de entrada y los almacena en un vector.

freopen() Cierra un fichero y lo vuclve a abrir. Lee un texto formateado, bajo el control de caracteres de formato, guardndolo fscanf() en una direccin. Activa el indicador de posicin de fichero para el flujo de datos, limpia el fseek() indicador de final de fichero y devuelve O si ha tenido xito. fsetpos() Sita un valor almacenado en el indicador de posicin del fichero. ftell() Devuelve una forma codificada del indicador de posicin del fichero. Escribe N caracteres en el flujo de salida, tomados a partir de determinada fwrite() posicin de memoria. getc() Toma un carcter de STDIN, la entrada estndar. getchar() Mismo efecto que fgetc(flujo). Lee caracteres del flujo de entrada STDIN y los almacena en un vector, hasta gets() leer un retorno de carro. perror() Escribe una lnea de tcxto en STDERR. Genera texto formateado, bajo el control de caracteres de formato, y lo escribe printf() en STDOUT. putc() Escribe un carcter en el flujo de salida seleccionado. putchar() Escribe un carcter en STDOUT. puts() Escribe una cadena de caracteres en STDOUT. remove() Elimina el fichero de nombre especificado del sistema de ficheros. rename() Renombra un fichero especificado y le asigna el nuevo nombre especificado. rewind() Sita el indicador de posicin al inicio del fichero. Lee de STDIN texto formateado, bajo el control de algunos caracteres de scanf() formato. setbuf() Sita un buffer para un flujo de datos. setvbuf() Establece el modo del buffer segn una serie de parmetros. sprintf() Genera texto formateado y lo almacena en localizaciones sucesivas de memoria. sscanf () Registra texto formateado a partir de localizaciones sucesivas de memoria. Gcnera un fichero temporal de nombre indicado, que es eliminado cuando el tmpfile() programa lo cierra. tmpnam() Crea un nombre de fichero nico y devuelve un puntero a l. ungetc() Si el carcter es distinto de EOF, lo almacena en un flujo de datos. vfprintf () Genera texto formateado, escribindolo en el flujo de datos especificado. vprintf () Genera texto fornlateado, escribilldolo en STDOUT. Genera texto formateado, almacenndolo en localizaciones sucesivas de vsprintf () memoria. Cabecera stdlib.h Este fichero de cabecera contiene las declaraciones de funciones miscelneas estndar. Llama a raise(SIGABRT), que produce la seal de abortar. Causa la abort() terminacin anormal del programa, informando a travs de STDERR. abs() Devuelve el valor absoluto de x. atexit() Registra una funcin cuya direccin se pasa como parmetro para ser llamada

por exit () y devuelve O en caso de xito. atof() Convierte los caracteres de una cadena a un valor de tipo double. atoi() Convierte los caracteres de una cadena a un valor de tipo int. atol() Convierte los caracteres de la cadena a un valor de tipo long. Busca en un vector de valores ordenados y devuelve la direccin de un bsearch() elemento del vector que es igual a la clave de bsqueda que se pasa como parmetro: si no aparece, devuelve NULL. Asigna una localizacin de memoria a un vector de N elementos de X bytes calloc() cada uno, inicializndolo a cero y devolviendo un puntero al inicio. Recibe numerador y denominador y devuelve el cociente y el resto en una div() estructura. Llama a todas las funciones registradas por atexit (), cierra todos los ficheros, y exit () devuelve el control al sistema operativo. Retira la asignacin de memoria a la variable cuya direccin se pasa como free() parmetro. Busca una lista de entorno que cada compilador define para una entrada cuyo getenv() nombre se empareja con la cadena pasada como parmetro.Si la encuentra, devuelve un puntero a la definicin de la variable. labs() Devuelve el valor absoluto de un long. ldiv() Igual que div(), pero con datos de tipo long. Asigna una localizacin para una variable de tamao N, devolviendo un malloc () puntero al inicio mblen() Devuelve el nmero de caracteres de una cadena. mbstowcs() Almacena una cadena multibyte. Determina el nmero de caracteres en la cadena multibyte S que constituyen el mbtowc() siguiente carcter multibyte. qsort() Ordena un vector de N elcmentos de X bytes. Calcula un nmero pseudoaleatorio basado en un valor inicial, en el rango rand() [IO,RAND_MAX] Cambia el tamao de una zona de memoria cuyo puntero recibe como realloc() parmetro. Almacerla el valor inicial utilizado por rand() para calcular un nmero srand() pseudoaleatorio. Convierte los caracteres iniciales de una cadena en un valor equivalente de tipo strtod() double. Convierte los caracteres iniciales de una cadena en un valor equivalente de tipo strtol() long. Convierte los caracteres iniciales de una cadena en un valor equivalente de tipo strtoul() unsigned long. Pasa la cadena parmetro al intrprete de comandos para que la ejecute, y devuelve la informacin de estado proporcionada por ste. Debe tenerse en system() cuenta que, aunque la funcin es estndar, el parmetro que recibe es un comando dependiente del sistema operativo. wcstombs() Almacena una cadena multibyte en sucesivos elementos del vector cuya

wctomb()

primera direccin se pasa como parmetro. Determina el nmero de caracteres que se necesitan para representar el carcter multibyte X. Cabecera string.h

Este fichero cle cabecera almacena la declaracin de funciones de manejo de cadenas. Busca el primer elemento de un vector de char que es igual al carcter memchr() acordado Compara elementos sucesivos de dos vectores de char, devolviendo 0 si son memcmp() iguales o la primera posicin distinta en caso contrario. memcpy() Copia una cadena de caracteres en una zona de memoria. memmove() Copia un vector de char a partir de una direccin de memoria determinada. Almacena N caracteres en cada uno de los elementos del vector que se pasa memset() como parmetro. Concatena dos cadenas, copiando una a continuacin de la otra, incluyendo su strcat() carcter nulo de terminacin. Busca el primer elemento de una cadena igual a un carcter pasado como strchr() parmetro, devolviendo su direccin o NULL si no aparece. Compara elementos sucesivos de dos cadenas, hasta que encuentra dos strcmp() elementos distintos. Devuelve el ndice de los elementos distintos o O. Compara dos cadenas, utilizando una regla de comparacin que depende de la strcoll() implementacin de la funcin en la mquina concreta. Copia una cadena en otra, incluyendo el carcter nulo de terminacin de strcpy() cadena. Busca el primer elemento de una cadena que sea igual a cualquier elemento de strcspn() otra cadena, devolviendo su ndice. Devuelve un puntero a la cadena que contiene el mensaje de error strerror() correspondiente al cdigo recibido como parmetro. Devuelve el nmero de caracteres de una cadena, sin incluir su carcter nulo de strlen() terminacin. Concatena dos cadenas, sin incluir el carcter nulo de terminacin X de la strncat() segunda (necesita conocer su tamao). strncmp() Compara los N primeros elementos de dos cadenas. Copia una cadena en otra, sin incluir su carcter de terminacin (necesita strncpy() conocer el tamao de la segunda). Busca el primer elemento de una cadena que sea igual a cualquier elemento de strpbrk() otra, devolviendo Sll dileCCiII. Busca el ltimo elemento de la cadena que sea igual a un carcter recibido strrchr() como parmetro. Busca el primer carcter de una cadena que no es igual a ninguno de otra, strspn() devolviendo su ndice. Busca la primera secuencia de una cadena que se empareje con strstr() otra,devolviendo su direccin strtok() Busca una cadena dentro de otra.

strxfrm()

Almacena una cadena de N caracteres en un vector de char de direccin especificada. Cabecera time.h

Este fichero de cabecera contiene la declaracin de funciones de gestin del tiempo. Almacena en una cadena una representacin en ingls de 26 caracteres de la hora, asctime() incluyendo un retorno de carro y el carcter nulo de terminacin, como "Mon Jan 03 08:55:18 1994\n". Devuelve el nmero de tics de reloj de un lapso de tiempo del procesador, clock() contando desde el inicio de la ejecucin del programa. ctime() Convierte el tiempo almacenado en una estructura a una representacin en texto. difftime() Devuelve la diferencia de tiempo, en segundos, entre dos tiempos de calendario. Altera los valores de una estructura de representacin de tiempo para representar mktime() un tiempo equivalente,pero con todos sus valores dentro del rango de representacin normal. Genera texto formateado indicador de la hora, bajo el control de unil serie de strftime() cdigos de formato. Almacena la hora del calendario actual en una estructura de datos, devolviendo el time() tiempo del calendario actual.

Anda mungkin juga menyukai