Está en la página 1de 97

1.

- INTRODUCCIN
El C es un lenguaje de programacin ampliamente extendido, en gran parte debido a su gran versatilidad. El C es ideal para escribir programas de muy diferentes tipos, tales como Sistemas operativos, ensambladores, interpretes de lenguajes, compiladores de lenguajes, editores de texto, controladores de red, bases de datos, programas de modem, etc. Son varias las caractersticas que hacen del C uno de los lenguajes de propsito general ms utilizados: ### ### Permite una fcil manipulacin de bits, bytes y de direcciones de memoria, as El C es un lenguaje estructurado, es decir, utiliza bloques o conjuntos de como de funciones de E/S. sentencias ordenadas lgicamente (por ejemplo el BASIC o el FORTRAN son lenguajes no estructurados), lo cual contribuye a la legibilidad de los programas haciendo ms fcil su escritura y mantenimiento. ### El C se compila, no se interpreta. Un intrprete es un programa que traduce linea por linea las sentencias de otro programa (p.ej en BASIC) al llamado cdigo mquina. Cada vez que se quiera ejecutar el programa se tiene que ejecutar tambin el intrprete. Un compilador lee el programa entero y lo convierte en cdigo mquina. El proceso de compilacin es ms largo, pero una vez compilado un programa, su ejecucin es mucho ms rpida y adems no es necesario compilarlo cada vez que se ejecuta. Como cualquier otro lenguaje de programacin, C trabaja con variables, constantes, operadores, etc que constituyen las expresiones. Un conjunto de expresiones constituye una funcin. El conjunto de estas funciones es lo que da lugar a un programa completo en C. Todos estos conceptos se analizan con detalle en los siguientes apartados 2 al 7.

2.- VARIABLES, CONSTANTES, OPERADORES Y EXPRESIONES


Las variables y las constantes son manipuladas por los operadores para formar expresiones. Esta es la base de toda la programacin. En este apartado se explican estos conceptos en lo que se refiere al lenguaje C.

2.1.- VARIABLES
Los nombres de las variables en C pueden llevar uno o varios caracteres, debiendo ser el primero una letra y los siguientes pueden ser letras, nmeros o el carcter de subrayado, teniendo en cuenta que no puede coincidir con el nombre de una funcin o el de una palabra clave del C.

TIPOS DE DATOS Hay 7 tipos de variables predefinidos, que se muestran en la Tabla 2.1: Tipo char int short int unsigned int long int float double Nmero de bits 8 16 8 16 32 32 64 Rango o a 255 -32768 a 32767 -128 a 127 0 a 65535 4294967296 a 4294967295 3.4E-38 a 4.3E38 (7 digitos de precisin) 1.7E-308 a 1.7E308 (12 dgitos de precisin)

Algunas versiones de C permiten aplicar los modificadores short, long y unsigned a otros tipos de datos adems del int. DECLARACIN DE VARIABLES Antes de usar una variable hay que declararla. Basicamente hay tres sitios donde se deben declarar las variables: dentro de las funciones (variables locales), en la definicin de los parmetros de la funcin (parmetros formales), o fuera de todas las funciones (variables globales). Ejemplos: /*Programa para ilustrar variables locales*/ Funcion1() { int variable_local; variable_local=1; } Funcion2() { printf("%d",variable_local); /*el valor de variable_local que se imprimir ya no ser 1 porque ha sido declarada en funcin1(), y su valor ha sido destrudo al salir de sta*/ } Parmetros formales: Como veremos ms adelante, si una funcin tiene argumentos, stos deben de haber sido declarados. Su declaracin se hace despues del nombre de la funcin y antes de abrir la llave:

Funcion1(parametro1,parametro2) int parametro1, parametro2; /*declaracin*/ { int suma; suma=parametro1+parametro2 . . . } Los parmetros formales tambin son dinmicos, y su valor se destruye al salir de la funcin. (Tambin pueden declararse directamente dentro del parntesis). Variables globales: Si declaramos una variable fuera de toda funcin podr accederse a ella desde cualquiera. Si en una funcin se declara una variable local con el mismo nombre que una global existente, mientras estemos en esa funcin se har referencia a la variable local. Por ejemplo: int var=0 ; /*variable global inicializada a 0*/ main () { var=7; . . } Funcion1() int var; var=10; /*var tomar el valor 10, no 7 ni 0*/ . . } La expresin mediante la cual asignamos un determinado valor a una variable recibe el nombre de sentencia de asignacin, cuya forma general es: nombre_variable=expresin; (ej,: x=10) Las asignacines en C se hacen de derecha a izquierda, esto es, la variable toma el valor de la expresin. ARREGLOS El arreglo o formacin es otra clase de variable que se utiliza con frecuencia en C. Un arreglo es un identificador que referencia una coleccin de datos del mismo tipo, con el mismo nombre. Los datos pueden ser numricos (int, float...) o caracteres. Este es un ejemplo de arreglo unidimensional de caracteres: supongamos que queremos guardar la cadena de

caracteres "HOLA" en un arreglo. Como la palabra "HOLA" tiene 4 letras necesitamos un arreglo de 5 elementos (uno ms para el caracter \0 -ver constantes de cadena de caracteres, ap 2.2-) tal como se describe en la siguiente tabla: Elemento del arreglo Carcter de la cadena letra[0] letra[1] letra[2] letra[3] letra[4] H O L A \0

El cdigo en C de este programa se describe en el prog1 (ver Apndice).

2.2.- CONSTANTES
C tiene cuatro tipos bsicos de constantes: enteras, en coma flotante, de caracter y de cadena de caracteres. Las dos primeras se llaman constantes de tipo numrico. ### ### ### Constantes enteras: son nmeros con valor entero (p.ej. 0 1 127 32767). Constantes en coma flotante: es un nmero que contiene un punto decimal, un Constantes de carcter: un slo carcter encerrado con comillas simples. 'X' '7' '' ' ') Prcticamente todas las computadoras personales utilizan el

exponente o ambos.(p.ej. 0.2 532.654 2E-8 .4533e7) (p.ej. 'a'

conjunto de caracteres ASCII en el cual cada carcter individual se codifica numricamente con su propia combinacin unica de 7 bits. ### Constantes de cadena de caracteres: Una constante de cadena de caracteres "1-3-1978" "F=m*a" " "). El compilador inserta consta de cualquier nmero de caracteres consecutivos (o ninguno), encerrados entre comillas dobles. (p.ej. "hola" automticamente un carcter nulo (\0) al final de toda constante de cadena de caracteres, como ltimo carcter de sta. ste carcter no aparece cuando se visualiza la cadena, pero es muy til para identificar rpidamente el final de una cadena de caracteres.

2.3.- OPERADORES
Un operador es un smbolo que indica al compilador que se lleven a cabo especficas manipulacines matemticas o lgicas. Hay varios tipos de operadores en C. Destacamos los aritmticos, los relacionales y los lgicos.

OPERADORES ARITMTICOS La lista de operadores aritmticos permitidos en C se muestran en la siguiente tabla: Operador + * / % -++ Accin resta suma multiplicacin divisin resto de divisin entera decremento incremento

Para ilustrar como funcionan en C estos operadores, ver prog2 (ver tambin prog6). Los operadores incremento y decremento se estudirarn con ms detalle en el captulo de estructuras de control. OPERADORES RELACIONALES Y LGICOS La clave de los conceptos de operadores relacionales y lgicos es la idea de cierto y falso. Los operadores relacionales y lgicos se muestran en la siguiente tabla: Operador relacional > >= < <= == != Accin mayor que mayor o igual que menor que menor o igual que igual distinto Operador lgico && || ! Accin AND OR NOT

Todas las expresiones relacionales y lgicas producen como resultado un 0 o un 1. Por ejemplo, el siguiente fragmento de programa imprime el nmero 1 en la pantallla (ver tambin prog3): int x; x=11; printf("%d",x>10);

No debe confundirse el operador relacional == con el operador de asignacin = ya mencionado. Hay otros operadores interesantes como el operador sizeof, que devuelve el tamao en bytes del tipo de dato entre parntesis. num_bytes=sizeof(int); (num_bytes tomara el valor 2) Otros operadores de especial importancia son los operadores de puntero & y *. En C, un puntero es la direccin de memoria de una variable. El operador & devuelve la direccin de memoria del operando. El operador * devuelve el valor de la variable ubicada en la dieccin que le siga. Todo esto se desarrollar ampliamente en el tema de punteros.

2.4.- EXPRESIONES
Como hemos dicho, los operadores, las constantes y las variables son los constituyentes de las expresiones. Una expresin en C es cualquier combinacin vlida de estas piezas. Cuando en una expresin se mezclan constantes y variables de distintos tipos, se convierten a un tipo nico. En general el compilador de C convertir todos los operandos al tipo del mayor operando. Adems podemos aadir espacios, tabulaciones y parntesis para hacer ms legible la expresin sin que por ello se produzcan errores o se disminuya la velocidad de ejecucin de la expresin. Existen abreviaturas para las expresiones del tipo: variable = variable operador expresin Esa expresion es equivalente a esta otra abreviada: variable operador = expresin (p.ej: x+=2) (p.ej: x=x+2)

3.- FUNCIONES DE ENTRADA Y SALIDA (por consola)


Hay dos formas de leer y escribir datos en un ordenador: por consola (mediante operaciones sobre el teclado y la pantalla) y sobre ficheros en disco. En este captulo slo explicaremos las principales funciones por consola. En C toda la E/S es orientada a carcter: no se pueden leer o escribir cadenas y nmeros directamente, slo bytes. Adems, en C no hay funciones incorporadas para realizar operaciones E/S. En realidad estas funciones se encuentran en la librera estndar de C. Se puede acceder a una funcin de entrada/salida desde cualquier sitio de un programa, simplemente escribiendo el nombre de la funcin, seguido de una lista de argumentos (si los tiene) entre parntesis. Las principales funciones de E/S son: getchar, putchar, gets, puts, scanf, printf,

3.1.- Getchar (Entrada de un caracter)


Esta funcin no requiere argumentos, pero, como en todas las funciones, es necesario que un par de parntesis vacos sigan a la palabra: variable de carcter = getchar();

La funcin getchar se puede tambin utilizar para leer cadenas de varios caracteres, leyendo en un bucle la cadena carcter.

3.2.- Putchar (salida de un carcter)


Esta funcin transmite un carcter al monitor, que estar representado por una variable tipo carcter. La referencia a la funcin putchar es de la forma: putchar (variable de carcter) La funcin putchar se puede utilizar para visualizar una constante de cadena de caracteres almacenando la cadena dentro de un arreglo de tipo carcter, y, mediante un bucle, escribir los caracteres uno a uno. Hay otras funciones ms potentes que getchar y putchar, llamadas gets y puts, capaces de leer y escribir de forma similar cadenas enteras de caracteres. (ver prog4)

3.3.- Scanf (introduccin de datos)


Esta funcin se puede utilizar para introducir cualquier combinacin de valores numricos, caracteres sueltos y cadenas de caracteres. Su forma general es: scanf (cadena de control, arg1, arg2,..., argn) donde cadena de control hace referencia a una cadena de caracteres que contiene informacin sobre el formato de los datos (especificadores de formato) y arg1, arg2,...,argn son punteros que indican las direcciones de memoria en donde se encuentran los datos. Los especificadores de formato de uso ms comn son: %c %s %d carcter simple cadena entero con signo %u %f %e entero sin signo coma flotante sin exponente coma flotante con exponente

Tambien se utilizan los prefijos l (entero largo o doble precisin con %f y %e) y h (entero corto) para modificar el tipo de tato. (ejs: %ld, %lf %hu). Todas las variables utilizadas para recibir valores a travs de scanf() se pasan por sus direcciones. Esta es la forma en que el C crea un "paso por referencia". Por ejemplo, si queremos leer un entero dentro de la variable numero, se utilizara esta llamada a scanf(): scanf ("%d",&numero); Las cadenas se leern sobre arreglos de caracteres, y el nombre del array, sin ningn ndice, es la direccin del primer elemento del arreglo. Por tanto, para leer una cadena dentro del arreglo de caracteres cadena, se utilizara: scanf ("%s",cadena);

En este caso, cadena ya es un puntero y no es necesario que vaya precedido por el operador &.

3.4.- Printf
Esta es una funcin de salida genrica por consola que se proporciona con el compilador de C. La forma genrica de printf() es: printf ("cadena de control", lista de argumentos); La cadena de control contiene los comandos de formato que le indican a printf() como debe visualizar el resto de los argumentos sobre la pantalla, as como la cantidad de argumentos existientes. Tenemos ejemplos de estas funciones en cualquier programa de los vistos hasta ahora. En concreto, en el prog5 se utiliza la funcin printf con 4 argumentos.

4.- ESTRUCTURAS DE CONTROL


En este captulo se estudian varias de las sentencias de control de los programas en C. Se incluyen las sentencias condicionales if y switch y las construcciones de bucles while, for y do/while.

4.1.- SENTENCIAS CONDICIONALES


LA SENTENCIA "IF" El formato general de la sentencia If es: if (condicin) { sentencias /*bloque 1*/ } else /*opcional*/ { sentencias /*bloque2*/ } Si la condicin es cierta (cualquier valor distinto de 0), se ejecutar el primer bloque de sentencias; si no, se ejecuta el segundo bloque, si existe. Una construccin comn de programacin es la escalera if-else-if, cuyo esquema es el siguiente: if (condicin) { sentencia; } else if (condicin) { sentencia; .

. else { sentencia; } Las condiciones se evaluan de arriba abajo. Tan pronto como se encuentre una condicin cierta, se ejecuta la sentencia asociada y se salta el resto de la escalera. El ltimo else actua como condicin por defecto, en caso de que ninguna de las anteriores se cumpla. LA SENTENCIA "SWITCH" La estructura switch es parecida a la escalera if-else-if, pero es menos confusa y ms elegante. El formato general de la sentencia switch es el siguiente: switch (variable) { case expresin1: sentencia; case expresin2: sentencia; . . default: sentencia; } La instruccin default es opcional, y se ejecuta cuando no se cumple ninguna de las anteriores. Mediante switch slo podemos probar una igualdad, mientras que con if se puede evaluar una expresin relacional o lgica. Un ejemplo sencillo de cmo funciona el switch se detalla en el prog6. (ver tambin prog14).

4.2.- BUCLES O ESTRUCTURAS REPETITIVAS


Los bucles permiten que se ejecuten un conjunto de instrucciones hasta que se cumple una cierta condicin. Esta condicin puede estar predefinida, como en el bucle for, o no como en los bucles while y do-while. EL BUCLE FOR El formato general de for para repetir una o ms sentencias es: for (inicializacin; condicin; incremento) { sentencia 1; . . sentencia n; }

El bucle for se continuar ejeutando mientras que las pruebas de ejecucin sean ciertas. Cuando la condicin sea falsa, la ejecucin del programa se reanudar en la sentencia siguiente al bloque for.

EL BUCLE WHILE El formato general de la sentencia es: while (condicin) { sentencia; } La sentencia se ejecuta mientras que la condicin sea cierta. EL BUCLE DO-WHILE A diferencia de los bucles for y while, el bucle do-while comprueba su condicin al final del bucle, por lo que siempre se ejecutar al menos una vez. Su formato general es: do { sentencias; } while (condicin);

BREAK Y EXIT() La sentencia break y la funcin de librera exit() permiten forzar una salida desde dentro del bucle, saltndose la condicin normal del bucle. Cuando se encuentre la sentencia break dentro de un bucle, el bucle se finaliza inmediatamente y el control del programa se pasa a la siguiente sentencia despues del bucle. La funcin exit() originar una terminacin inmediata del programa y una vuelta al sistema operativo.

5.- ARREGLOS
El arreglo o array proporciona una forma de referirse a los elementos individuales de un conjunto, utilizando el mismo nombre de una variable para todos los elementos pero empleando distintos ndices.

5.1.- DECLARACIN DE ARREGLOS


Como el resto de variables, los arrays tienen que ser declarados para que el compilador conozca el tipo y el tamao que queremos para el arreglo. Por ejemplo: int elementos[10];

En este caso int especifica el tipo de array, la palabra elementos es un puntero hacia el primer elemento del array y el [10] especifica cuntas variables de tipo int tendr nuestro arreglo.

5.2.- INTRODUCCIN Y LECTURA DE DATOS EN UN ARREGLO


Para introducir datos en un arreglo se suele utilizar el bucle for, que har que la funcin scanf se ejecute reiteradamente para pedir al usuario que introduzca valores para cada elemento del arreglo. Para imprimir los elementos de un arreglo construimos un bucle similar en el cual se repita la funcin printf tantas veces como elementos haya en el arreglo. (Ver ejemplo en el apartado 5.5)

5.3.- LECTURA DE UN NMERO DESCONOCIDO DE ELEMENTOS


Cuando no sabemos de antemano el nmero de elementos que necesitamos introducir en un arreglo podemos utilizar los bucles while o do-while de modo que se interrumpa la entrada de datos en el momento que no se cumpla una determinada condicin. La variable que comprueba si se cumple la condicon para que se ejecute el bucle se denomina centinela. Como ejemplo de centinela vease el prog7.

5.4.- INICIALIZACIN DE ARREGLOS


Al igual que podemos inicializar variables a un valor determinado, podemos inicializar los elementos de un arreglo asignandoles determinados valores iniciales y as evitar tener que introducirlos cada vez. Este tipo de arreglos slo se pueden declarar como variables globales (fuera de toda funcin) o como variables tipo static: (variables permanentes dentro la funcin donde se declaran) Por ejemplo: static int vector[6] = {13, 11, 7, 5, 3, 1}; Hara la siguiente asignacin: Elemento del arreglo vector[0] vector[1] vector[2] vector[3] vector[4] vector[5] Valor asignado 13 11 7 5 3 1

Como ejemplo de esto ver prog8 (descomposicin en factores primos).

5.5.- ARREGLOS BIDIMENSIONALES


Los arreglos pueden tener ms de una dimensin, lo cual es muy util para representar matrices y operar con ellas. El ejemplo siguiente muestra como introducir los elementos de una matriz 3 por 3, y su visualizacin en pantalla. Adems, ver programa prog9 en el que se multiplican dos matrices tres por tres. El C permite arreglos de ms de dos dimensiones. El lmite depender del compilador. Pero los arrays de ms de tres dimensiones no se suelen utilizar ya que el almacenamiento de todos los elementos de un array est asignado en memoria permanentemente durante la ejecucin del programa. Por tanto, cuando son necesarios arrays multidimensionales grandes, se deben asignar dinmicamente los bits y las partes del array que sean necesarios, y utilizar punteros.

/*programa que introduce y visualiza los elementos de una matriz 3 * 3*/ #include <stdio.h> #include <math.h> main () { int A[3][3]; /*declaracin del arreglo de la matriz*/ int i,j; /*declaracin de los contadores*/ for (i=0;i<3;i++) /*bucles para introducir los elementos de la matriz*/ { for (j=0;j<3;j++) { printf("introduce elemento (%d,%d)\n",i,j); /*visualiza el elemento a introducir*/ scanf("%d",& A[i][j]); /*guarda el elemento en el arreglo*/ } } for (i=0;i<3;i++) /*bucle para imprimir los elementos de la matriz*/ { for (j=0;j<3;j++) { printf("%d ",A[i][j]); } printf("\n"); } }

6.- PUNTEROS
Un puntero es una variable que contiene la direccin de memoria de otra variable (se dice que "apunta" a esa variable). Para acceder a los datos de los punteros se utilizan los operadores * ("contenido de...") y & ("direccin de memoria de..."). Para utilizar punteros, stos tienen que habler sido declarados. Por ejemplo, si x es un puntero a float, se indica: float *x; Como ejemplo de como funciona un puntero vase el ejemplo1: #include <stdio.h> void main () { int numero=225;/*declaracion y asignacion de la cantidad 225 a la variable numero*/ int *punt_numero; /*declaracion de la variable punt_numero como puntero*/ punt_numero=&numero;/*asignacion de la direccion de memoria de numero al puntero*/ printf("El contenido de la direccin de memoria %x es %d.\n",punt_numero,*punt_numero); /*la direccin de memoria se expresa como variable hexadecimal*/ } La salida por pantalla de este programa podra ser la siguiente: El contenido de la direccin de memoria FFF2 es 225.

6.1.- EXPRESIONES CON PUNTEROS


Los punteros se pueden utilizar en la mayora de las expresiones vlidas de C, pero presentan algunos casos particulares: - En los operadores ++ y --, el incremento o decremento depender del tipo de dato al que apunte el puntero. Por ejemplo, un puntero a entero de valor puntero=1000, tras aplicarle el operador ++: puntero=puntero++; tomar el valor 1002. - Tambin podemos sumar o restar enteros a los punteros: puntero=puntero + 5; ahora puntero valdra 1012. Aparte de incrementar o sumar y restar enteros a punteros no podemos hacer ms operaciones aritmticas con ellos: no se pueden multipicar o dividir punteros ni sumarlos o restarlos entre si,y no se les pueden aplicar operadores lgicos (a no ser en casos concretos, como comparar los elementos de un arreglo).

6.2.- ARREGLOS Y PUNTEROS


Existe una estrecha relacin entre los arrays y los punteros. De hecho, el ordenador slo sabe utilizar punteros, y el compilador traduce toda la notacin de arreglos a notacin de punteros. Por ejemplo, veamos el mismo programa (ejemplos 2 y 3) que imprime los valores de un array en notacin de arreglos y de punteros: /*programa que imprime los valores de un arreglo*/ #include <stdio.h> void main() { static int array[]={1,2,3,5,7}; int i; for (i=0;i<5;i++) { printf("%d ", array[i]); } } _______________________________ /*programa que utiliza punteros para imprimir valores del arreglo*/ #include <stdio.h> void main() { static int array[]={1,2,3,5,7}; int i; for (i=0;i<5;i++) { printf("%d ", *(array+i)); /*se podra poner tambin array[i]*/ } } La salida de ambos programas es exactamente la misma: 1 2 3 5 7 En el segundo programa vemos la utilizacin del operador suma con punteros: *(array+i). Esto significa, dentro de la expresin, "imprime el contenido del elemento array[0] + i" donde i vara desde 0 hasta 4. Pero no se incrementan las direcciones de memoria una a una, sino de dos en dos, como corresponde a un int. Cabe destacar que para sealar el elemento array[0] slo hemos utilizado la palabra array. Es decir: &array[0] es equivalente a array

6.3.- PASO POR REFERENCIA


Se pueden pasar punteros a funciones como argumentos. Cuando se pasa un argumento por valor, el dato es copiado a la funcin, y cualquier alteracin hecha al dato dentro de la funcin no es devuelta a la rutina llamadora. Pero cuando pasamos por referencia se pasa la direccin del dato, lo cual permite que el dato sea alterado globalmente desde dentro de la funcin. Esto se analizar con detalle en el siguiente captulo.

6.4.- ASIGNACIN DINMICA DE MEMORIA.


La definicin convencional de un arreglo produce la reserva de un bloque fijo de memoria al principio de la ejecucin del programa, pero si el arreglo se representa en trminos de una variable puntero no se produce ninguna asignacin inicial de memoria. Para asignar memoria a este tipo de arreglos se usa la asignacin dinmica de memoria, mediante la funcin de biblioteca malloc. Por ejemplo, imaginemos que necesitamos un arreglo con capacidad para 10 enteros. Podemos reservar la memoria declarando un arreglo llamado x: int x[10]; En este caso ya hemos reservado espacio en memoria para 10 enteros. Sin embargo si declaramos la variable como un puntero: int *x; Podemos asignar el mismo espacio en memoria mediante la funcin malloc: x=(int *) malloc (10 * sizeof (int)); con la ventaja de que, mediante la asignacin dinmica de memoria podemos reservar la memoria que necesitemos durante la ejecucin del programa y luego liberarla, mediante la funcin free. (ver programas de ordenacin). Si adems necesitamos que el arreglo quede inicializado a 0, podemos utilizar la funcin calloc, que funciona de la misma forma, pero asigna automticamente el valor 0 a todos los elementos.

6.5.- PUNTEROS A PUNTEROS


Un puntero a puntero almacena la direccin de memoria donde se encuentra una variable puntero. Para ver cmo funcionan, considerese el ejemplo4: void main() { int x,*p,**q; x=10; p=&x; q=&p; printf("%d",**q);/*imprime el valor de x*/

El puntero p guarda la direccin de memoria de x, cuyo contenido es 10. Por tanto *p es 10. El puntero q guarda la direccin de memoria de p, y por tanto **q sera tambin 10.

6.6.- ARREGLOS DE PUNTEROS


Un arreglo multidimensional puede ser expresado como un arreglo de punteros (punteros a punteros) en vez de como un puntero a un grupo de arreglos contiguos. Esto permite un acceso ms rpido a los datos y facilita las operaciones con matrices. Como ejemplo de todo esto y de la asignacin dinmica de memoria, vease el programa prog10 que suma dos matrices guardadas en arreglos de punteros.

7- FUNCIONES 7.1.- SINTAXIS. PASO POR VALOR Y PASO POR REFERENCIA


Las funciones son bloques con los que se constituyen los programas en C. El formato general de una funcin es el siguiente: nombre_funcin (lista de parmetros) declaraciones de parmetros; { cuerpo de la funcin; } Las funciones devuelven un valor, que puede ser especificado por la sentencia return o, si no se especifica un valor, devuelve 0. Hay que distinguir entre las funciones de librera y las funciones definidas por el usuario. Todos los programas en C tienen al menos una funcin de usuario: el main(). Las funciones pueden ser llamadas desde otras funciones de dos formas distintas: por valor y por referencia. Para ilustrar cmo hace una llamada por valor, vease el ejemplo5: #include <stdio.h> void intercambio(int a,int b); void main() { int x,y; x=777; y=10; printf("Valor inicial: x=%d y=%d\n",x,y); y=intercambio(x,y); printf("Despues del intercambio: x=%d y=%d\n",x,y); } void intercambio(int a,int b) { int aux;

aux=a; a=b; b=aux; printf("Dentro de intercambio: x=%d y=%d\n",a,b); } En realidad esta funcin slo intercambia los valores dentro de la funcin intercambio, ya que a y b son variables locales y no se pasan a la funcin main(). Para conseguir que los valores se cambien tambin en la funcin main recurrimos al paso por referencia: (ejemplo6) #include <stdio.h> void intercambio(int *a,int *b); /*declaracin de la funcin intercambio*/ void main() { int x,y; x=777; y=10; printf("Valor inicial: x=%d y=%d\n",x,y); printf("Direccin de memoria: &x=%p &y=%p\n",&x,&y); intercambio(&x,&y); /*llamada a intercambio,pasandole los punteros de x e y*/ printf("\nDespus del intercambio: x=%d y=%d\n",x,y); printf("Direccin de memoria: &x=%p &y=%p\n",&x,&y); } void intercambio(int *a,int *b) { int aux; aux=*a; *a=*b; *b=aux; printf("\nDentro de intercambio: x=%d y=%d\n",*a,*b); printf("Direccin de memoria: &x=%p &y=%p\n",&a,&b); } Se han incluido las direccines de memoria de las variables x e y para que se pueda ver que realmente se intercambian los contenidos de los punteros, mientras que estos no son afectados. Para ver un ejemplo de paso por valor y por referencia en el mismo programa, ver prog11.

7.2.- LLAMADA DE FUNCIONES CON ARREGLOS


Un elemento de un array utilizado como un argumento se trata igual que cualquier otra variable sencilla. Tambin podemos pasar todo un arreglo a una funcin simplemente pasando la direccin del primer elemento del arreglo. Considrese el ejemplo7: #include <stdio.h> void visualiza (int *numero);/*declaracin de la funcin visualiza*/ void main()

{ static int arreglo[10]={1,2,3,4,5,6,7,8,9,0};/*definimos los elementos del arreglo*/ int i; visualiza(arreglo); } void visualiza(int *numero) /*funcin visualiza*/ { int i; for(i=0;i<10;i++) { printf("%d ",numero[i]);/*imprime los elementos del arreglo*/ } } Finalmente, para darnos cuenta de la importancia de las funciones para la legibilidad y claridad de los programas, y para facilitar su modificacin consideremos el siguiente problema: En el prog8 habamos conseguido descomponer cualquier nmero tipo unisigned int en factores primos. Pero esto no era del todo cierto, ya que slo habamos definido 7 factores primos (hasta el 17), y nmeros como el 961 eran considerados como irreducibles, ya que el programa considera irreducible cualquier nmero que no sea divisible por un primo hasta 17. La forma de mejorar el programa es aparentemente sencilla: calcular primero todos los nmeros primos hasta el dado y luego dividirlo por cada uno de ellos. Entonces veramos que 961 es divisible por 31, y por tanto no es primo. En el prog12 tenemos un posible algoritmo para el clculo de nmeros primos hasta uno dado (a nosotros no se nos ocurri otro mejor). Pero el problema surge a la hora de integrar este programa dentro del anterior: necesitamos guardar los nmeros primos en un arreglo. Pero no sabemos a priori cuantos nmeros primos va a haber hasta el final del programa, as que necesitamos una asignacin dinmica de memoria. An as, no podremos guardar los nmeros en el arreglo a la vez, a no ser que hagamos una asignacin de memoria individual para cada elemento (lo cual intentamos pero no fue posible, ya que en cada asignacin se borran todos los datos guardados). As que necesitamos que el programa haga dos veces la misma operacin: una para saber cuanta memoria necesitamos y otra para guardar los valores. Adems, y puestos a aadir, podemos hacer que el usuario elija entre visualizar simplemente los nmeros primos o descomponer tambin en factores el nmero que introduce. Si hacemos todo esto de forma desordenada, improvisando centinelas y contadores sobre la marcha, abusando del goto, sin emplear funciones como el switch, que facilitaran la legibilidad, etc, tenemos el prog13. El prog13 funciona, pero dos horas despus de terminarlo no tienes ni idea de por qu. Pues bien, ahora que conocemos la programacin modular y el paso de arreglos a funciones, vamos a intentar que el prog13 sea mucho ms fcil de leer y sirva de compendio de casi todo lo estudiado hasta ahora. As conseguimos el prog14.

Analizando detenidamente el prog14 vemos que, en principio es ms largo. Adems, las funciones de calcular primos, guardar y descomponer se parecen mucho, pero hay una mejora importante: la funcin main es mucho ms corta y fcil de seguir, y en general todo el programa es mucho mas legible (con excepcin de la dificultad aadida de las variables locales). Adems, hemos aadido sin dificultad una tercera opcin al programa simplemente borrando una linea del case 1 y pasando opcion como parmetro. En el prog13 sera mucho ms dificil aadir cualquier cosa sin perderse. Por tanto, vemos que trabajar con funciones es indispensable para programar en C. Para ver adems un programa que trabaja con matrices y funciones, ver prog15.

8.- ORDENAR UN ARREGLO 8.1.- QU ES ORDENAR?:


Ordenar es un acto intuitivo que consiste en organizar un numero determinado de elementos de una forma tal que ,cuando vayan a ser recuperados para su utilizacin, sean fcilmente localizables. De una forma ms matemtica, ordenar consiste en: Dados n elementos {a1,a2,...,an} permutarlos formando un nuevo conjunto {ak1,ak2,...,akn} de tal forma que dada una funcin f de ordenacin se verifique:{ f(ak1)### f(ak2) ###... ### f(akn)}.

8.2-POR QU EXISTEN TANTOS ALGORITMOS DE ORDENACIN?:


La razn simplemente es que, al igual que en las matemticas, casi ningn problema tiene un slo mtodo de resolucin. No obstante siempre existe uno mejor que otro (ms corto y fcil de operar) en funcin de los datos de que se dispone y el resultado al que se quiere llegar. Esto que ocurre en matemticas ocurre por igual en la programacin, ya que unos algoritmos poseen determinadas ventajas frente a otros en funcin de lo que se quiera hacer. La ordenacin de arrglos se realiza desde la memoria interna rpida del ordenador. De esta forma se puede disponer de todos los elementos a ordenar cuando queramos. Como ejemplo intuitivo supongamos que disponemos de una pequea mesa y queremos ordenar un palo de la baraja de menor a mayor. Como no tenemos un elevado nmero de elementos podemos ponerlos todos a nuestra vista sobre la mesa y comenzar a ordenarlos.

Ordenacin por seleccin directa: (Vase Seleccio.C) Es el mtodo que normalmente usamos para ordenar una lista de forma directa.

Consiste en coger el primer elemento y compararlo con el resto de los elementos. Cuando encuentra un elemento menor se coge ese elemento y se sigue comparando. Una vez comparados todos se coloca el elemento ms pequeo en el lugar en el que estaba el elemento inicial a comparar, y este (el inicial) se coloca donde estaba el menor. Como ejemplo obsrvese la siguiente tabla: Lista desordenada 1 iteracin 2 iteracin 3 iteracin 4 iteracin 5 iteracin Lista ordenada 3 3 1 1 1 1 1 4 4 4 2 2 2 2 6 6 6 6 3 3 3 5 5 5 5 5 4 4 2 2 2 4 4 5 5 1 1 3 3 6 6 6

El elemento en negrita es el que se coge y se compara. El proceso seguido en la tabla es el siguiente: 1. Se coge el primer elemento (3) y se compara: Con el 4: Al ser mayor no intercambia el valor y pasa al siguiente. Con el 6: Al ser mayor no intercambia el valor y pasa al siguiente. Con el 5: Al ser mayor no intercambia el valor y pasa al siguiente. Con el 2: Al ser menor que (3) se coge el valor de 2 y se compara con los

restantes. Con el 1: Al ser menor que (2) se coge el valor 1 y se compara con el resto. Como es el menor se le coloca en la 1 posicin. 2. El resto de las iteraciones siguen el mismo proceso pero cada vez se va cogiendo un elemento ms avanzado ya que el anterior ya ha quedado ordenado. CDIGO DE LA FUNCIN DEL MTODO SELECCIN DIRECTA EN C void Seleccion(int *,int); /*Declaracin de la funcion*/

void Seleccion(int *lista,int num_elem) { int i,j,aux,pos_min=0;

int minimo; for (i=0;i<num_elem;i++) { minimo=lista[i]; pos_min=i; for(j=i;j<num_elem;j++) { if(minimo>lista[j]) { minimo=lista[j]; pos_min=j; } } aux=lista[i]; lista[i]=minimo; lista[pos_min]=aux; } } Ordenacin por insercin directa: (Vase Insercio.C) Este mtodo es el usado por los jugadores de cartas y consiste en coger el 2 elemento Lista desordenada 1 iteracin 2 iteracin 3 iteracin 3 3 3 3 3 3 4 iteracin 3 3 2 2 2 2 5 iteracin 2 2 1 Lista ordenada 1 4 4 4 4 4 4 4 2 3 3 3 3 3 1 2 2 6 6 6 6 5 5 2 4 4 4 4 4 1 3 3 3 5 5 5 5 6 2 5 5 5 5 5 1 4 4 4 4 2 2 2 2 2 6 6 6 6 6 1 5 5 5 5 5 1 1 1 1 1 1 1 1 1 1 6 6 6 6 6 6 del arreglo y compararlo con el anterior y si este es mayor intercambiarlos y seguir comparando realizando el mismo proceso hasta el final de la lista. Ilustremos el mismo ejemplo de antes.
Coge el 4 y compara con el 3 y como no es mayor no hace nada Coge el 6 y compara con el 4 y como no es mayor no hace nada Coge el 5 y compara con el 6 y como no es mayor no hace nada Coge el 2 y compara con el 6 y como es mayor se intercambian Coge el 2 y compara con el 5 y como es mayor se intercambian Coge el 2 y compara con el 4 y como es mayor se intercambian

/*Coge el elemento a comparar; cada vez una posicin ms avanzado*/

/*Recorre el arreglo desde la posicin del elemento inicial hasta el final*/

/*Si encuentra uno menor que el valor que cogi en un principio coge ese valor y su posicin para seguir comparando*/

*/Intercambia la posicin del valor que comparaba en un principio con la del menor encontrado*/

Coge el 2 y compara con el 3 y como es mayor se intercambian Coge el 2 y no compara ms porque se ha acabado el arreglo. Coge el 1 y compara con el 6 y como es mayor se intercambian. Coge el 1 y compara con el 5 y como es mayor se intercambian. Coge el 1 y compara con el 4 y como es mayor se intercambian. Coge el 1 y compara con el 3 y como es mayor se intercambian. Coge el 1 y compara con el 2 y como es mayor se intercambian. Coge el 1 y no compara ms porque se ha acabado el arreglo.

El rendimiento de este mtodo puede mejorarse considerablemente mediante la utilizacin del mtodo de bsqueda binaria. Si uno se da cuenta de que la secuencia a 1,.....,ai-1 est siempre ordenada, se puede agilizar el mtodo buscando el lugar adecuado de insercin. El mtodo de bsqueda binaria parte del elemento central de a1,.....,ai-1 y mediante biseccin encuentra el lugar de insercin. (Vase Insbinar.C)

CDIGO DE LA FUNCIN DEL MTODO INSERCIN EN C void Insercion(int *,int); /*Declaracin de la funcin*/

void Insercion(int *lista,int num_elem) { int i,j,actual; for (i=1;i<num_elem;i++) { actual=lista[i]; /*Coge el elemento a comparar desde el 2 hasta el final cada vez una posicin ms avanzado*/ for(j=i;actual<lista[j-1] && j>0;j---) /* Va comparando actual con los anteriores e intercambindose hasta que encuentra uno { lista[j]=lista[j-1]; } lista[j]=actual; } } que no es mayor que l o hasta que llega al final del arreglo*/

CDIGO DE LA FUNCIN DEL MTODO DE INSERCIN BINARIA EN C void InsercionBinaria(int *,int); /*Declaracin de la funcin*/

void InsercionBinaria(int *lista,int num_elem) { int i,j,izq,der,cent,aux; for (i=0;i<num_elem;i++) { aux=lista[i]; izq=0; der=i-1; while(izq<der) { cent=(izq+der)/2; if(aux<lista[cent]) { der=cent-1; } else { izq=cent+1; } } for(j=i-1;j>=izq;j--) { lista[j+1]=lista[j]; } lista[izq]=aux; } } Ordenacin por intercambio directo: (Vase Burbuja.C) Este mtodo,tambin llamado de la burbuja) se basa en la comparacin e intercambio dos a dos. Veamos un ejemplo ilustrativo: Lista desordenada 3 4 6 5 2 1 /*Va intercambiando el elemento hasta ese lugar*/ /*Busca el lugar donde insertar el elemento. Coge el elemento central. Si el elemento a comparar es menor disminuye el lugar por la derecha, sino aumenta por la izquierda . As hasta que encuentra dos elementos entre los que coloca el elemento a insertar*/

j=0 i=0 i=1 i=2 i=3 i=4 3 3 3 3 3 4 4 4 4 4 4 6 6 6 5 5 5 5 5 5 6 2 2 2 2 2 2 6 1 1 1 1 1 1 6 i=0 3 i=1 3 i=2 3 i=3 3 FIN 3 4 4 4 4 4

j=1 5 5 5 2 2 2 2 2 5 1 1 1 1 1 5 6 6 6 6 6 i=0 i=1 i=2 3 3 3 4 4 2 2

j=2 2 2 4 1 1 1 1 4 5 5 5 5 6 6 6 6

FIN 3

FIN 3

j=3 i=0 i=1 3 2 2 3 1 1 1 3 4 4 4 5 5 5 6 6 6

FIN 2

j=4 i=0 LISTA ORDENADA 2 1 3 4 5 6 1 2 3 4 5 6

El funcionamiento bsico es coger el primer elemento y compararlo con el siguiente. Si este es menor se intercambian. En la siguiente iteracin coge el segundo y lo compara con el siguiente. As hasta el final del arreglo. Para que el mtodo sea ms rpido, hay que tener en cuenta que en cada iteracin queda ordenado un elemento y no es necesario volver a compararlo en la siguiente iteracin.

CDIGO DE LA FUNCIN DEL MTODO DE LA BURBUJA DE EN C void Burbuja(int *,int); void Burbuja(int *lista,int num_elem) { int i,j,aux; for (j=0;j<num_elem-1;j++) { for(i=0;i<num_elem-j-1;i++) { if(lista[i]>lista[i+1]) { aux=lista[i]; lista[i]=lista[i+1]; lista[i+1]=aux; } } } } Ordenacin por insercin con incrementos decrecientes:(Vase Shell.C) Este mtodo se basa en la comparacin y ordenacin de elementos distantes x y tambin se denomina mtodo de Shell en honor a su inventor. Esta distancia se llama salto. La comparacin se va realizando con el mismo salto hasta que ya no se produzca ningn cambio; en ese momento se cambia el salto y realiza el mismo proceso. Como ejemplo veamos la siguiente ordenacin: /*Intercambia elementos*/

Lista desordenada

Cogeremos el salto =nmero de elementos/2. El salto en primer lugar es por tanto 3. Para coger los siguientes saltos iremos dividiendo por dos los anteriores, es decir salto1=salto/2.(Conviene recordar que se trata de una divisin entera y por tanto 3/2=1)

Salto=3

3 3 3

4 4 2 2

6 6 6 1

5 5 5 5

2 2 4 4

1 1 1 6

Fin

vuelta.

Como

hay

intercambios da otra vuelta ms. 3 3 Fin 2 vuelta. Como no hay 3 2 2 2 1 1 1 5 5 5 4 4 4 6 6 6

intercambios, se cambia el valor del salto. Salto=1 (igual que el mtodo de burbuja) 2 2 2 2 2 Fin 1 vuelta. Como hay 2 3 1 1 1 1 1 1 3 3 3 3 3 5 5 5 4 4 4 4 4 4 5 5 5 6 6 6 6 6 6 3 2 1 5 4 6

intercambios da otra vuelta ms. 1 2 3 4 5 6

Ahora continuara comparando el resto de elementos dos a dos y an hara otra pasada en la que ya no habra cambios.

CDIGO DE LA FUNCIN DEL MTODO DE SHELL EN C void Shell(int *,int); /*Declaracin de la funcin*/

void Shell(int *lista,int num_elem) { int salto=num_elem,aux,hay_cambio,i; do { salto/=2; do { hay_cambio=0; for(i=0;(i+salto)<num_elem;i++) { if(lista[i]>lista[i+salto]) { aux=lista[i]; lista[i]=lista[i+salto]; lista[i+salto]=aux; hay_cambio=1; } } }while (hay_cambio); }while (salto>1); } El programa comienza ordenando los elementos separados por una distancia que viene dada por el salto. Una vez ordenados dichos elementos, la variable hay_cambio toma el valor 0, con lo que el programa sale del bucle de ordenacin y divide el salto por 2, ordenando de nuevo los elementos separados por el nuevo salto, y as sucesivamente /*Intercambio*/

hasta que el salto=1 y termina de ordenar por el mtodo de la burbuja (de una sola pasada) los elementos que falten. Ordenacin por particin: (Vase Quicksor.C) Este mtodo, tambin denominado Quicksort por su rapidez, consiste en tomar un elemento (pivote) del arreglo y dividir la lista en dos: una parte con los elementos mayores que el pivote y otra parte con los menores y una vez obtenidas estas dos partes ordenarlos por el mtodo de la burbuja. Para obtener las dos listas se sigue el siguiente procedimiento: Una vez tomado el pivote (usaremos como pivote el primer elemento de la lista), se recorre el arreglo de izquierda a derecha hasta encontrar un elemento mayor que el pivote y entonces se busca de derecha a izquierda hasta encontrar uno menor. A continuacin se intercambian los dos elementos y se continua este proceso hasta hallar un elemento en el que confluyan los dos recorridos. Este elemento se supone que estar colocado aproximadamente en la mitad del arreglo. Como ejemplo ilustrativo vase la siguiente tabla:

Lista desordenada

Pivote=3

4 izquierda (3>4) 1

1 derecha (1<3)

6 izquierda (3>6)

2 derecha (2<3)

5 izq=der

La lista queda dividida en dos partes aproximadamente iguales (en este caso iguales):

Lista A Lista B

1 5

2 6

3 4

Ahora estas dos listas se ordenan por separado mediante cualquier otro mtodo. En nuestro ejemplo utilizaremos el de Shell por ser el ms potente de los anteriormente descritos.

CDIGO DE LA FUNCIN DEL MTODO QUICKSORT EN C void Quicksort(int *lista,int num_elem) { int *listaA,*listaB,pivote=lista[0]; int tam_listaA=0,tam_listaB=0,i; listaA=(int*)malloc(num_elem*sizeof(int)); listaB=(int*)malloc(num_elem*sizeof(int)); if (listaA==NULL) { printf (Error en asignacin de memoria de la listaA); } if (listaB==NULL) { printf (Error en asignacin de memoria de la listaB); } for(i=0;i<num_elem;i++) { if(lista[i]<=pivote) { listaA[tam_listaA]=lista[i]; tam_listaA++; } else { listaB[tam_listaB]=lista[i]; tam_listaB++; } } Shell (listaA,tam_listaA); Shell (listaB,tam_listaB); for (i=0;i<tam_listaA;i++) { lista[i]=listaA[i]; } for (i=0;i<tam_listaB;i++) /* Ordena cada lista por separado mediante el mtodo de Shell (puede hacerse con otro cualquiera)*/ /* Manda los elementos (ya ordenados) de la listaA a la las primeras posiciones de la lista inicial*/ /* Manda los elementos (ya ordenados) de la listaB a la las posiciones no ocupadas por listaA de la lista inicial*/ /* Manda los elementos mayores que el pivote a la listaB*/ /* Manda los elementos menores o iguales que el pivote a la listaA*/ /*Reserva de dinmica de memoria. En el peor de los casos no habr divisin y la lista ms grande tendr el tamao de la original*/

{ lista[i+tam_listaA]=listaB[i]; } free(listaA); free(listaB); } El mtodo quicksort se hace tanto ms eficiente cuanto ms parecidos son los tamaos de las sublistas. Estos tamaos dependen del pivote que se elija. As cuando el pivote sea el elemento que queda en el centro de la lista el mtodo alcanzar su mayor grado de eficiencia. Definamos ese valor ideal del pivote como centro=num_elem/2. A este elemento ideal se le denomina mediana y se define como el elemento del arreglo que es menor (o igual) que la mitad de los elementos y es mayor (o igual) que la otra mitad. Por ejemplo la mediana del arreglo 2,1,3,5,4 es el 3. Dependiendo de cmo sea el pivote respecto a la mediana se tienen los siguientes tres casos: 1) Si el pivote es demasiado pequeo: Cuando esto ocurre el valor centro deseado es mayor que el pivote con el que se ha partido la lista. Para resolverlo debera repetirse el proceso de divisin para los elementos a la derecha del pivote. Esto puede expresarse mediante el siguiente diagrama: /* Libera la memoria reservada para listaA y listaB*/

###
izquierda j i centro

###
derecha

2)

Si el pivote es demasiado grande: En este caso centro es menor que el pivote escogido. Por tanto la particin queda

desequilibrada y para equilibrarla hay que volver a partir los elementos situados a la izquierda del pivote. El diagrama que representa esta situacin es:

###
izquierda centro j i

###
derecha

3) Si el pivote es el adecuado: Que el pivote sea el adecuado significa que parte el arreglo en dos listas iguales de tamao. Si esto sucede es porque el pivote es exactamente la mediana. El esquema es el siguiente:

###
izquierda j i centro

###
derecha

CDIGO DE LA FUNCIN PARA LA OBTENCIN DE LA MEDIANA EN C (Vase Mediana.C) /*Declaracin de la funcin*/

int Mediana(int *,int);

int Mediana(int *lista,int num_elem) { int izquierda,derecha,i,j,aux,centro; izquierda=0; derecha=num_elem; centro=(num_elem/2); while (izquierda<derecha) { i=izquierda; j=derecha; do { while (lista[i]<lista[centro]) /*Traslada el ndice extremo izquierdo hacia la { i++; } while (lista[centro]<lista[j]) /*Traslada el ndice extremo derecho hacia la { j--; } izquierda*/ derecha*/

if (i<=j) { aux=lista[i]; lista[i]=lista[j]; lista[j]=aux; i++; j--; } }while (i<=j); if (j<centro) { izquierda=i; } if (centro<i) { derecha=j; } } return (lista[centro]); }

/*Intercambio*/

/*Establece los nuevos lmites del arreglo */

Aplicando este mtodo para obtener el pivote se obtiene el Quicksort mejorado. (Vase Qsortmej.C)

COMPARACIN ORDENACIN

DE

LOS

DISTINTOS

MTODOS

DE

La eficiencia de un mtodo de ordenacin de arreglos puede medirse en funcin del nmero C de comparaciones y M de intercambios de elementos. En primer lugar compararemos entre si a los tres mtodos directos (seleccin, insercin, intercambio) que, si bien no son los mejores, poseen algunas ventajas sobre los ms sofisticados: 1.Sus programas son cortos y fciles de entender. Por tanto no ocupan mucha memoria. 2. Son suficientemente rpidos para un nmero de elementos suficientemente pequeo. Sin embargo son enormemente lentos para arreglos de un tamao grande. La siguiente tabla muestra los valores mnimos, mximos y medios de comparaciones ( C ) e intercambios (M) en funcin del nmero de elementos ( n) de los distintos mtodos dirtectos:

MNIMO Seleccin directa Insercin directa Intercambio directo C= (n -n)/2 M= 3(n-1) C= n-1 M= 2(n-1) C= (n -n)/2 M= 0
2 2 2

MEDIO C= (n -n)/2 M= n(ln n+ 0.57) C= (n +n-2)/4 M= (n -9n-10)/4 C= (n -n)/2 M= (n -n)x0.75


2 2 2 2 2 2

MXIMO C= (n -n)/2 M= n /4+3(n-1) C= (n -n)/2-1 M= (n +3n-4)/2 C= (n -n)/2 M= (n -n)x1.5


2 2 2 2

Todos estos mtodos elementales realizan un nmero de movimientos del orden de n , ya que esencialmente mueven cada elemento una posicin en cada paso. As pues cualquiera de los otros mtodos avanzados tienen como principal caracterstica el hecho de que mueve los elementos una distancia mayor de cada vez. No obstante los mtodos avanzados poseen tal grado de sofisticacin que no es posible encontrar una frmulas matemticas suficientemente comprensibles. Las relaciones ms relevantes para expresar el esfuerzo de computacin de estos mtodos son cin
1.2 2

para el

mtodo de Shell (cuando el salto se toma como ...31,15,7,3,1) y cilog (n) para el quicksort y del

montculo. A los mtodos avanzados se les denomina tambin logartmicos en ocasiones, por ser su esfuerzo de computacin del orden de n log (n). Para una mejor comprensin de cules son los mejores mtodos vense la siguiente tabla1 experimentale realizada en un ordenador 486/DX4. Los tiempos que en ella aparecen han sido medidos en segundos.

MTODO ORDENADO
N elementos de

ESTADO DEL ARREGLO ALEATORIO


10000
10,989011 25,879121 9,175824 6,593407

INVERSO
10000
13,461538 38,956044 19,065934 13,461538

10000
10,934066 15,989011 0 0,109890

5000
2,582418 3,846154 0 0,054945

5000
2,637363 6,318681 2,252747 1,593407

5000
3,186813 9,560440 4,615385 3,241758

Seleccin Burbuja Insercin Insercin Binaria Shell Quicksort Quicksort mejorado

0,054945 0,054945 0,054945

0 0 0

0,439560 0,329670 0,274725

0,164835 0,169890 0,109890

0,164835 0,109890 0,054945

0,054945 0,054945 0

Se pude observar claramente que el peor mtodo de ordenacin es el de la burbuja en cualquiera de los casos expuestos. Tambin se ve como la mejora del mtodo de insercin binaria sobre el de insercin es bastante significativa cuando el nmero de elementos es elevado aunque contraproducente en el improbable caso de querer ordenar un arreglo ya ordenado. Comparando los mtodos directos entre s llegamos a la conclusin de que el mejor, en caso de que el arreglo est en orden inverso, es el de seleccin, mientras que para el resto

Nota: Los datos expuestos en la tabla pueden comprobarse experimentalmente en el proyecto Speed.prj que se adjunta en el disquete.

de los casos lo esel de insercin (observaciones que podan ser predichas en la anterior tabla).

Comparando el mtodo Quicksort y el Quicksort mejorado llegamos a la conclusin de que la mejora no es muy significativa. El Quicksort es, de todos los mtodos (en especial de los avanzados), el mejor aunque no se separa mucho del de Shell.

9.- BUSCAR UN ELEMENTO


En ocasiones es necesario encontrar un determinado elemento dentro de un arreglo. Existen para este fin dos mtodos principales: Bsqueda secuencial. Bsqueda binaria. Estas dos funciones se encuentran en el archivo Buscar.C.

9.1.- BSQUEDA SECUENCIAL:


Este mtodo es muy intuitivo y consiste simplemente en introducir el elemento a buscar y hacer que el programa recorra el arreglo elemento por elemento hasta encontrar el buscado y, una vez encontrado que nos devuelva su posicin dentro del arreglo. La funcin para este mtodo es la siguiente: int BusqSecuencial(int *,int,int); /*Declaracin de la funcin*/

void BusqSecuencial (int *lista, int tam, int buscado, int *posicion) { int i,j=0; for(i=0;i<tam;i++) { if (lista[i]==buscado) { posicion[j]=i; j++; } if (j==0) { printf (Ese elemento no est en el arreglo.\n); exit (0); } }

if (lista[0]==buscado) { posicion[0]=-1; } } Esta funcin introduce en un arreglo las posiciones en las que aparece el elemento. Para aplicar esta funcin hay que tener en cuenta que si el elemento buscado se encuentra en la posicin 0 de la lista, el valor dentro del arreglo posicin ser -1. Adems debe tenerse en cuenta que todas aquellas posiciones del arreglo posicion en las que no se halla incluido ningn valor tendrn por defecto el valor 0 (para ello es recomendable el uso de calloc par la reserva de memoria).

9.2.- BSQUEDA BINARIA:


Este mtodo, en el cual se apoya la insercin binaria, procede cogiendo un elemento situado en el medio del arreglo. Si el elemento buscado es menor que el situado en el centro, situa el extremo derecho en el elemento anterior al central; por contra si es mayor, situa el extremo izquierdo en la posicin siguiente a la del elemento central. Como se puede deducir de este algoritmo, para poder aplicar la bsqueda binaria es totalmente imprescindible que el arreglo este ordenado. El cdigo de la funcin es el siguiente: void BusqBinaria(int *,int,int ,int *) /*Declaracin de la funcin*/

void BusqBinaria(int *arreglo,int tam,int buscado,int *posicion) { int bajo,central,alto; int i,j,z=0; bajo=0; alto=tam; central=0; while (bajo<=alto&&arreglo[central]!=buscado) { central=(alto+bajo)/2; if (buscado<arreglo[central]) { alto=central-1; } /*Va partiendo el arreglo para

encontrar el elemento buscado*/

else { bajo=central+1; } } j=central; while (arreglo[j]==buscado&&j>=0) { if (j==0&&j>=0) { posicion[z]=-1; j-} else { posicion[z]=j; z++; j--; } } if (arreglo[central]!=buscado) { printf (Ese elemento no est en la lista o el arreglo no est ordenado.\n); } j=central+1; z++; while (arreglo[j]==buscado&&j<=tam) { posicion[z]=j; z++; j++; } } /*Busca a la derecha de central por si el elemento estuviese repetido*/ /*Busca a la izquierda de central por si el elemento estuviese repetido*/

Al igual que en la funcin para la bsqueda secuencial, esta funcin introduce las posiciones en las que se encuentra el elemento en un arreglo (posicion). El arreglo en el que se introducen las posiciones tiene las mismas peculiaridades que antes;es decir: Si el elemento se encuentra en la posicin 0 del arreglo, el arreglo posicion contendr el valor -1. Todos las posiciones del arreglo posicion en las que no se haya introducido un valor tendrn el valor 0 por defecto.(Se debe usar la funcin calloc para reservar la memoria del puntero y as inicializar todas las posiciones a 0.). Estas dos peculiaridades son las que hay que tener en cuenta a la hora de usar esta funcin (adems de que el arreglo debe estar ordenado) para usarla. Como ejemplo vease el proyecto Binaria.prj incluido en el disquete.

Qu mtodo es mejor?:
A la vista de los resultados obtenidos al comparar los mtodos de ordenacin, es lgico pensar que el mtodo de bsqueda binaria ser mucho ms rpido que el de bsqueda secuencial. Como ya dijimos, un mtodo que compara elemento por elemento es mucho ms lento que aquel que lo hace entre elementos ms distantes porque el nmero de comparaciones se hace muy elevado.

NMERO DE COMPARACIONES Bsqueda secuencial Bsqueda binaria (N+1)/2 (1+log2N)/2

Como ejemplos de programas de ordenacin y bsqueda vanse los programas Prog16.C y Prog17.C adems del proyecto Poblacio.prj.

10.- CONSERVAR LOS DATOS


En muchas ocasiones los datos que usamos para ejecutar un determinado programa son siempre los mismos. En esos casos no es muy prctico tener que introducir siempre los mismos datos una y otra vez. Otras veces nos puede interesar conservar los datos obtenidos despus de ejecutar el programa para futuras aplicaciones. Con lo que hemos estudiado hasta ahora no podemos hacer esto, ya que cada vez que el programa terminaba de ejecutarse se borraban los datos que estaban en la memoria. La mejor solucin sera poder guardar esos datos en dispositivos perifricos (disquetes, CDROMs, disco duro...)en forma de archivos. Bien esto va a ser lo que estudiemos ahora: ARCHIVOS. En primer lugar hay que destacar que los programas que utilizan archivos son ms lentos que aquellos que cogen los datos directamente de la memoria. Existen dos tipos principales de archivos: los de texto y los binarios. Existen algunas diferencias entre estos dos tipos de archivos pero ambos se abren igual.

10.1.- APERTURA , CREACIN Y CIERRE DE ARCHIVOS:


Para abrir o crear un archivo lo primero que hay que hacer es declarar un puntero (aunque no es exactamente un puntero) de archivos que apunte al lugar donde se encuentra el archivo en el dispositivo perifrico: FILE *puntero; (El prototipo de FILE viene definido en stdio.h> Para abrir el archivo se utiliza la funcin fopen definida en stdio.h de la siguiente forma: puntero=fopen(nombre_archivo, tipo_archivo); El nombre_archivo puede ser una variable introducida por el usuario. Los diferentes tipos de archivo que se pueden abrir vienen definidos en la siguiente tabla: Tipo de archivo r w a Significado Abre un archivo ya existente en modo de lectura Crea un archivo en modo escritura. Si el archivo que se abre ya existe, el contenido anterior de ste ser borrado por completo. Abre un archivo para aadir datos al final. Si el archivo a abrir no existe se crear uno nuevo.

r+ w+ a+

Abre un archivo ya existente tanto para lectura como para escritura Crea un archivo nuevo para lectura y escritura. En caso de abrir un archivo ya existente se borrar la informacin Abre un archivo existente para leer y aadir. Si el nombre especificado no corresponde a un archivo existente se abrir uno nuevo.

Para cerrar un archivo se utiliza la funcin fclose definida en stdio.h. Su uso es de la siguiente forma: fclose(puntero); Es importante resear que antes de terminar el programa hay que cerrar todos los archivos abiertos. La principal diferencia entre los archivos de texto y los binarios radica en la forma de escribir y leer los datos en ellos contenidos:

10.2.- ARCHIVOS DE TEXTO:


Estos archivos contienen caracteres consecutivos. Estos caracteres pueden ser tanto letras(forman cadenas de caracteres) como nmeros (pero nmeros vistos como caracteres). Las funciones que se utilizan par escritura y lectura son fprintf y fscanf respectivamente. Los parmetros de estas funciones son los siguientes: fprintf (puntero,%tipo de dato,donde esta almacenado); Ej: fprintf (original, %d, lista[2]); fscanf (puntero,%tipo de dato,&donde lo mandamos); Ej: fscanf (original,%d, &lista[2]); Cuando usamos cualquiera de estas funciones, despues de escribir/leer el dato el puntero avanza automticamente al siguiente elemento. Para avanzar a posiciones determinadas dentro del fichero existen varias funciones aunque la ms destacable es fseek definida en stdio.h. La sintaxis de la funcin es la siguiente: fseek (puntero, nueva posicin, desde donde empezar); Nueva posicin es la posicion contada a partir de desde_donde_empezar en bytes..(Es un valor de tipo long). Desde donde empezar puede tener tres valores: SEEK_SET:Busca desde el comienzo del archivo. SEEK_CUR:Busca desde loa posicin actual. SEEK_END:Busca desde el final del archivo.

Existe otra funcin (ftell) que nos devuelve la posicin en la que nos encontramos dentro del archivo en ese momento. Su sintaxis es: ftell (puntero); (devuelve un valor de tipo long). En muchas ocasiones queremos leer el fichero hasta el final, pero no sabemos donde esta ste. Para ello existe una funcin eof(puntero); definida en io.h que nos devuleve los siguientes valores: 1 Cuando est al final del archivo. 0 Si no est al final de la funcin. -1 Si hay algn error. Como ejemplos de archivos de texto vasen los programas Prog18.C, Prog19.C, Prog20.C y Prog21.C.

10.3.- ARCHIVOS BINARIOS:


Estos constan de bloques de bytes contiguos. Son por tanto archivos escritos en cdigo binatio como su nombre indica. En este tipo de archivos las funciones que de lectura y escritura que se usan son fwrite y fread. La sintaxis de estas funciones es: fwrite (&var,tamao_var,nmero_bloques,puntero); Var: Puntero al bloque de datos. Tamao var: Tamao del bloque de datos (sizeof()). Nmero bloques:Nmero de bloques a trasferir. Puntero: Puntero al archivo donde se archivaran los datos. Otra de las diferencias de estos archivos es la forma de encontrar el final del archivo, para lo que se usa la funcin feof(puntero) (Esta funcin puede utilizarse tanto para archivos binarios como de texto). La funcin devuelve los siguientes valores: 0 si no nos encontramos al final del archivo. Cualquier otro valor si nos encontramos al final del archivo. Las funciones de bsqueda (ftell,fseek) anteriormente mencionadas, sirven igualmente para este tipo de archivos. Sirvan como ejemplos de archivos binarios los programas Prog22.C, Prog23.C, Prog24.C y Prog25.C hechos con estructuras.

11.- ESTRUCTURAS
Una estructura es un tipo de variable como puede ser (int,floata,char...) que es definida por el usuario y cuya caracterstica ms importante es que est compuesta por miembros (elementos int, float, otras estructuras, arreglos..). La declaracin de las estructuras se hace fuera del main de la siguiente forma: struct biblioteca { char libro [ ]; char editorial [ ]; ... ... }; Una vez definida la estructura podemos declarar dentro del main variables que pertenezcan a ese tipo de dato: main() { struct biblioteca nuevo; /*Dos variables de tipo natacion con todos los miembros que ella contiene*/ ... } Una vez definida la estructura y declaradas las variables es sencillo llamar a cualquier miembro sin ms que escribir nuevo.libro a la hora de mandar un dato a ese miembro. Como ya se dijo anteriormente es posible declarar una estructura dentro de otra (siempre y cuando haya sido definida antes). struct prestado { char nombre [20]; int dia; int mes; int ao; }; struct biblioteca { char libro [50]; char editorial [20]; struct prestado dejado; }; A la hora de utilizar el nombre de alguien a quien se le ha prestado el libro, se escribira: nuevo.dejado.nombre.

Como ejemplos vanse los programas Prog22.C, Prog23.C, Prog24.C y Prog25.C ya citados anteriormente.

APNDICE

ndice de programas
Prog1: Introduce una cadena decaracteres en un arreglo. Prog2: Divide dos enteros y muestra el resto de su divisin entera. Prog3: Comprueba si una expresin es cierta o falsa.(1 0) Prog4: Lee y escribe cadenas de caracteres con los comandos gets y puts. Prog5: Suma tres nmeros y los visualiza (printf con tres parmetros). Prog6: Coge dos nmeros y pregunta que operacin desea hacer con ellos (sumar,restar,multiplicar, dividir y resto entero). Prog7: Introduce caracteres en un arreglo hasta que el usuario introduce un valor determinado (0) . Prog8: Descompone un nmero en factores primos. Prog9: Multiplica matrices de 3 * 3. Prog10: Suma de matrices (con punteros). Prog11: Intercambia el valor de dos variables. Prog12: Calcula nmeros primos. Prog13: Calcula nmeros primos y descompone en factores. Prog14: Calcula nmeros primos y descompone en factores (mediante funciones). Prog15: Suma, multiplica o traspone matrices. (Mediante funciones) Prog16: Obtine la clasificacin de una prueba de natacin. Prog17: Ordena una lista de palabras de la A-Z o de la Z-A. Prog18: Ordena una lista de palabras cogidas del archivo PALABRAS.TXT. Prog19: Guarda los aos de nacimiento de los individuos de una poblacin en el archivo FECHAS.TXT. Prog20: Programa que dice que tipo de pas es y describe la pirmide de poblacin a partir del archivo creado por Prog19. Prog21: Programa que guarda estructuras en archivos de texto. Prog22: Programa que recoge y guarda en un archivo binario (BILBIOTE.BIN)los datos de unos libros. Prog23: Programa que visualiza los datos del archivo BIBLIOTE.BIN. Prog24: Programa que aade datos al archivo BIBLIOTE.BIN. Prog25: Programa que cambia los datos de algn registro del archivo BIBLIOTE.BIN.

ndice de proyectos

Binaria.prj: Proyecto que contiene los programas: 1. 2. Binaria.c Buscar.c Para ejecutar el proyecto es necesario que el archivo Buscar.h se encuentre en tc\include. Este proyecto busca las posiciones en las que se encuentra un elemento dentro de un arreglo ordenado. Poblacio.prj: Proyecto que contiene los programas: 1. Poblacio.c 2. Buscar.c 3. Shell.c Para ejecutar este proyecto es necesario que el archivo Buscar.h y el Ordena.h de encuentren en tc\include. Este proyecto busca los individuos nacidos en un determinado ao dentro de un arreglo y calcula el porcentaje que representa del total. Speed.prj: Proyecto que contiene los programas: 1. Burbuja.c 2. Insbinar.c 3. Insercio.c 4. Mediana.c 5. Qsortmej.c 6. Quicksor.c 7. Seleccio.c 8. Shell.c 9. Velocida.c Para ejecutar este proyecto es necesario que el archivo Ordena.h se encuentre en tc\include. Este proyecto calcula el tiempo que tardan los distintos mtodos de ordenacin en ordenar un nmero de elementos.

ndice de archivos usados por los programas

Palabras.txt: Lista de alabras usada por el prog18.c

Fechas.txt: Archivo creado por el Prog19.c y usado opr el Prog29.c

Bibliote.bin: Archivo creado por Prog22.c y usado por Prog23.c, Prog24.c y Prog25.c

Ejemplo1.c
#include <stdio.h> void main () { int numero=225;/*declaracion y asignacion de la cantidad 225 a la variable numero*/ int *punt_numero; /*declaracion de la variable punt_numero como puntero*/ punt_numero=&numero;/*asignacion de la direccion de memoria de numero al puntero*/ printf("El contenido de la direccin de memoria %x es %d\n",punt_numero,*punt_numero); /*la direccin de memoria se expresa como variable hexadecimal*/ }

Ejemplo2.c
#include <stdio.h> void main() { static int array[]={1,2,3,5,7}; int i; for (i=0;i<5;i++) { printf("%d\n", array[i]); } }

Ejemplo3.c
#include <stdio.h> void main() { static int array[]={1,2,3,5,7}; int i; for (i=0;i<5;i++) { printf("%d ", *(array+i)); } }

Ejemplo4.c
void main() { int x,*p,**q; x=10; p=&x; q=&p; printf("%d",**q);/*imprime el valor de x*/

Ejemplo5.c
#include <stdio.h> intercambio(int a,int b); void main() { int x,y; x=777; y=10; printf("Valor inicial: x=%d y=%d\n",x,y); y=intercambio(x,y); printf("Despues del intercambio: x=%d y=%d\n",x,y); } intercambio(int a,int b) { int aux; aux=a; a=b; b=aux; printf("Dentro de intercambio: x=%d y=%d\n",a,b); }

Ejemplo6.c
#include <stdio.h> void intercambio(int *a,int *b); /*declaracin de la funcin intercambio*/ void main() { int x,y; x=777; y=10; printf("Valor inicial: x=%d y=%d\n",x,y); printf("Direccin de memoria: &x=%p &y=%p\n",&x,&y); intercambio(&x,&y); /*llamada a intercambio,pasandole los punteros de x e y*/ printf("\nDespus del intercambio: x=%d y=%d\n",x,y); printf("Direccin de memoria: &x=%p &y=%p\n",&x,&y); } void intercambio(int *a,int *b) { int aux; aux=*a; *a=*b; *b=aux; printf("\nDentro de intercambio: x=%d y=%d\n",*a,*b); printf("Direccin de memoria: &x=%p &y=%p\n",&a,&b); }

Ejemplo7.c
#include <stdio.h> void visualiza (int *numero);/*declaracin de la funcin visualiza*/ void main() { static int arreglo[10]={1,2,3,4,5,6,7,8,9,0};/*definimos los elementos del arreglo*/ int i; visualiza(arreglo); } void visualiza(int *numero) /*funcin visualiza*/ { int i; for(i=0;i<10;i++) { printf("%d ",numero[i]);/*imprime los elementos del arreglo*/ } }

Prog1.c
/*programa que introduce una cadena de caracteres en un arreglo*/ #include <stdio.h> void main() { char cadena[21];/*se reserva uno ms para guardar el carcter /0*/ int num_letras,i; printf("Este programa guarda una cadena de caracteres en un arreglo\n"); printf("e imprime la cadena completa\n"); printf("Por favor, introduce el nmero de letras de la cadena(MAX.20)\n"); scanf("%d",&num_letras); printf("Introduce la cadena letra por letra(separadas por INTRO):\n"); for (i=0;i<num_letras;i++) { scanf("%s",&cadena[i]); } printf ("La cadena introducida es:\n"); for (i=0;i<num_letras;i++) { printf("%c ",cadena[i]); /*i varia desde 0 hasta num_letras*/ } printf ("\n"); }

Prog2.c
/*Programa que divide dos enteros y devuelve el resto de su divisin entera*/ void main() { int dividendo,divisor,resto; /*declaracin de variables*/ printf("Este programa pide dos nmeros enteros\n"); printf("y devuelve el resto de su divisin entera\n"); printf("Introduce el dividendo\n"); scanf("%d",&dividendo); /*entrada de datos*/ printf("Introduce el divisor\n"); scanf("%d",&divisor); /*entrada de datos*/ resto=dividendo%divisor; /*operacin interna*/ printf("El resto es: %d",resto); /*salida de datos*/ }

Prog3.c
/*programa que imprime un "0" o un "1" segn la respuesta introducida por el usuario sea cierta o no*/ void main() { int x; printf(" Este programa escribe un 1 si aciertas la siguiente pregunta, y si no,\n"); printf("escribe un 0. La pregunta es:\n"); printf(" Qu da de agosto es la fiesta de San Eusebio?\n"); scanf("%d",&x); printf("La respuesta es: %d\n",x==17);/*pero no lo mires!*/ /*si el usuario introduce el nmero 17, la relacin ser correcta, lo que equivale a que x==17 tome el valor 1. si se introduce cualquier otro nmero no se cumplir la relacin, por que x==17 tomar el valor 0 */ }

Prog4.c
/*programa que introduce una cadena de caracteres en un arreglo*/ #include <stdio.h> void main() { char cadena[20]; printf("Este programa guarda una cadena de caracteres en un arreglo\n"); printf("e imprime la cadena completa\n"); printf("Introduce la cadena(MAX.20):\n"); gets(cadena); printf ("La cadena introducida es:\n"); puts(cadena); printf ("\n"); }

Prog5.c
/*programa que coge 3 nmeros, los suma y muestra la operacion en pantalla*/ #include <stdio.h> void main() { int num1,num2,num3,resultado; printf("Introduce el primer numero\n"); scanf("%d",&num1); printf("Introduce el segundo numero\n"); scanf("%d",&num2); printf("Introduce el tercer nmero\n"); scanf("%d",&num3); resultado=num1+num2+num3; printf("%d + %d + %d = %d \n",num1,num2,num3,resultado); }/*en este caso printf tiene 4 argumentos*/

Prog6.c
/*programa que coge 2 nmeros y pide al usuario el tipo de operacin que desea hacer con ellos*/ #include <stdio.h> void main() { int num1,num2; float resultado; int opcion; printf("Este programa pide 2 nmeros y permite hacer 5 operaciones con ellos\n"); printf("Introduce el primer numero\n"); scanf("%d",&num1); printf("Introduce el segundo numero\n"); scanf("%d",&num2); printf("\n"); printf("+--------------------+\n"); printf(" 1.-Sumar \n"); printf(" 2.-Restar \n"); printf(" 3.-Multiplicar \n"); printf(" 4.-Dividir \n"); printf(" 5.-Resto entero \n"); printf("+--------------------+\n"); printf("Elige una opcin: "); scanf("%d",&opcion); switch(opcion) { case 1: resultado=num1+num2; printf("%d + %d = %.0f \n",num1,num2,resultado); break;/*la instruccin %.0f sirve para que no saque cifras decimales ya que resultado est declarado como float*/ case 2: resultado=num1-num2; printf("%d - %d = %.0f \n",num1,num2,resultado); break;

case 3: resultado=num1*num2; printf("%d * %d = %.0f \n",num1,num2,resultado); break; case 4: resultado=(float)num1/num2;/*division float*/ printf("%d / %d = %.2f \n",num1,num2,resultado); break;/*la expresin *%.2f permite visualizar el resultado con 2 decimales*/ case 5: resultado=num1%num2; printf("El resto de %d / %d es %.0f \n",num1,num2,resultado); break; default: printf("La opcin introducida no es vlida.\n"); break; } }

Prog7.c
/*programa que introduce una cadena de caracteres en un arreglo*/ #include <stdio.h> void main() { char cadena[21];/*se reserva uno ms para guardar el carcter /0*/ int i,num_letras=0; printf("Este programa guarda una cadena de caracteres en un arreglo\n"); printf("e imprime la cadena completa\n"); printf("Introduce la cadena letra por letra(separadas por INTRO):\n"); printf ("Para finalizar introduce '0'.\n"); do { scanf("%s",&cadena[num_letras]); num_letras++; }while(cadena[num_letras-1]!='0');/*el -1 es para que lea el registro anterior*/ printf ("La cadena introducida es:\n"); for (i=0;i<num_letras-1;i++) /*num_letras -1 es para que no lea el 0*/ { printf("%c ",cadena[i]); /*i varia desde 0 hasta num_letras*/ } printf ("\n"); }

Prog8.c
/*programa que descompone un nmero en factores primos*/ #include <stdio.h> void main() { static int vector[7]={2,3,5,7,11,13,17}; static int contador[7]={0,0,0,0,0,0,0}; unsigned int i,aux,numero,resto; printf("Este programa descompone en factores primos el nmero que usted introduzca.\n"); printf("\tPor favor, introduzca un nmero entero positivo: "); scanf("%u",&numero); printf("\n"); aux=numero; printf("\tEl proceso de descomposicin es el siguiente:\n\n"); for (i=0;i<7;i++) { while (numero%vector[i]==0) { resto=numero/vector[i]; printf("\t\t%u | %u\n",numero,vector[i]); numero=resto; contador[i]+=1; } } if (numero>17) { printf("\t\t%u | %u\n",numero,numero);/*para incluir el caso de que numero sea primo*/ } printf("\n"); printf("El nmero %u descompuesto en factores primos es el producto de:\n\n",aux); for (i=0;i<7;i++) { if (contador[i]!=0)/*para que no escriba si el exponente es 0*/ { printf(" %u elevado a %u\n",vector[i],contador[i]); } } if (numero>17) { printf("\t\t%u elevado a 1\n",numero);/*para incluir numero=primo*/ }

Prog9.c
#include <stdio.h> #include <math.h> main () { int A[3][3]; int B[3][3];/*factores*/ int i,j,k; int C[3][3];/*resultado*/ printf ("Este programa multiplica matrices tres por tres.\n");

for (i=0;i<3;i++) { for (j=0;j<3;j++) { printf("introduce elemento (%d,%d)\n",i,j); scanf("%d",& A[i][j]); } } for (i=0;i<3;i++) { for (j=0;j<3;j++) { printf("%d ",A[i][j]); } printf("\n"); } for (i=0;i<3;i++) { for (j=0;j<3;j++) { printf("introduce elemento de la 2 matriz (%d,%d)\n",i,j); scanf("%d",& B[i][j]); } printf ("\n"); } printf ("\n"); for (i=0;i<3;i++) { for (j=0;j<3;j++) { printf("%d ",B[i][j]); } printf("\n"); } for(i=0;i<3;i++) { for (j=0;j<3;j++) { C[i][j]=0; for (k=0;k<3;k++) { C[i][j]=C[i][j]+(A[i][k]*B[k][j]); } } } printf("el producto de las dos es \n"); for (i=0;i<3;i++) { for (j=0;j<3;j++) { printf("%d ",C[i][j]); } printf("\n"); } }

Porg10.c
/*programa que suma matrices del mismo tamao m*n*/ #include <stdio.h> void main() { int **A, **B, **C; /*punteros a matrices operandos y resultado*/ int num_fil, num_col; int i,j; printf ("introducir numero de filas de las matrices\n"); scanf ("%d", &num_fil); printf ("introducir numero de columnas de las matrices\n"); scanf ("%d", &num_col); /*Asignacin dinmica de memoria*/ A=(int**) malloc(num_fil*sizeof(int*)); if (A==NULL) { printf ("Error en la reserva de memoria.\n"); exit (1); } /*salir del programa si hay errores en la asignacin*/ for (i=0;i<num_fil;i++) { A[i]=(int*) malloc(num_col*sizeof(int)); if (A[i]==NULL) { printf ("Error en la reserva de memoria.\n"); exit (1); } } B=(int**) malloc(num_fil*sizeof(int*)); if (B==NULL) { printf ("Error en la reserva de memoria.\n"); exit (1); } for (i=0;i<num_fil;i++) { B[i]=(int*) malloc(num_col*sizeof(int)); if (B[i]==NULL) { printf ("Error en la reserva de memoria.\n"); exit (1); } }

for (i=0;i<num_fil;i++) /*pide los elementos de la matriz A*/ { for (j=0;j<num_col;j++) { printf("introduce elemento (%d,%d)\n",i,j); scanf("%d",& A[i][j]); }

} printf("\n"); for (i=0;i<num_fil;i++) /*imprime los elementos de la matriz A*/ { for (j=0;j<num_col;j++) { printf("%d ",A[i][j]); } printf("\n"); } for (i=0;i<num_fil;i++) /*pide elementos de matriz B*/ { for (j=0;j<num_col;j++) { printf("introduce elemento de la 2 matriz (%d,%d)\n",i,j); scanf("%d",& B[i][j]); } } printf ("\n"); for (i=0;i<num_fil;i++) /*imprime matriz B*/ { for (j=0;j<num_col;j++) { printf("%d ",B[i][j]); } printf("\n"); } printf("\n\n"); for (i=0;i<num_fil;i++) /*suma las matrices*/ { for (j=0;j<num_col;j++) { C[i][j]=A[i][j] + B[i][j]; } } printf("El resultado es:\n"); for (i=0;i<num_fil;i++) /*imprime el resultado*/ { for (j=0;j<num_col;j++) { printf("%d ",C[i][j]); } printf("\n"); } }

Prog11.c
#include <stdio.h> introduce(int numero); void intercambio(int *a,int *b); /*declaracin de la funcin intercambio*/ void main() { int x,y; x=introduce(x); y=introduce(y); printf("Valor inicial: x=%d y=%d\n",x,y); printf("Direccin de memoria: &x=%p &y=%p\n",&x,&y); intercambio(&x,&y); /*llamada a intercambio,pasandole los punteros de x e y*/ printf("\nDespus del intercambio: x=%d y=%d\n",x,y); printf("Direccin de memoria: &x=%p &y=%p\n",&x,&y); } introduce(int numero) { printf("Introduce un nmero entero: "); scanf("%d",&numero); return(numero); } void intercambio(int *a,int *b) { int aux; aux=*a; *a=*b; *b=aux; printf("\nDentro de intercambio: a=%d b=%d\n",*a,*b); printf("Direccin de memoria (variables locales): &a=%p &b=%p\n",&a,&b); }

Prog12.c
/*Programa que calcula nmeros primos*/ #include <stdio.h> void main() { unsigned int i=2,j,numero,aux,contador=0; printf("Este programa calcula todos los nmeros primos hasta el que usted introduzca.\n"); printf("introduzca un nmero:\n"); scanf("%u",&numero); for(i=2;i<=numero;i++) { for(j=i/2;j>1;j--) /*comprueba si el nmero es divisible por otro menor o igual que la mitad*/ { /*para no hacer divisiones innecesarias*/ if(i%j!=0) { aux=i; } else { aux=0; break; /*si el programa llega a este punto es porque i es divisible por algn nmero*/

} }

/*entonces se rompe el bucle y se pasa a la siguiente iteracin*/

if(aux!=0) /*si no se ha pasado por aux=0, es porque el nmero es primo, y lo imprimimos*/ { printf("%u ",i); contador=contador+1; } } printf("\nHasta el nmero %u hay %u numeros primos.\n",numero,contador); }

Prog13.c
/*Programa que calcula nmeros primos y factoriza*/ #include <stdio.h> void main() { int opcion,centinela_goto=0; int *primos; int *contador2; int num_primos; unsigned int i=2,j,resto,numero,aux=1,contador=0;/*necesitamos que al principio aux sea distinto de cero, para que se cumpla que 2 y 3 son primos*/ printf("Este programa calcula todos los nmeros primos hasta el que usted introduzca.\n"); printf("introduzca un nmero:\n"); scanf("%u",&numero); printf("Adems, si lo desea, lo descompone en factores primos.\n"); printf("Para ello, primero se almacenan los nmeros primos en un arreglo.\n"); printf("Desea guardar en un arreglo los nmeros primos hasta el %u\n",numero); printf("y hallar su descomposicin factorial?\n"); printf(" 1.-Descomponer %u en factores primos.\n",numero); printf(" 2.-Solamente visualizar los nmeros primos hasta el %u.\n",numero); printf("\nTeclee '1' o '2': "); scanf("%d",&opcion); principio: for(i=2;i<=numero;i++) { for(j=i/2;j>1;j--) /*comprueba si el nmero es divisible por otro menor o igual que la mitad*/ { /*para no hacer divisiones innecesarias*/ if(i%j!=0) { aux=i; } else { aux=0; break; /*si el programa llega a este punto es porque i es divisible por algn nmero*/ } /*entonces se rompe el bucle y se pasa a la siguiente iteracin*/ } if(aux!=0) /*si no se ha pasado por aux=0, es porque el nmero es primo, y lo imprimimos*/ { if (opcion!=1) {

printf("%u ",i); } if (centinela_goto==1) { primos[contador]=i; printf("%u ",primos[contador]); } contador=contador+1; } } if (centinela_goto==1) { printf("\nLos nmeros han sido guardados en un arreglo."); goto factores; } printf("\nHasta el nmero %u hay %u numeros primos.\n",numero,contador); if (opcion==2) { exit(2); } if (opcion==1 && centinela_goto!=1) { primos=(int*)malloc(contador*sizeof(int)); if (primos==NULL) { printf("Error en la asignacin de memoria\n"); exit(2); } contador=0; centinela_goto=1; aux=1; goto principio; } factores: num_primos=contador;/*vamos a llamar al nmero de primos num_primos*/ contador2=(int*)malloc((num_primos)*sizeof(int)); if (contador2==NULL) { printf("Error en la asignacin de memoria\n"); exit(3); } for (i=0;i<num_primos;i++) { contador2[i]=0; } printf("\n\tA continuacin vamos a descomponer en factores primos el numero que \nusted ha introducido antes.\n"); printf("\n"); aux=numero; printf("\tEl proceso de descomposicin es el siguiente:\n\n"); for (i=0;i<num_primos;i++) { while (numero%primos[i]==0)

{ resto=numero/primos[i]; printf("\t\t%u | %u\n",numero,primos[i]); numero=resto; contador2[i]+=1; } } if (numero>num_primos) { printf("\t\t%u | %u\n",numero,numero);/*para incluir el caso de que numero sea primo*/ } printf("\n"); printf("El nmero %u descompuesto en factores primos es el producto de:\n\n",aux); for (i=0;i<num_primos;i++) { if (contador2[i]!=0)/*para que no escriba si el exponente es 0*/ { printf(" %u elevado a %u\n",primos[i],contador2[i]); } } if (numero>num_primos) { printf("\t\t%u elevado a 1\n",numero);/*para incluir numero=primo*/ } free(primos); free(contador2); }

Prog14.c
#include <stdio.h> #include <alloc.h> Calcula_cant_primos(unsigned int,int);/*declaracion de las funciones*/ *Guarda(unsigned int,unsigned int); void Descompone(unsigned int,unsigned int,unsigned int *pr); /*------------------------------------------------------------------------*/ void main() { unsigned int *primos; unsigned int cant_primos,num,i; int opcion; printf("Este programa calcula todos los nmeros primos hasta el que usted introduzca.\n"); printf("introduzca un nmero:\n"); scanf("%u",&num); printf("Adem s, si lo desea, lo descompone en factores primos.\n"); printf("Para ello, primero se almacenan los nmeros primos en un arreglo.\n"); printf("Desea guardar en un arreglo los nmeros primos hasta el %u\n",num); printf("y hallar su descomposicin factorial?\n"); printf(" 1.-Descomponer %u en factores primos.\n",num); printf(" 2.-Solamente visualizar los nmeros primos hasta el %u.\n",num); printf(" 3.-Visualizar los nmeros primos y descomponer %u.\n",num); printf("\nTeclee '1', '2' o '3': "); scanf("%d",&opcion); switch(opcion) {

case 1: cant_primos=Calcula_cant_primos(num,opcion); printf("%u primos\n",cant_primos); primos=Guarda(num,cant_primos); Descompone(num,cant_primos,primos); exit(1);

case 2: cant_primos=Calcula_cant_primos(num,opcion); printf("\nHasta el numero %u hay %u primos.\n",num,cant_primos); exit(2); case 3: cant_primos=Calcula_cant_primos(num,opcion); printf("%u primos\n",cant_primos); primos=Guarda(num,cant_primos); for(i=0;i<cant_primos;i++) { printf("%u ",primos[i]); } Descompone(num,cant_primos,primos); exit(3); default: printf("Opcin incorrecta.\n"); exit(4); }/*switch*/ }/*main*/ /*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/ Calcula_cant_primos(unsigned int numero,int opcion) { unsigned int i=2,j,aux,contador=0; for(i=2;i<=numero;i++) { for(j=i/2;j>1;j--) /*comprueba si el nmero es divisible por otro menor o igual que la mitad*/ { /*para no hacer divisiones innecesarias*/ if(i%j!=0) { aux=i; } else { aux=0; break; /*si el programa llega a este punto es porque i es divisible por algn nmero*/ } /*entonces se rompe el bucle y se pasa a la siguiente iteracin*/ } if(aux!=0) /*si no se ha pasado por aux=0, es porque el nmero es primo, y lo imprimimos*/ { if (opcion==2) { printf("%u ",i); }

contador=contador+1; } } return(contador);/*devuelve la cantidad total de primos*/ } /*-------------------------------------------------------------------------*/

*Guarda(unsigned int numero,unsigned int cant_primos) /*esta funcin devuelve un puntero*/ { int *p; /*variable local puntero*/ unsigned int i=2,j,aux,contador=0; p=(int*)malloc(cant_primos*sizeof(int));/*asignacin din mica de memoria*/ if (p==NULL) { printf("Error en asignacin de memoria."); exit(4); } for(i=2;i<=numero;i++) { for(j=i/2;j>1;j--) /*comprueba si el nmero es divisible por otro menor o igual que la mitad*/ { /*para no hacer divisiones innecesarias*/ if(i%j!=0) /*comprueba si el resto es nulo o no*/ { aux=i; } else { aux=0; break; /*si el programa llega a este punto es porque i es divisible por algn nmero*/ } /*entonces se rompe el bucle y se pasa a la siguiente iteracin*/ } if(aux!=0) /*si no se ha pasado por aux=0, es porque el nmero es primo, y lo guardamos*/ { p[contador]=i; contador++; } } return(p);/*devolucin del puntero a main*/ } /*-------------------------------------------------------------------------*/ void Descompone(unsigned int numero,unsigned int num_primos,unsigned int *pr) { unsigned int resto,i,aux; unsigned int *contador2; contador2=(int*)calloc((num_primos),sizeof(int));/*A.D. de memoria para el contador*/ if (contador2==NULL) { printf("Error en la asignacin de memoria\n"); exit(5); } printf("\nA continuacin vamos a descomponer en factores primos el numero que usted \nha introducido.\n");

printf("\n"); aux=numero; printf("\tEl proceso de descomposicin es el siguiente:\n\n"); for (i=0;i<num_primos;i++) { while (numero%pr[i]==0) { resto=numero/pr[i]; printf("\t\t%u | %u\n",numero,pr[i]); numero=resto; contador2[i]+=1; } } printf("\n"); printf("El nmero %u descompuesto en factores primos es el producto de:\n\n",aux); for (i=0;i<num_primos;i++) { if (contador2[i]!=0)/*para que no escriba si el exponente es 0*/ { printf(" %u elevado a %u\n",pr[i],contador2[i]); } } free(pr); free(contador2); }

Prog15.c
#include <stdio.h> #define TAM 3 void Suma(int [][],int [][]); void Multiplica(int [][],int [][]); void Traspone(int [][]); void Visualiza(int [][]); void main() { int opcion; int A[TAM][TAM]; int B[TAM][TAM]; int i,j; printf("Este programa realiza las siguientes operaciones con matrices:\n"); printf(" 1.-Suma.\n"); printf(" 2.-Multiplicacin.\n"); printf(" 3.-Trasposicin.\n"); printf("Introduce el nmero de tu opcin:"); scanf ("%d",&opcion); switch (opcion) { case 1: printf ("Introduce matriz A.\n"); /*Pide la matriz*/ for (i=0;i<TAM;i++) { for (j=0;j<TAM;j++) { printf("Introduce elemento (%d,%d)\n",i,j);

scanf("%d",& A[i][j]); } printf ("\n\n"); } printf ("Introduce matriz B\n"); for (i=0;i<TAM;i++) { for (j=0;j<TAM;j++) { printf("Introduce elemento (%d,%d)\n",i,j); scanf("%d",& B[i][j]); } } printf ("La matriz A es:\n"); Visualiza(A); printf ("La matriz B es:\n"); Visualiza(B); Suma(A,B); break; case 2: printf ("Introduce matriz A.\n"); for (i=0;i<TAM;i++) { for (j=0;j<TAM;j++) { printf("Introduce elemento (%d,%d)\n",i,j); scanf("%d",& A[i][j]); } printf ("\n\n"); } printf ("Introduce matriz B\n"); for (i=0;i<TAM;i++) { for (j=0;j<TAM;j++) { printf("Introduce elemento (%d,%d)\n",i,j); scanf("%d",& B[i][j]); } } printf ("La matriz A es:\n"); Visualiza(A); printf ("La matriz B es:\n"); Visualiza(B); Multiplica(A,B); break; case 3: printf ("Introduce matriz A.\n");

for (i=0;i<TAM;i++) { for (j=0;j<TAM;j++) { printf("Introduce elemento (%d,%d)\n",i,j); scanf("%d",& A[i][j]); } printf ("\n\n"); } printf ("La matriz A es:\n"); Visualiza(A); printf ("La traspuesta es:\n"); Traspone(A); break; default: printf("Opcin incorrecta.\n"); exit(4); } } void Suma(int A[TAM][TAM],int B[TAM][TAM]) { int i,j; int C[TAM][TAM]; for (i=0;i<TAM;i++) /*suma las matrices*/ { for (j=0;j<TAM;j++) { C[i][j]=A[i][j] + B[i][j]; } } printf("\nEl resultado es:\n"); for (i=0;i<TAM;i++) /*imprime el resultado*/ { for (j=0;j<TAM;j++) { printf("%d ",C[i][j]); } printf("\n"); } } void Multiplica (int A[TAM][TAM],int B[TAM][TAM]) { int i,j,k; int C[TAM][TAM]; for(i=0;i<TAM;i++) { for (j=0;j<TAM;j++) {

C[i][j]=0; for (k=0;k<TAM;k++) { C[i][j]=C[i][j]+(A[i][k]*B[k][j]); } } } printf("\nEl producto de las dos es \n"); for (i=0;i<3;i++) { for (j=0;j<3;j++) { printf("%d ",C[i][j]); } printf("\n"); } } void Traspone(int A[TAM][TAM]) { int i,j; int traspuesta[TAM][TAM]; for (i=0;i<TAM;i++) { for (j=0;j<TAM;j++) { traspuesta [i][j]=A[j][i]; printf("%d ",traspuesta [i][j]); } printf("\n"); } } void Visualiza(int matriz[TAM][TAM]) { int i,j; for (i=0;i<TAM;i++) { for (j=0;j<TAM;j++) { printf ("%d ", matriz [i][j]); } printf ("\n"); } }

Prog16.c
/*PROGRAMA QUE OBTIENE LA CLASIFICACIN DE UNA PRUEBA DE NATACIN*/ #include <stdio.h> /*Declaracin de funciones a usar*/ float Convierte();

void Seleccion (float *,int); void Desconv (float); /*Variables globales*/ int min,seg,cent; void main() { int i,nadadores; float *tiempo; /*Cabecera*/ printf ("Este programa obtiene la clasificacin de una prueba de natacin de 50,100 y 200metros.\n"); printf ("Introduzca el nmero de participantes en la prueba:"); scanf ("%d",&nadadores); /*Reserva de memoria*/ tiempo=(float*)malloc(nadadores*sizeof(float)); printf ("\n\nIntroduce los tiempos(min seg cent):\n");/*Lee los tiempos*/ for (i=0;i<nadadores;i++) { printf ("Tiempo %d:",i+1); scanf ("%d" "%d" "%d",&min,&seg,&cent); tiempo[i]=Convierte();/*Almacena los tiempos en forma de centsimas*/ } Seleccion(tiempo,nadadores);/*Ordena los tiempos de menor a mayor*/ printf ("La clasificacin es:\n"); for (i=0;i<nadadores;i++) /*Saca la clasificacin*/ { Desconv(tiempo[i]); printf ("%d.- %d'%02d''%02d\n",i+1,min,seg,cent); } } float Convierte() /*Convierte los tiempos de min,seg,cent a cent*/ { float cent1; float cent2,total; cent1=min*6000; /*minutos ---> cent*/ cent2=seg*100; /*segundos---> cent*/ total=cent1+cent2+cent; return (total); } void Seleccion(float *punt,int K) /*Ordena arreglos de "floats"*/ { int i,j,pos_min=0; float aux; float minimo; for (i=0;i<K;i++) /*coge la posicin inicial 1,2,...,K*/ { minimo=punt[i]; pos_min=i; for(j=i;j<K;j++)/*recorre el arreglo*/ { if(minimo>punt[j]) { minimo=punt[j];/*compara el 1 elemento con los dems y asigna a mnimo el menor*/ pos_min=j;

} } /*intercambio*/ aux=punt[i]; punt[i]=minimo; punt[pos_min]=aux; } } void Desconv(float marca) /*Desconvierte los tiempos de cent a min,seg,cent*/ { int aux; min=(int)(marca/6000); /*Divisin entera de la marca para obtener los minutos*/ aux=(int) marca%6000; /*Resto de la divisin anterior*/ seg=aux/100; /*Divisin entera del resto para obtener los segundos*/ cent=(int)aux%100; /*Resto de antes para obtener las centsimas*/ }

Prog17.c
/*PROGRAMA QUE ORDENA UNA LISTA DE PALABRAS DE LA A-Z O DE LA Z-A*/ #include <stdio.h> #include <stdlib.h> #include <string.h> /*Funciones a usar*/ void A_Z (char *[],int); void Z_A (char *[],int); void main() { int i,num_elem=0; char *lista[20]; int opcion; /*cabecera*/ printf ("\n\nEste programa ordena alfabticamente una lista de palabras.\n\n"); printf ("Cuando hallas terminado tu lista de palabras escribe FIN.\n"); /*Lee la lista de palabras hasta que se introduce la palabra FIN(en maysculas)*/ printf ("Por favor introduce las palabras (MAX.25 caracteres):\n"); do { lista[num_elem]=(char*)malloc(27*sizeof(char)); printf ("Palabra %d: ",num_elem+1); scanf("%s",lista[num_elem]); }while (strcmp(lista[num_elem++], "FIN")); /*Men para elegir ordenacin de la A-Z o de Z-A*/

printf ("\n\nElige el orden de ordenacin:\n"); printf (" 1.-De la A-Z.\n"); printf (" 2.-De la Z-A.\n"); printf ("Escribe el nmero de tu opcin:"); scanf ("%d",&opcion); switch(opcion) { case 1: A_Z (lista,num_elem-1); break; case 2: Z_A (lista,num_elem-1); break; default: printf ("\nEsa opcion no es correcta."); exit (1); } printf ("\n"); printf ("La lista ordenada es:\n"); /*Saca la lista ordenada*/ for (i=0;i<num_elem-1;i++) { printf ("La palabra %d es: %s.\n",i+1,lista[i]); } } void A_Z (char *lista[],int tamano) /*Ordena de A-Z*/ { char *aux; int i,j; for (j=0;j<tamano-1;j++) { for (i=j;i<tamano;i++) { if (strcmpi(lista[j],lista[i]) > 0) /*Ordena alfabeticamente usando la funcion del C STRCMPI*/ { /*La condicin > implica ordenacion normal*/ aux=lista[j]; lista[j]=lista[i]; lista[i]=aux; } } } } void Z_A (char *lista[],int tamano) /*Ordena de Z-A*/ { char *aux; int i,j; for (j=0;j<tamano-1;j++) { for (i=j;i<tamano;i++) { if (strcmpi(lista[j],lista[i]) < 0) /*Ordena alfabeticamente usando la funcion del C STRCMPI*/

{ aux=lista[j]; lista[j]=lista[i]; lista[i]=aux; } } } }

/*La condicon < implica ordenacin inversa*/

Prog18.c
/*PROGRAMA QUE ORDENA UNA LISTA DE PALABRAS COGIDAS DEL ARCHIVO PALABRAS.TXT LAS GUARDA EN PALABORD.TXT*/ #include <stdio.h> #include <stdlib.h> #include <string.h> /*Funciones a usar*/ void A_Z (char *[],int); void Z_A (char *[],int); void main() { FILE *desorden; /*punteros de ficheros*/ FILE *orden; int i,num_elem=0; char destino[50]; char **lista; int opcion; /*cabecera*/ printf ("\n\nEste programa ordena alfabticamente una lista de palabras procedente del\narchivo PALABRAS.TXT, y la guarda en otro archivo dado por el usuario.\n"); printf ("Por favor introduce el archivo en el que deseas guardar la lista de palabras\nordenada:\n"); gets(destino); desorden=fopen("palabras.txt","r"); /*apunta el puntero a un archivo en modo lectura*/ if(desorden==NULL) { printf ("Error en asignacin de archivos.\n"); exit (1); } orden=fopen(destino,"w"); /*apunta el puntero a un archivo en mod escritura*/ if(orden==NULL) { printf ("Error en asignacin de archivos.\n"); exit (1); } /*Lee la lista de palabras hasta que se encientra el fin del archivo*/ do { lista[num_elem]=(char*)malloc(27*sizeof(char)); /*reserva memoria segn aumentan los elementos*/ fscanf(desorden,"%s",lista[num_elem]); num_elem++; }while (!feof(desorden)); fclose(desorden); /*cierra el fichero al que apunta desorden*/

printf ("\n\nEl programa ya ha leido la lista de palabras del fichero PALABRAS.TXT.\n"); /*Men para elegir ordenacin de la A-Z o de Z-A*/ printf ("Elige el orden de ordenacin:\n"); printf (" 1.-De la A-Z.\n"); printf (" 2.-De la Z-A.\n"); printf ("Escribe el nmero de tu opcin:"); scanf ("%d",&opcion); switch(opcion) { case 1: A_Z (lista,num_elem-1); break; case 2: Z_A (lista,num_elem-1); break; default: printf ("\nEsa opcion no es correcta."); exit (1); } for (i=0;i<num_elem-1;i++) /*Escribe la lista de palabras ordenada en otro fichero*/ { fprintf (orden,"%s\n",lista[i]); } fclose(orden); printf ("La lista ordenada ha sido guardada en PALABORD.TXT.\n"); } void A_Z (char *lista[],int tamano) /*Ordena de A-Z*/ { char *aux; int i,j; for (j=0;j<tamano-1;j++) { for (i=j;i<tamano;i++) { if (strcmpi(lista[j],lista[i]) > 0) /*Ordena alfabeticamente usando la funcion del C STRCMPI*/ { /*La condicin > implica ordenacion normal*/ aux=lista[j]; lista[j]=lista[i]; lista[i]=aux; } } } } void Z_A (char *lista[],int tamano) /*Ordena de Z-A*/ { char *aux; int i,j; for (j=0;j<tamano-1;j++)

{ for (i=j;i<tamano;i++) { if (strcmpi(lista[j],lista[i]) < 0) /*Ordena alfabeticamente usando la funcion del C STRCMPI*/ { /*La condicon < implica ordenacin inversa*/ aux=lista[j]; lista[j]=lista[i]; lista[i]=aux; } } } }

Prog19.c
#include <stdio.h> void main() { FILE *destino; int indice=0; int anio; destino=fopen("fechas.txt","w"); /*Asigna al puntero el lugar donde est FECHAS.TXT*/ /*Condicin de seguridad*/ if (destino==NULL) { printf ("Error en asignacin de puntero"); exit (1); } /*Cabecera*/ printf ("Este programa guarda los datos de aos de nacimiento de una poblacin en un\narchivo llamado FECHAS.TXT.\n"); printf ("Introduce los aos de nacimiento de los individuos(para finalizar introduce -1):\n"); do { printf ("Individuo %d:",indice+1); scanf ("%d",&anio); if (anio!=-1) /*Escribe los datos en el fichero si son distintos de -1*/ { fprintf (destino,"%d\n",anio); indice++; } else /*Cuando el dato sea -1 finaliza el programa*/ { printf ("Fin de introduccin de datos.\n"); printf ("El nmero de habitantes es: %d individuos.\n",indice); exit (0); } }while (1); fclose(destino);

Prog20.c
/*PROGRAMA QUE DICE QUE TIPO DE PAIS ES Y PIRMIDE DE POBLACIN CORRESPONDIENTE A PARTIR DE LAS FECHAS DE NACIMIENTO DE LOS POBLADORES*/ #include <stdio.h> /*funciones a utilizar*/ void Edades (int*,int*,int,int); /*calcula la edad de los individuos*/ int Secuencial(int*,int,int); /*busca el nmero de individuos con una determinada edad*/ int Juventud (int*,int); /*calcula los individuos de 0 a 15 aos*/ int Adulto (int*,int); /*calcula los individuos de 15 a 65 aos*/ int Vejez (int*,int); /*calcula los individuos de 65 a 130 aos*/ void main() { FILE *origen; int actual,i; int individuos=0; int *anio; int *edad; int juventud,adulto,vejez; float porc_juv,porc_adul,porc_vej; /*cabecera*/ printf ("Este programa calcula el nmero de habitantes de la poblacin as como el\nporcentaje de habitantes de cada estado social.\n"); printf ("El programa coge los datos de un archivo de texto llamado FECHAS.TXT.\n"); printf ("Por favor introduce el ao actual:"); scanf ("%d",&actual);

origen=fopen("fechas.txt","r"); if (origen==NULL) { printf("Error en el archivo\n"); exit(1); } do /*lee los aos de nacimiento de los individuos del archivo fechas.txt*/ { anio[individuos]=(int*)malloc(sizeof(int)); /*asignacin dinmica de memoria*/ fscanf (origen,"%d",&anio[individuos]); individuos++; }while(!feof(origen)); fclose(origen); individuos--; /*resta un individuo para no leer el carecter EOF*/ edad=(int*)malloc(individuos*sizeof(int)); /*asignacin dinmica de memoria*/ Edades(anio,edad,individuos,actual); juventud=Juventud(edad,individuos); adulto=Adulto(edad,individuos);

vejez=Vejez(edad,individuos); porc_juv=(float)(juventud*100)/individuos; /* % de jvenes*/ porc_adul=(float)(adulto*100)/individuos; /* % de adultos*/ porc_vej=(float)(vejez*100)/individuos; /* % de ancianis*/ printf ("\n\n"); printf ("El nmero de habitantes en el pas es de %d.",individuos); printf ("\n\n"); printf ("Porcentaje de menores de 15 aos(jvenes): %.2f%\n",porc_juv); printf ("Porcentaje de individuos entre 15-65 aos(adultos): %.2f%\n",porc_adul); printf ("Porcentaje de individuos de ms de 65 aos(ancianos): %.2f%\n",porc_vej); printf ("\n\n"); /*halla el tipo de pas de que se trata (joven,intermedio o viejo*/ if (porc_juv>=40) { printf ("El porcentaje de individuos jvenes es mayor del 40%, por tanto es un PAS JVEN\n."); printf ("Su pirmide de poblacin se corresponde con una base ancha y una cspide estrecha.\n"); } else if (porc_juv<40&&porc_vej<12) { printf ("El porcentaje de jvenes es menor del 40% y el de ancianos menor del 12%.\nPor tanto es un PAS INTERMEDIO.\n"); printf ("Su pirmide se asemeja ms a un rectngulo en la base y en el centro.\n"); } else if (porc_vej>12) { printf ("El porcentaje de ancianos es mayor del 12%,por tanto es un PAS VIEJO.\n"); printf ("Su pirmide de poblacin es invertida; ms ancha en la cspide que en la base.\n"); } printf ("\n\n"); }

/*--------------------------------------------------------------------------*/ int Vejez (int *edad,int tam) { int i; int veces=0; int vejez=0; for(i=66;i<=500;i++) { veces=Secuencial(edad,tam,i); /*busca individuos con la edad i*/ vejez+=veces; } return (vejez); } /*--------------------------------------------------------------------------*/ int Adulto (int *edad,int tam) { int i; int veces=0;

int adulto=0; for(i=15;i<=65;i++) { veces=Secuencial(edad,tam,i); /*busca individuos con la edad i*/ adulto+=veces; } return (adulto); } /*--------------------------------------------------------------------------*/ int Juventud (int *edad,int tam) { int i; int veces=0; int juventud=0; for(i=0;i<15;i++) { veces=Secuencial(edad,tam,i); /*busca individuos con la edad i*/ juventud+=veces; } return (juventud); } /*--------------------------------------------------------------------------*/ int Secuencial(int *arreglo,int tam,int buscado) { int num_veces=0; int i; for (i=0;i<tam;i++) { if (arreglo[i]==buscado) { num_veces++; } } return (num_veces); }

/*--------------------------------------------------------------------------*/ void Edades(int *lista,int *edad,int tam,int actual) { int i; for (i=0;i<tam;i++) { edad[i]=actual-lista[i]; } }

Prog21.c
/*PROGRAMA QUE GUARDA ESTRUCTURAS EN ARCHIVOS DE TEXT0*/ #include <stdio.h> /*Definicin de la estructura*/

struct biblioteca { char titulo[50]; char autor[50]; char editorial[20]; unsigned int precio; }; void main() { int i,num_libros; FILE *destino; char archivo[15]; struct biblioteca libro; /*declaracin de la variable del tipo de la estructura biblioteca*/ printf ("Programa que escribe el registro de libros recibidos en una libreria en un archivo especificado por el usuario.\n"); printf ("Por favor introduce el nombre del archivo donde se guardarn los datos:\n"); gets(archivo); printf ("Por favor introduce el nmero de libros recibidos:"); scanf ("%d",&num_libros); destino=fopen(archivo,"w"); if (destino==NULL) { printf("Error en la asignacin de puntero.\n"); exit(1); } for (i=0;i<num_libros;i++) /*coge los datos y los archiva en un archivo*/ { gets(libro.autor); printf ("Titulo(MAX.50):"); gets(libro.titulo); /*coge la cadena y la manda a la direccin de titulo dentro de la estructura libro*/ printf("Autor(MAX.50):"); gets(libro.autor); printf("Editorial(MAX.20):"); gets(libro.editorial); printf ("Precio:"); scanf ("%u",&libro.precio); printf ("\n"); fprintf (destino,"Titulo: %s\n",libro.titulo); /*Escribe el contenido de la variable titulo que esta dentro de una estructura*/ fprintf (destino,"Autor: %s\n",libro.autor); fprintf (destino,"Editorial: %s\n",libro.editorial); fprintf (destino,"Precio: %u\n\n",libro.precio); } fclose(destino); }

Prog22.c
/*PROGRAMA QUE RECOGE GUARDA EN UN ARCHIVO BINARIO LAS DATOS DE UNOS LIBROS*/ #include <stdio.h> #include <conio.h>

/*declaracin de estructuras*/ struct fecha { int dia; int mes; int anio; }; struct prestado { char nombre[20]; char apellido1 [20]; char apellido2 [20]; struct fecha fecha; /*estructura dentro de estructura*/ }; struct biblioteca { char titulo[50]; char autor[50]; char editorial[20]; struct prestado prestado; /*estructura dentro de estructura*/ }; /*declaracin de funciones*/ struct biblioteca Introducir(struct biblioteca); struct biblioteca Inicializar(struct biblioteca); void main() { FILE *destino; struct biblioteca libro; clrscr(); /*limpia la pantalla*/ /*cabecera*/ printf ("Este programa guarda los datos de los libros de una biblioteca en un archivo\nbinario llamado BIBLIOTE.BIN.\n"); printf ("Las indicaciones entre corchetes corresponden al nmero mximo de caracteres\naceptables (incluidos espacios en blanco).\n\n"); printf ("Introduce los datos de los libros (para terminar escribe FIN en el titulo):\n"); printf ("\n"); destino=fopen("bibliote.bin","w"); if(destino==NULL) { printf("Error en archivo.\n"); exit(1); } while (1) /*bucle infinito*/ { printf ("Titulo(Mx[50]):"); gets(libro.titulo); if (strcmp(libro.titulo,"FIN")==0) /*condicin de ruptura del bucle*/ { printf ("Proceso de introduccin de datos finalizado.\n"); break;

} libro=Introducir(libro); /*funcin para coger los datos*/ clrscr(); fwrite (&libro,sizeof(struct biblioteca),1,destino); /*escribe datos en un archivo en forma binaria*/ printf ("\n"); gets (libro.titulo); } fclose (destino); } /*---------------------------------------------------------------------------*/ struct biblioteca Introducir (struct biblioteca libro) { char prestado; printf ("Autor(Mx[50]):"); gets(libro.autor); printf ("Editorial(Mx[20]):"); gets(libro.editorial); printf ("Este libro esta prestado?[s/n]:"); scanf ("%c",&prestado); if (prestado=='s') { printf ("\n\nIntroduce los datos de la persona y la fecha;\n"); gets(libro.prestado.nombre); printf ("Nombre(Mx[20]:"); gets(libro.prestado.nombre); printf ("1Apellido(Mx[20]):"); gets(libro.prestado.apellido1); printf ("2Apellido(Mx[20]):"); gets(libro.prestado.apellido2); printf ("Fecha(dd mm aa):"); scanf ("%d %d %d",&libro.prestado.fecha.dia,&libro.prestado.fecha.mes,&libro.prestado.fecha.anio); printf ("\n\n"); } else { libro=Inicializar(libro); /*funcin para dar valores por defecto a los prstamos*/ } return(libro); } /*---------------------------------------------------------------------------*/ struct biblioteca Inicializar(struct biblioteca libro) { int i; libro.prestado.fecha.dia = 0; libro.prestado.fecha.mes = 0; libro.prestado.fecha.anio = 0; for (i=0;i<20;i++) /*bucle que llena el nombre del prstamo con espacios en blanco*/ { libro.prestado.nombre[i]=' '; } for (i=0;i<20;i++)

{ libro.prestado.apellido1[i]=' '; } for (i=0;i<20;i++) { libro.prestado.apellido2[i]=' '; } return(libro); }

Prog23.c
/*PROGRAMA PARA VER LOS DATOS DE LOS LIBROS GUARDADOS EN BIBLIOTE.BIN*/ #include <stdio.h> #include <conio.h> /*declaracin de estructuras*/ struct fecha { int dia; int mes; int anio; }; struct prestado { char nombre [20]; char apellido1 [20]; char apellido2 [20]; struct fecha fecha; }; struct biblioteca { char titulo[50]; char autor[50]; char editorial[20]; struct prestado prestado; }; /*declaracin de funciones*/ void Ver(struct biblioteca,int);

void main() { FILE *origen; char continuar; int registro; struct biblioteca libro; clrscr(); /*limpia la pantalla*/ /*cabecera*/ printf ("Este programa muestra uno por uno cada uno de los libros contenidos en el\narchivo BIBLIOTE.BIN.\n");

printf ("Introduzca el registro desde el que desea comenzar: "); scanf ("%d",&registro); origen=fopen("bibliote.bin","r"); if(origen==NULL) { printf("Error en el archivo.\n"); exit(1); } while (!feof(origen)) { fseek (origen,(registro-1)*sizeof(struct biblioteca),SEEK_SET);/*busca la posicin del registro a ver*/ fread (&libro,sizeof(struct biblioteca),1,origen); Ver(libro,registro); /*funcin que muestra los datos*/ registro++; printf ("\n=============================================================================\n"); printf ("Desea continuar?[s/n]:"); scanf ("\n%c",&continuar); if (continuar=='n') /*condicin para finalizar*/ { printf ("Proceso terminado por el usuario.\n"); exit (0); } clrscr(); } printf ("\nTodos los registros han sido visualizados.\n"); fclose(origen); } /*-----------------------------------------------------------------------------------------*/ void Ver(struct biblioteca libro,int registro) { printf ("\n\nREGISTRO: %d\n\n",registro); printf ("Ttulo: %s\n",libro.titulo); printf ("Autor: %s\n",libro.autor); printf ("Editorial: %s\n",libro.editorial); printf ("-----------------------------------------------------------------------------\n"); printf ("El libro ha sido prestado a:\n"); printf ("Nombre: %s\n",libro.prestado.nombre); printf ("1Apellido: %s\t2Apellido: %s\n",libro.prestado.apellido1,libro.prestado.apellido2); printf ("\n"); printf ("Fecha de %d/%d/%d\n",libro.prestado.fecha.dia,libro.prestado.fecha.mes,libro.prestado.fecha.anio); }

prstamo:

Prog24.c
/*PROGRAMA QUE AADE DATOS A UN ARCHIVO BINARIO (BIBILIOTE.BIN) LAS DATOS DE UNOS LIBROS*/ #include <stdio.h> #include <conio.h>

/*declaracin de estructuras*/ struct fecha { int dia; int mes; int anio; }; struct prestado { char nombre[20]; char apellido1 [20]; char apellido2 [20]; struct fecha fecha; /*estructura dentro de estructura*/ }; struct biblioteca { char titulo[50]; char autor[50]; char editorial[20]; struct prestado prestado; /*estructura dentro de estructura*/ }; /*declaracin de funciones*/ struct biblioteca Introducir(struct biblioteca); struct biblioteca Inicializar(struct biblioteca); void main() { FILE *destino; struct biblioteca libro; clrscr(); /*limpia la pantalla*/ /*cabecera*/ printf ("Este programa aade datos libros de una biblioteca al archivo\nbinario BIBLIOTE.BIN.\n"); printf ("Las indicaciones entre corchetes corresponden al nmero mximo de caracteres\naceptables (incluidos espacios en blanco).\n\n"); printf ("Introduce los datos de los libros (para terminar escribe FIN en el titulo):\n"); printf ("\n"); destino=fopen("bibliote.bin","a"); if(destino==NULL) { printf("Error en archivo.\n"); exit(1); } while (1) /*bucle infinito*/ { printf ("Titulo(Mx[50]):"); gets(libro.titulo); if (strcmp(libro.titulo,"FIN")==0) /*condicin de ruptura del bucle*/ { printf ("Proceso de introduccin de datos finalizado.\n"); break; }

libro=Introducir(libro); /*funcin para coger los datos*/ clrscr(); fwrite (&libro,sizeof(struct biblioteca),1,destino); /*escribe datos en un archivo en forma binaria*/ printf ("\n"); gets (libro.titulo); } fclose (destino); } /*---------------------------------------------------------------------------*/ struct biblioteca Introducir (struct biblioteca libro) { char prestado; printf ("Autor(Mx[50]):"); gets(libro.autor); printf ("Editorial(Mx[20]):"); gets(libro.editorial); printf ("Este libro esta prestado?[s/n]:"); scanf ("%c",&prestado); if (prestado=='s') { printf ("\n\nIntroduce los datos de la persona y la fecha;\n"); gets(libro.prestado.nombre); printf ("Nombre(Mx[20]:"); gets(libro.prestado.nombre); printf ("1Apellido(Mx[20]):"); gets(libro.prestado.apellido1); printf ("2Apellido(Mx[20]):"); gets(libro.prestado.apellido2); printf ("Fecha(dd mm aa):"); scanf ("%d %d %d",&libro.prestado.fecha.dia,&libro.prestado.fecha.mes,&libro.prestado.fecha.anio); printf ("\n\n"); } else { libro=Inicializar(libro); /*funcin para dar valores por defecto a los prstamos*/ } return(libro); } /*---------------------------------------------------------------------------*/ struct biblioteca Inicializar(struct biblioteca libro) { int i; libro.prestado.fecha.dia = 0; libro.prestado.fecha.mes = 0; libro.prestado.fecha.anio = 0;

for (i=0;i<20;i++) /*bucle que llena el nombre del prstamo con espacios en blanco*/ { libro.prestado.nombre[i]=' ';

} for (i=0;i<20;i++) { libro.prestado.apellido1[i]=' '; } for (i=0;i<20;i++) { libro.prestado.apellido2[i]=' '; } return(libro); }

Prog25.c
/*PROGRAMA PARA CAMBIAR LOS DATOS DEL ARCHIVO BIBLIOTE.BIN*/ #include <stdio.h> #include <conio.h> /*declaracin de estructuras*/ struct fecha { int dia; int mes; int anio; }; struct prestado { char nombre[20]; char apellido1 [20]; char apellido2 [20]; struct fecha fecha; };

struct biblioteca { char titulo[50]; char autor[50];

char editorial[20]; struct prestado prestado; }; /*declaracin de funciones*/ struct biblioteca Introducir(struct biblioteca); struct biblioteca Inicializar(struct biblioteca); void main() { FILE *destino; struct biblioteca libro; int registro; clrscr();/*limpia la pantalla*/ /*cabecera*/ printf ("Este programa permite cambiar los datos de un libros del archivo binario llamadoBIBLIOTE.BIN.\n"); printf ("Las indicaciones entre corchetes corresponden al nmero mximo de caracteres\naceptables (incluidos espacios en blanco.\n\n"); printf ("Introduce los datos de los libros (para terminar escribe FIN en el titulo):\n"); printf ("\n"); destino=fopen("bibliote.bin","r+"); if (destino==NULL) { printf ("Error en archivo.\n"); exit(1); } printf ("Introduce el nmero de registro del libro a modificar:"); scanf ("%d",&registro); fseek(destino,(registro-1)*sizeof(struct biblioteca),SEEK_SET);/*busca la posicin del registro a modificar*/ fread (&libro,sizeof(struct biblioteca),1,destino);/*lee los datos de ese registro*/ printf ("Introduce los nuevos datos:\n"); printf ("Titulo(Mx[50]):"); gets(libro.titulo); gets(libro.titulo); libro=Introducir(libro); /*funcin para introducir los datos*/ fseek(destino,(registro-1)*sizeof(struct biblioteca),SEEK_SET); /*vuelve a situar el puntero en el lugar del registro a sustituir*/ fwrite (&libro,sizeof(struct biblioteca),1,destino); /*escribe los nuevos datos*/ printf ("\n"); printf ("Los datos han sido modificados.\n"); fclose (destino); }

/*--------------------------------------------------------------------------*/ struct biblioteca Introducir (struct biblioteca libro)

{ char prestado; printf ("Autor(Mx[50]):"); gets(libro.autor); printf ("Editorial(Mx[20]):"); gets(libro.editorial); printf ("Este libro esta prestado?[s/n]:"); scanf ("%c",&prestado); if (prestado=='s') { printf ("\n\nIntroduce los datos de la persona y la fecha;\n"); gets(libro.prestado.nombre); printf ("Nombre(Mx[20]:"); gets(libro.prestado.nombre); printf ("1Apellido(Mx[20]):"); gets(libro.prestado.apellido1); printf ("2Apellido(Mx[20]):"); gets(libro.prestado.apellido2); printf ("Fecha(dd mm aa):"); scanf ("%d %d %d",&libro.prestado.fecha.dia,&libro.prestado.fecha.mes,&libro.prestado.fecha.anio); printf ("\n\n"); } else { libro=Inicializar(libro); /*funcin que asigna unos datos iniciales a prestado*/ } return(libro); } /*--------------------------------------------------------------------------*/ struct biblioteca Inicializar(struct biblioteca libro) { int i; libro.prestado.fecha.dia = 0; libro.prestado.fecha.mes = 0; libro.prestado.fecha.anio = 0; for (i=0;i<10;i++) { libro.prestado.nombre[i]=' '; } for (i=0;i<10;i++) /*bucle para rellenar el espacio de apellido1 con espacios en blanco*/ { libro.prestado.apellido1[i]=' '; } for (i=0;i<10;i++) { libro.prestado.apellido2[i]=' '; } return(libro); }

Binaria.c
#include <stdio.h> #include <stdlib.h> #include <buscar.h> void main() { int i,tam,buscado; int *lista; int *posicion; printf ("Este programa busca dentro de un arreglo ordenado las posiciones en las que\naparece un elemento.\n"); printf ("Introduce el nmero de elementos:\n"); scanf ("%d", &tam); lista=(int*)malloc(tam*sizeof(int)); if (lista==NULL) { printf ("Error en asignacin de memoria a lista"); exit (1); } posicion=(int*)calloc(tam,sizeof(int)); /*Asigna memoria a posicin y lo inicializa a cero*/ if (posicion ==NULL) { printf ("Error en asignacin de memoria a posicion"); exit (1); } printf ("Introduce los elementos ordenados:\n"); for (i=0;i<tam;i++) { scanf ("%d", &lista[i]); } printf ("Introduce el elemento buscado:\n"); scanf ("%d",&buscado); BusqBinaria(lista,tam,buscado,posicion); /*Llamada a la funcin*/ printf ("Las posiciones son:\n"); for (i=0;i<tam;i++) { while (posicion[i]!=0&&i<tam) /*Cuando encuentra el valor cero es que no hay ms informacin til*/ { if (posicion[i]==-1) /*si hay un -1 es porque el elemento se encuentra en la posico 0 del arreglo*/ { printf ("%d\n",0); i++; } else /*si no es -1 imprime su valor*/ { printf ("%d\n",posicion[i]); i++; } } } }

Velocida.c
#include <stdio.h> #include <stdlib.h> #include <ordena.h> #include <time.h> void Ordenado(); void Aleatorio(); void Inverso(); /*declaracin de las funciones*/ void Metodo(int*,int); /*funcion para elegir las opciones*/ float principio,fin; /*declaracin de variables globales para medir el tiempo*/ void main() { char opcion; printf ("Este programa ordena arreglos que se encuentran en diferentes estados de\nordenacin mediante diferentes mtodos y muestra adems el tiempo empleado.\n"); printf ("Si el nmero de elementos a ordenar es mayor de 300, estos no se\nvisualizaran. Slamente se saldr en pantalla el tiempo empleado en ordenarlo.\n"); printf ("Elige el estado de orden del arreglo.\n"); printf (" 1.- Ordenado.\n"); printf (" 2.- Aleatorio.\n"); printf (" 3.- Generado inversamente\n"); printf (" 4.- Abandonar.\n\n"); printf ("Escribe el nmero de tu eleccin:"); scanf ("%c", &opcion); switch (opcion) { case '1': Ordenado(); break; case '2': Aleatorio(); break; case '3': Inverso(); break; case '4': printf ("Programa abortado por el usuario.\n"); break; default: printf ("Opcin incorrecta\n"); } } void Ordenado() { int *ordenado; int i; int tam; printf("Introduce el nmero (mximo 10000) de elementos a generar:"); scanf ("%d",&tam);

ordenado=(int*)malloc(tam*sizeof(int)); if (aleat==NULL) /*comprobacin de asignacin de punteros*/ { printf("Error en la asignacin de memoria.\n); exit(1); } for (i=0;i<tam;i++) { ordenado[i]=i; } if (tam<=300) /*slo los imprime si son menos de 300*/ { printf ("Los nmeros son:\n"); for (i=0;i<tam;i++) { printf ("%d ",ordenado[i]); } } printf ("\n"); printf ("\n"); Metodo(ordenado,tam); printf ("\n"); if (tam<=300) { printf ("Los nmeros ordenados son:\n"); for(i=0;i<tam;i++) { printf ("%d ",ordenado[i]); } } printf ("\n\n"); printf ("El tiempo empleado ha sido:%f\n", (fin-principio)/CLK_TCK); /*trasforma los clicks de reloj en segundos*/ free (ordenado); } void Aleatorio() { int *aleat; int i; int tam; printf("Introduce el nmero (mximo 10000) de elementos a generar:"); scanf ("%d",&tam); aleat=(int*)malloc(tam*sizeof(int)); /*reserva dinmica de memoria*/ if (aleat==NULL) { printf("Error en la asignacin de memoria.\n); exit(1); } randomize();/*macro que inicializa el generador de nmeros aleatorios*/ for (i=0;i<tam;i++) { aleat[i]=rand() % tam; /*genera un arreglo de nmeros aleatorios*/ } if (tam<=300) {

printf ("Los nmeros son:\n"); for (i=0;i<tam;i++) { printf ("%d ",aleat[i]); } } printf ("\n"); printf ("\n"); Metodo(aleat,tam); printf ("\n"); if (tam<=300) { printf ("Los nmeros ordenados son:\n"); for(i=0;i<tam;i++) { printf ("%d ",aleat[i]); } } printf ("\n\n"); printf ("El tiempo empleado ha sido:%f\n",(fin-principio)/CLK_TCK); free (aleat); } void Inverso() { int *inverso; int i,j; int tam; printf("Introduce el nmero (menor o igual a 10000)de elementos a generar:"); scanf ("%d",&tam); inverso=(int*)malloc(tam*sizeof(int)); j=tam-1; /*variable auxiliar para generar los numeros ordenados inversamente*/ for (i=0;i<tam;i++) { inverso[i]=j; j--; } if (tam<=300) { printf ("Los nmeros son:\n"); for (i=0;i<tam;i++) { printf ("%d ",inverso[i]); } } printf ("\n"); printf ("\n"); Metodo(inverso,tam); if (tam<=300) { printf ("Los nmeros ordenados son:\n"); for(i=0;i<tam;i++) { printf ("%d ",inverso[i]); } } printf ("\n\n");

printf ("El tiempo empleado ha sido:%f\n",(fin-principio)/CLK_TCK); free (inverso); }

void Metodo(int *puntero,int N) { int elige; printf ("Este menu sirve para elegir el mtodo de ordenacin que prefieras:\n"); printf (" 1.- Seleccin directa.\n"); printf (" 2.- Burbuja.\n"); printf (" 3.- Insercin.\n"); printf (" 4.- Insercin binaria.\n"); printf (" 5.- Shell.\n"); printf (" 6.- Quicksort.\n"); printf (" 7.- Quicksort mejorado.\n\n"); printf ("Introduce el nmero de tu opcin:"); scanf ("%d", &elige); switch (elige) { case 1: principio=clock();/*inicio del temporizador en clicks de reloj*/ Seleccion(puntero,N);/*llamada a la funcin*/ fin=clock();/*fin del temporizador en clicks de reloj*/ break; case 2: principio=clock(); Burbuja(puntero,N); fin=clock(); break; case 3: principio=clock(); Insercion(puntero,N); fin=clock(); break; case 4: principio=clock(); InsercionBinaria(puntero,N); fin=clock(); break; case 5: principio=clock(); Shell(puntero,N); fin=clock(); break; case 6: principio=clock(); Quicksort(puntero,N); fin=clock(); break; case 7: principio=clock(); Quicksortmejor(puntero,N); fin=clock();

break; default: printf ("Opcion incorrecta"); break; } }

Poblacio.c
/*Programa que calcula el % de individuos de una determinada edad*/ #include <stdio.h> #include <ordena.h> #include <buscar.h> void main() { /*Declaracion de variables*/ int *anio; int *posicion; int n,i; int individuos; int anio_buscado; int porcentaje; /*Cabecera*/ printf ("Este programa calcula el porcentaje de individuos de una determinada edad dentrode una poblacin.\n"); printf ("Introduce el nmero de individuos en la poblacin:\n"); scanf ("%d",&individuos); /*Reserva de memoria*/ anio=(int*)malloc(individuos*sizeof(int)); posicion=(int*)calloc(individuos*sizeof(int));/*Arreglo usado por la funcin de bsqueda*/ printf ("Introduce los aos de nacimiento:\n");/*Lee los aos de nacimiento*/ for (i=0;i<individuos;i++) { printf ("Individuo %d:",i+1); scanf ("%d",&anio[i]); } Shell(anio,individuos);/*Ordena el arreglo*/ printf ("\n\n"); printf ("Introduce el ao de nacimiento de los individuos a evaluar:");/*Pide el ao a buscar*/ scanf ("%d",&anio_buscado); BusqBinaria(anio,individuos,anio_buscado,posicion);/*Busca las posiciones donde est ese ao*/ n=0; while (posicion[n]!=0) /*Cuenta el nmero de indiduos nacidos en ese ao*/ { n++; } porcentaje=(n*100)/individuos;/*Calcula el porcentaje de individuos con esa edad*/ printf ("\n\n"); printf ("El porcentaje de individuos nacidos en %d es: %d %\n",anio_buscado,porcentaje);

Bibliografa
Programacin en C Byron Gotfried (McGraw Hill) Programacin en lenguaje C Herbert Schildt (Mc Graw Hill) Programacin en Microsoft Cpara IBM PC y compatibles Robert Lafore - Grupo Waite (Anaya)