Sei sulla pagina 1di 47

Propsitos En esta unidad: Determinars las estructuras de datos involucradas en la solucin de un problema.

. Disears soluciones empleando arreglos y estructuras (registros). Utilizars arreglos y estructuras (registros) en programas escritos en lenguaje C. Competencia especfica Utilizar estructuras de datos para almacenar y manipular los datos de un programa por medio del desarrollo de programas en lenguaje C. Introduccin En muchas ocasiones nos vemos en la necesidad de procesar datos que estn relacionados entre s, a este tipo de datos se le conoce como estructurados, ya que estn compuestos de un conjuntos de datos bsicos (recuerda la clasificacin de datos presentada en la unidad 3 en la tabla 3.2 Tipo de datos). Por ejemplo pensemos en el nombre completo de una persona, que est compuesto nombre, apellido paterno y apellido materno, o bien, en una direccin, formada por nombre de la calle, nmero y cdigo postal, en este ltimo caso no slo est formada por varios datos simples sino que adems podemos considerarlos de diferentes tipos (Figura 5.3).

Figura 5.3: Ejemplos de datos Estructurados Con este tipo de datos ser til poder hacer referencia a ellos bajo un mismo identificador, y as tratarlos como una unidad. Una estructura de datos es un mecanismo de agrupacin de datos que facilitan el manejo de datos estructurados y que se caracteriza por la forma en que se acede a sus elementos. Pensemos en otro ejemplo en el cual se tienen datos relacionados, supongamos que nos enfrentamos al siguiente problema:

Fundamentos de programacin
Programa Desarrollado
Problema 5.1: Se requiere un programa para llevar el registro de calificaciones de un grupo de diez estudiantes y generar reportes que incluyan datos como el promedio del grupo, la calificacin mxima, el nmero de estudiantes que tienen una calificacin superior al promedio del grupo, entre otros. En este caso, a diferencia de los ejemplos anteriores, es claro que las calificaciones de cada estudiante se puede tratar como un dato simple e independiente de los otros, sin embargo las operaciones que se desean realizar sern las mismas para todo el conjunto de calificaciones, de tal forma que habra que escribir una serie de instrucciones secuenciales para ingresar cada dato y procesarlo. Por ejemplo, para ingresar los datos se requiere leer una por una cada calificacin, para obtener el promedio se tendra que hacer la suma de todas y despus dividirlas entre 10, hasta aqu no se ha complicado mucho, pero imagina todas las comparaciones que debes hacer para identificar cul es la calificacin mayor. Es claro que este mtodo resulta de lo ms ineficiente, y por supuesto si consideramos la posibilidad de modificar el programa para que sea capaz de procesar 60 o ms calificaciones, el programa adems de extenderse, implica reestructurarlo en su totalidad y que ste sea ms complejo que la versin anterior. En cambio si consideramos a todos las calificaciones como un dato estructurado podemos hacer uso de una estructura de dato que nos facilite su manipulacin. Existen diferentes tipos de estructuras de datos, cada una caracterizada por la forma de acceso a sus elementos, y el tipo que estos pueden tener, as tenemos arreglos, listas, colas, tablas, pilas, entre otros. No obstante, para esta unidad nos centraremos slo en las estructuras de datos que implementa el lenguaje C de forma directa: los arreglos y las estructuras. 5.1. Arreglos El uso de arreglos facilita y hace ms eficiente la declaracin y manipulacin de una coleccin de datos de un mismo tipo que estn relacionados entre s, como es el caso de las calificaciones en el Problema1, ya que todas las calificaciones se pueden considerar como valores enteros. 5.1.1. Definicin y tipos de arreglos Un arreglo se define como una coleccin finita, homognea y ordenada de elementos. Finita ya que para todo arreglo debe especificarse el nmero mximo de elementos que podr contener; la homogeneidad se refiere a que todos los elementos deben ser del mismo tipo, y ordenada porque es posible determinar cul es el primer elemento, cual el segundo, y as hasta el ensimo elemento(Cairo Osvaldo, Guardati Buemo Silvia, 1993). La posicin que ocupa un elemento dentro de un arreglo se le denomina formalmente ndice y siempre es un nmero entero. El tamao o longitud de un arreglo se define como el nmero de elementos que lo constituyen. La dimensin de un arreglo est relacionada con el nmero de ndices necesarios para especificar a una elemento en particular.

Fndamentos de programacin
Prll Podemos
clasificar a los arreglos de acuerdo a su dimensin como unidimensionales o multidimensionales. Los arreglos unidimensionales(tambin llamados lineales) reciben su nombre debido a que cualquier elemento es referenciado por un nico ndice, por ejemplo retomando el caso de las calificaciones del problema 5.1, stas pueden ser almacenadas en un arreglo unidimensional como el que se muestra en la Figura 5.4, en donde el nombre del arreglo es lista y los nombres de las variables donde se almacenan las calificaciones son: lista[0], lista[1], lista[2], lista[3], lista[4] , lista[9]. En este caso el nombre en comn es lista y lo nico que cambia para cada elemento es el nmero que le corresponde a cada variable segn la posicin que ocupa en la lista. Observa que un solo ndice es suficiente para diferenciar a un elemento de otro.

Figura 5.4 Representacin grfica de un arreglo unidimensional

Por otro lado los arreglos multidimensionales son aquellos para los cuales un solo ndice no es suficiente para poder referenciar a un elemento individual, los arreglos bidimensionales son el caso ms comnmente utilizado de arreglos multidimensionales y por tanto los nicos que presentaremos. Un arreglo bidimensional es un conjunto de datos homogneos, finito y ordenado, donde se hace referencia a cada elemento por medio de dos ndices. El primero de los cuales generalmente se utiliza para indicar rengln y el segundo para indicar columna (Cairo Osvaldo, Guardati Buemo Silvia, 1993) Un arreglo bidimensional tambin puede verse como una tabla de valores, o bien como un arreglo de arreglos, de ah la necesidad de dos ndices, en la Figura I.5 se muestra un ejemplo grfico de un arreglo bidimensional, en la cual del lado derecho podemos ver al arreglo como una tabla y del lado izquierdo representado como un arreglo de arreglos, Observa que cada rengln de la tabla es cada uno de los elementos del arreglo de arreglos. Es claro que con un solo ndice no podramos identificar a

Fundentos de programacin
Programo
Un nico elemento ya que solo podramos ubicar toda una columna o todo un rengln, en cambio la combinacin de rengln-columna si nos identifica a un elemento en particular.

Figura I.5Representacin grfica de un arreglo bidimensional 5.1.2. Declaracin e inicializacin En lenguaje C los ndices de los arreglo siempre empiezan en cero, es decir, al primer elemento del arreglo le corresponde la posicin 0, al segundo la posicin sucesivamente hasta llegar al elemento TAM-1, donde TAM corresponde al tamao del arreglo. La declaracin de un arreglo consiste en reservar espacio de memoria suficiente para el conjunto de datos homogneos. La declaracin de una variable de tipo arreglo sigue las mismas reglas que para las variables simples; con la diferencia de que ahora ser necesario especificar el tamao del arreglo, esto se hace escribiendo el tamao del arreglo encerrado entre corchetes identificador. La sintaxis para la declaracin de un arreglo unidimensional en lenguaje C es la siguiente: <tipo><nombre>[<tamao>]; Y para un arreglo bidimensional es: <tipo><nombre>[<tamao1>] [<tamao2>];

Fundamentos de programacin
Programa Desarrollado
El tipo de dato para los arreglos puede ser cualquier tipo bsico, es decir entero, flotante o carcter (en C int, float , double o char ). De todos ellos los arreglos de tipo carcter ( char ) tienen un tratamiento especial, ya que un arreglo de este tipo se considerara una cadena. Debido a la importancia que tienen las cadenas en la programacin ms adelante los trataremos de manera particular. Al igual que las variables simples, un arreglo puede inicializarse al momento de ser declarado, para ello se utiliza el operador asignacin =, pero como un arreglo almacena a un conjunto de datos, es necesario inicializarlo con un conjunto de valores, los cuales se indican mediante llaves, separando por comas cada elemento del conjunto de valores iniciales, la sintaxis se muestra a continuacin: <tipo><nombre>[<tamao>]={<valor0>,<valor1>,,<valorTAM-1>}; La asignacin de cada valor inicial se hace consecutivamente desde el elemento 0, por tanto no es posible asignar valores a elementos salteados. Veamos como ejemplo la declaracin del arreglo unidimensional lista (Figura 5.4) planteado para las calificaciones del problema1. Inicializando sus elementos en la declaracin queda como: int lista[10] = {9,10,8,5,9,6,7,9,4,8}; En el caso de los arreglos bidimensionales la sintaxis es la siguiente: <tipo><nombre>[<tamao1>][<tamao2>]={ {<valor00>,<valor01>,,<valor0(TAM21)>}, {<valro10>,<valor11>,,<valor1(TAM21-1)>},, {<valor(TAM1-1)0>,<valor (TAM2-1)1>,,<elem (TAM1-1)(TAM2-1)>} }; Veamos ahora como queda la declaracin del arreglo bidimensional tabla mostrado en la Figura I.5, inicializando su valores: int tabla[5][3]={{9,10,8},{5,9,6},{7,9,4},{8,9,6},{7,9,4}}; Aunque tambin es posible declararlo de la siguiente forma: int tabla[5][3]={9,10,8,5,9,6,7,9,4,8,9,6,7,9,4}; Esta es debido a que como ya se dijo antes un arreglo bidimensional se pude ver como un arreglo de arreglos.

Fundamentos de programacin
Programa Desarrollado
Por otro lado, en lenguaje C siempre es necesario especificar el tamao del arreglo al momento de declararlo, sin embargo esto se puede hacer de forma explcita o implcita. Explcitamente es cuando se especifica el tamao dentro de los corchetes que siguen al identificador, como en los ejemplos anteriores. De forma implcita se hace cuando el arreglo es inicializado con un conjunto de valores, y se omite el tamao dentro de los corchetes, entonces el compilador asume el tamao del arreglo igual al tamao del conjunto de valores iniciales, de tal forma que la declaracin del arreglo lista puede quedar como: int lista[] = {9,10,8,5,9,6,7,9,4,8}; Observa que en este caso no se escribe el tamao dentro de los corchetes, pero como hay 10 elementos en el conjunto de valores iniciales, el compilador de C asume un tamao 10 para el arreglo. Para los arreglos bidimensionales, slo es posible especificar una dimensin de forma implcita, el tamao de renglones siempre debe hacerse de forma explcita. La asignacin de un conjunto de valores al arreglo, en una sola operacin de asignacin, nicamente es posible en su declaracin, si se intenta realizar en otro momento el compilador marcar un error, ya que en cualquier otra parte del programa slo se podrn asignar valores simples a cada uno de los elementos por separado. Es importante sealar que cuando se desea inicializar el arreglo al declararlo, es posible inicializar slo algunos de sus elementos, pero en este caso se tendra que especificar explcitamente el tamao, adems se debe recordar que la asignacin de valores iniciales es consecutiva desde el elemento 0. Los elementos para los cuales no se indique un valor inicial, automticamente se inicializan en cero. Por ejemplo la declaracin int lista[10] = {5}; Reservar espacio en memoria para los 10 elementos del arreglo de los cuales al primer elemento se le asignar un 5 y al resto se les asignar un cero. En el caso de los arreglos bidimensionales es posible declara slo algunos elementos por rengln, siempre y cuando los elementos sean consecutivos, como en el caso de los unidimensionales. Por ejemplo la siguiente declaracin para el arreglo tabla: int tabla[5][3]={{9,10},{5},{7,9,4},{8,9,}};

Fundamentos de programacin
ograma Desarrollado
Dara como resultado la siguiente asignacin de valores iniciales [0] [0] 9 [1] 5 [2] 7 [3] 8 [4] 0 En el caso de que la declaracin fuera: int tabla[5][3]={9,10,5,7,9,4,8,9,}; Entonces la asignacin de valores iniciales se hara de la siguiente forma [0] [1] [0] 9 [1] 7 [2] 8 [3] 0 [4] 0 [1] 10 0 9 9 0

10 9 9 0 0

5.1.3. Acceso a los elementos de un arreglo Para referirse a un elemento del arreglo es necesario indicar el nombre del arreglo seguido del ndice o ndices correspondientes al elemento que deseamos acceder. Para ello se debe seguir la siguiente sintaxis. Elementos de un arreglo unidimensional: <nombre del arreglo>[<ndice>]; Elementos de un arreglo bidimensional: <nombre del arreglo>[<ndice de rengln>][<ndice de columna>]; Observa que para cada ndice se utilizan corchetes separados. Cada elemento del arreglo se puede tratar igual que a cualquier otra variable, es decir, podemos asignarle un valor, incluir en una expresin algebraica o lgica, imprimir en pantalla su valor, asignarle desde el teclado un valor, etc.

Fundamentos de programacin
Programa Desarrollado
veamos algunos ejemplos: Instruccin tabla[0][2] = 8; printf(%d,lista[4]); scanf(%d,&tabla[0][0]); lista[1]++;

Asignar el valor de 8 al tercer elemento del primer rengln de arreglo tabla Imprimir en pantalla el quinto elemento del arreglo lista Lee un entero desde teclado y asignarlo en la primera posicin del arreglo tabla. Incrementar en uno el valor del segundo elemento del arreglo lista

5.1.4. Ciclos y arreglos Los arreglos y los ciclos estn estrechamente relacionados, podramos afirmar que en cualquier programa que se emplee un arreglo ste ser manipulado por medio de una estructura repetitiva. Anteriormente mencionamos que un arreglo se utiliza cuando queremos almacenar y manipular datos relacionados entre s y, generalmente, cuando tenemos un arreglo debemos ejecutar el mismo conjunto de operaciones sobre cada uno de sus elementos. En lenguaje C el ndice del elemento se puede especificar mediante una expresin, es decir una variable, una constante o como el resultado de una operacin, lo que hace posible ir cambiando el ndice de un elemento dentro de un ciclo sin tener que escribir una serie de instrucciones secuenciales para realizar la misma operacin sobre cada uno de los elementos del arreglo. La forma general de procesar un arreglo unidimensional por medio de un ciclo se muestra en la Figura I.6, observa cmo la variable contador pos del ciclo, tambin se utiliza como ndice para el elemento del arreglo, de tal forma que en cada iteracin se haga referencia a un elemento diferente del arreglo.

Fundamentos de programacin
Programa Desarrollado

Figura I.6Procesamiento de arreglos unidimensionales mediante ciclos No es difcil intuir que para el caso de los arreglos bidimensionales ser necesario no solo un ciclo sino un par de ciclos anidados, ya que tenemos dos dimensiones, cada uno de los ciclos se encargar de variar a un ndice, la estructura general para estos ciclos se muestra en la Figura I.7. Dos ciclos estn anidados cuando est uno dentro de otro, de tal forma que por cada iteracin del externo, el interno completa todo un ciclo. Considerando esto, observa que en la Figura I.7 se toma como contador a la variable i para el ciclo externo, la cual tambin se utiliza como ndice de rengln. Asimismo, se utiliza a la variable j como contador para el ciclo interno, adems de ndice de columna, de esta manera se est recorriendo el arreglo por rengln.

Fundamentos de programacin
Programa Desarrollado

Figura I.7Procesamiento de arreglos bidimensionales mediante ciclos anidados Si analizamos el diagrama de flujo podemos observa que para la primera iteracin del ciclo externo, la variable i tiene el valor de 0 mientras que j toma los valores desde 0 hasta TAMC-1 (TAMC es el nmero total de columnas) de tal forma que el rengln se mantiene fijo mientras nos movemos en todas las columnas, en la siguiente iteracin cambia el rengln ya que i toma el valor de 1 y recorremos nuevamente todas las columnas, este proceso se repite hasta el valor final de i que es TAMF-1 (TAMF es el nmero de renglones).

Fundamentos de programacin
Programa Desarrollado
Ejemplo 5.1: Veamos cmo utilizar arreglos en la solucin de un problema, resolviendo como ejemplo parte del problema 1, enfocndonos nicamente en la lectura de las 10 calificaciones y el clculo del promedio. Para almacenar las calificaciones se puede utilizar un arreglo unidimensional de tipo entero, ser necesario pedir al usuario que ingrese las 10 calificaciones para poder realizar las operaciones necesarias para el clculo del promedio, es decir, la suma de las misma y la divisin entre el total de calificaciones, para finalmente imprimir en pantalla el promedio, adicionalmente se imprimir tambin la lista de calificaciones ingresadas. No existe ninguna restriccin que sea necesaria considerar. Cada uno de los procesos que se van a realizar sobre las calificaciones, es decir leerlas, sumarlas e imprimirlas en pantalla se pueden implementar mediante ciclos, en vez de tener que escribir 10 veces la misma expresin para cada una de las 10 calificaciones. La lectura y la suma de las calificaciones se pueden implementar dentro del mismo ciclo. De esta manera podemos resumir el anlisis del problema de la siguiente forma: Datos de entada: Calificaciones de los 10 estudiantes (calif [ ]) Salida: Promedio de calificaciones (prom) Mtodo: prom =

[]

10

=0

rogramacin
sarrollado
La solucin del problema representada en pseudocdigo se muestra en el siguiente algoritmo. inicio suma 0 Desde i 0 mientras i<10, i i+1 Imprimir Ingresa la calificacin i Leer calif[i] suma suma+calif[i] Fin Desde prom prom/10 Imprimir Las calificaciones ingresadas fueron: Desde i 0 mientras i<10, i i+1 Imprimir Calificacin i : calif[i] Fin Desde Imprimir Calificacin promedio = prom Fin Algoritmo 5.2. Promedio de calificaciones La codificacin del algoritmo anterior es la siguiente: /*Directivas de preprocesador*/ #include <stdio.h> #include <stdlib.h> /* Definimos como constante simblica el tamao del arreglo*/ #define TAM 10 /* Definicin de funcin principal */ main( ) { /*Declaracin del arreglo calificaciones*/ int calif[TAM]; double prom = 0; int i; printf("*** printf(* El siguiente programa calcula el promedio de *\n"); printf(* un grupo de diez estudiantes printf("*** /*Lectura y suma de las calificaciones*/ for(i=0; i < TAM; i++) { printf("Proporciona la calificacin %d: ",i+1); scanf(%d, &calif[i]); prom = prom + calif[i];

Fundamentos de programacin
Programa Desarrollado
} /*Clculo e impresin del promedio*/ prom = prom/TAM; /*Impresin de las calificaciones*/ printf("\nLas calificaciones ingresadas fueron: \n"); for(i=0; i < TAM; i++) printf("\nCalificacion %d: %d",i+1, calif[i]); printf("\n\n\tPromedio system("pause"); } Programa 5.1: promCalificaciones.c En la siguiente figura se muestra una ejecucin del programa. = %.2f\n\n", prom);

Figura 5.8: Ejecucin del programa promCalificaciones.c Observa que el tamao del arreglo se especifica por medio de una constante simblica, utilizando la directiva #define, esto facilita el cambiar el tamao del arreglo sin tener que hacer cambios en todo el cdigo.

Fundamentos de programacin
Programa Desarrollado

Actividad 1. Foro Estructuras de Datos -Ejercicio A Realiza una prueba de escritorio con los datos que se muestran en la ejecucin del programa promCalificaciones.c (figura 5.6) y posteriormente escribe, compila y ejecuta el programa en la computadora. Reflexiona cmo solucionaras el problema si no contaras con los arreglos y qu pasara si en vez de calcular el promedio de 10 calificaciones tuvieras que hacerlo para 50, qu se debera modificar en cada el programa que se present en esta seccin y qu tendras que modificar sino contaras con los arreglos. Ingresa tus conclusiones al Foro Estructuras de Datos A continuacin se presenta otro ejemplo para ilustrar el uso de arreglos bidimensionales. Ejemplo 5.2: Se requiere un programa que calcule el determinante de una matriz de 2x2. Considerando la siguiente informacin. Dada la siguiente matriz:

Su determinante se define como:

=a00a11-a01a10

Anlisis del problema: Para este problema se puede utilizar un arreglo bidimensional de 2 renglones y 2 columnas para almacenar los valores de la matriz, los cuales se pueden solicitar al usuario utilizando la estructura de ciclos anidados presentada en la Figura I.7, nuestro dato de salida ser el valor del determinante y adicionalmente tambin se mostrar en pantalla la matriz ingresada. Datos de entada: Elementos de la matriz (A[ ][ ]) Salida: Valor del determinante (det) Mtodo: 0][1]] = ]0[]0[ ]1[]1[ ]0[]1[ La solucin del problema se da en el siguiente diagrama de flujo.

Fundamentos de programacin
Programa Desarrollado

Algoritmo 5.3: Determinante de una matriz 2x2

Fundamentos de programacin
ProgramDesarrollado
La codificacin del algoritmo se deja como ejercicio al lector, sin embargo, en la siguiente figura se muestra un ejemplo de ejecucin del programa. /* Directivas al preprocesador #include <stdlib.h> #include <stdio.h> */

/* Constantes con el tamao de la matriz */ #define TAM 2 /* Funcin principal */ main() { int i, j; float det; float A[TAM][TAM]; /*declaracin de la matriz*/ /* Mensaje de bienvenida */ printf("*** printf("* Determinante de una matriz A de 2x2 *\n"); printf("*** /* Lectura de la matriz A */ for(i=0; i<TAM; i++) for(j=0; j<TAM; j++){ printf("\nProporciona el elemento A[%d][%d]: ", i,j); scanf("%f", &A[i][j]); } det = A[0][0]*A[1][1] - A[0][1]*A[1][0]; printf("\nA: \n\t"); /* Impresin de la matriz A */ for(i=0; i<TAM; i++){ for(j=0; j<TAM; j++) printf("%8.2f", A[i][j]); printf("\n\t"); } printf("\n\n\t\tDeterminante system("pause"); } Programa 5.2: determinantes.c = %.2f\n\n", det);

Fundamentos de programacin
Programa Desarrollado
En la siguiente figura se muestra una ejecucin del programa.

Figura 5.9: Ejecucin del programa determinante.c Actividad 1. Foro Estructuras de Datos -Ejercicio B Realiza una prueba de escritorio con los datos que se muestran en la ejecucin del programa determinante.c (figura 5.7) y posteriormente escribe, compila y ejecuta el programa en la computadora. Comparte tu experiencia en el Foro. 5.1.5 Cadenas Una cadena es una serie de caracteres tratados como una sola unidad. Una cadena puede incluir letras, dgitos y varios caracteres especiales(Deitel H. M., Deitel P. J., 1995). En algunos lenguajes de programacin existe un tipo de dato especfico para definir a las cadenas, sin embargo, en lenguaje C las cadenas se implementan por medio de arreglos de tipo carcter ya que no existe un tipo especfico para ellas, pero existe todo un conjunto de funciones estndar definidas en la biblioteca string.h mediante las cuales es posible realizar las operaciones ms comunes, por ejemplo: copiarlas, concatenarlas, compararlas, entre otras. Adems es posible imprimirlas y leerlas de forma similar que un dato simple. En lenguaje C toda constaten de tipo cadena se indica entre comillas dobles, por ejemplo: Calle 2 #135

Fundamentos de programacin
Programa Desarrollado
Una cadena en C termina siempre con el carcter nulo \0 (cuyo valor ascii es cero) que representa el fin de cadena. Al declarar arreglos de tipo char que sean una cadena se pueden inicializar directamente con una constante cadena de la siguiente forma: char cad[50]=saludo; Al inicializar una variable cadena de esta manera, se agrega automticamente el smbolo de carcter nulo para indicar el fin de cadena, es decir, en la posicin 6 del arreglo cad se encuentra almacenado el fin de cadena \0. De forma general, es importante sealar que en un arreglo de tamao N es posible almacenar correctamente una cadena de mximo N-1 caracteres. De tal forma que en el arreglo cad se puede almacenar una cadena de mximo 49 caracteres. Las cadenas en C pueden ser asignadas a un arreglo de tipo char utilizando la funcin mediante el especificador de formato %s, por ejemplo la lnea de cdigo: scanf(%s,cad); De esta manera se lee desde el teclado una cadena y se guarda en el arreglo cad, slo que en este caso no se incluye el operador & antes del nombre del arreglo, pues el identificador del arreglo almacena la direccin del primer elemento del mismo. La funcin gets() tambin nos permite leer del teclado una cadena y asignarla a un arreglo de tipo char, por ejemplo la instruccin: gets(cad); Lee una cadena desde el teclado y la almacena en el arreglo cad. Una diferencia importante entre usar scanf y gets es que con la primera la lectura de la cadena se da por terminada cuando el usuario presiona [Enter] o Espacio, mientras que la segunda termina la lectura de la cadena nicamente cuando el usuario presiona [Enter], tal como se muestra en los siguientes ejemplos: Cadena ingresada Instruccin Contenido del arreglo cad[] Calle 2 #135 scanf(%s,c cad[]: ad); C a l l e / / 0 0 Calle 2 #135 gets(cad); cad[]: C a l l e 2 # scanf

Prorrollado

programacin
similarmente, para imprimir en pantalla una cadena se puede utilizar la funcin printf con el especificador de formato %s, o bien, la funcin puts, nuevamente ambas funciones tienen un comportamiento similar con la nica diferencia de que puts incluye siempre un salto de lnea al final, esto se ilustra a continuacin. Cdigo c Impresin de cadena con printf
#include <stdio.h> #include <stdlib.h> main(){ char mensaje[30]=Mar profundo ; printf(%s,mensaje); system(pause); }

Ejecucin

Impresin de cadena con puts


#include <stdio.h> #include <stdlib.h> main(){ char mensaje[30]=Mar profundo ; puts(mensaje); system(pause); }

Las funciones que nos permiten el manejo de cadenas se encuentran string.h, para ilustrar algunas se muestra el siguiente programa en C. Ejemplo 5.3: El programa siguiente verifica si una clave (password) de 8 caracteres alfanumricos ingresado por el usuario es correcta. /*Directivas de preprocesador*/ #include <stdio.h> #include <stdlib.h> #include <string.h> /* se incluye la biblioteca de cadenas */ main( ) { /* Declaracin de variables */ char pwscorrecto[9]=jk278la0;

/* Clave correcta */

Fundamentos de programacin
Programa Desarrollado
char pwsingresado[9]; /* para leer la clave que ingrese el usuario */ char nombre[10]; /* Para leer el nombre del usuario */ char mensaje[50]=Bienvenido ; /* Lectura de datos */ printf(Nombre: "); gets(nombre); /* Lectura de una cadena con espacios */ printf(pasword: "); scanf(%s,pwsingresado); /* Lectura de una cadena sin espacios*/ if (!strcmp(pwscorrecto,pwsingresado)){ /* comparacin de claves, si la funcin strmp regresa 0 son i iguales */ printf(pasword correcto \n); strcat(mensaje,nombre); /* pega al final de mensaje el nombre del usuario*/ puts(mensaje); /* impresin de la cadena con salto de lnea*/ } else { strcpy(mensaje, Acceso denegado); /* copia la cadena acceso denegado al mensaje */ puts(mensaje); /* imprime la cadena*/ } system("pause"); } Programa 5.3: password.c En la siguiente figura se muestran dos ejecuciones del programa a) Clave invlida

Figura 5.10: Ejecucin del programa password.c (Fuente: elaboracin propia utilizando DevC++) Con esto se concluye la seccin de arreglos, recuerda que un arreglo es un conjunto de dato del mismo tipo. En la siguiente seccin vers cmo puedes agrupar datos de diferente tipo.

Fundamentos de programacin
Programa Desarrollado
5.2. Estructuras Las estructuras en C al igual que los arreglos nos permiten tratar a un conjunto de datos bajo un mismo identificador pero a diferencia de los arreglos las estructuras son conjuntos de datos contiguos en memoriano homogneos de tal forma que una estructura puede estar formada por datos de diferentes tipos. Una de las aplicaciones para las estructuras es para la manipulacin de registros que se recuperan o se almacenan en una base de datos. 5.2. Definicin, declaracin e inicializacin Una estructura es una coleccin de una o ms variables, de tipos posiblemente diferentes, agrupadas bajo un nombre para manejo conveniente (en algunos lenguajes tambin se conocen como registros). Las estructuras permiten tratar a un grupo de variables relacionadas como una unidad, en vez de que se traten en forma separada (Kernighan & Ritchie, 1991, pg. 141). La definicin de una estructura en C inicia con la palabra reservada struct seguida del identificador para el tipo de estructura y de un bloque de definiciones de variable que constituyen el conjunto de elementos que forman parte de ella, la sintaxis para definir la estructura es la siguiente: struct<identificadorEstructura>{ <tipo1><identificadorE1>; <tipo2><identificadorE2>; <tipoN><identificadorEN>; } Observa que se utiliza la palabra reservada struct para iniciar la definicin y que las declaraciones para los elementos de la estructura se encierran entre llaves. Una estructura puede contener a N elementos de diferentes tipos, de cualquiera de los tipos bsicos, o incluso un arreglo, veamos un ejemplo: struct paciente { int nss; /* nmero de seguro social */ char apellido[50]; char nombre[20]; int edad; float estatura; char sexo; }

Fundamentos de programacin
Programa Desarrollado
En este ejemplo se est definiendo la estructura paciente que tiene seis elementos: dos enteros (nss y edad), dos cadenas (apellido y nombre), un flotante (estatura) y un carcter (sexo). Sin embargo la definicin anterior no reserva espacio en memoria para la estructura, ms bien define un tipo de dato, por lo tanto para poder utilizar la estructura, es necesario declarar una variable de este tipo, es aqu cuando se reserva espacio en memoria. La sintaxis para hacer esta declaracin es la siguiente: struct<identificadorEstructura><identificador_var>; Por ejemplo la declaracin: struct paciente paciente1, paciente2; Declara a las variables paciente1 y paciente2, las cuales son del tipo paciente y por tanto para cada una de ellas se reserva espacio en memoria suficiente para cada uno de sus seis elementos. Otra forma vlida de hacer la declaracin es hacindola seguida a la definicin de la estructura, para el ejemplo anterior puede escribirse como sigue: struct paciente { int nss; char apellido[50]; char nombre[20]; int edad; float estatura; char sexo; } paciente1, paciente2; En este caso el identificador para el tipo de estructura puede omitirse, pero entonces la nica forma de declarar variables para ese tipo de estructura es en su definicin, y no en una declaracin por separado, de tal forma que nuestro ejemplo puede quedar como sigue: struct { int nss; char apellido[50]; char nombre[20]; int edad; float estatura; char sexo; } paciente1, paciente2; Por otro lado, al igual que los arreglos, tambin se pueden inicializar los elementos de una estructura en el momento de la declaracin de una variable del tipo de la estructura en cuestin, stos deben estar encerrados entre llaves y separados por comas. La sintaxis general es la siguiente:

Fundamentos de programacin
Prog Desarrollado
struct<identificadorEstructura><identificador_var> = { <valorE1>,<valor2>, ,<valorN> }; Por ejemplo : struct paciente paciente1 = {1240, PicaPiedra, Pedro, 45, 1.80, M}; Slo en el momento de la declaracin es posible asignar todos los valores de una estructura (al igual que con los arreglos), as que si despus se quiere modificar tendrn que hacerse las modificaciones de forma separada en cada uno de sus elementos, como se muestra en el siguiente subtema. Actividad 2. Arreglos y estructuras. Retoma el programa que has trabajado para las evidencias de aprendizaje anteriores y realiza una versin preliminar del mismo pero ahora incorporando lo que has aprendido en esta unidad. Tu facilitador(a) te orientar si tienes dudas. Con esta actividad podrs prepararte para la entrega de tu evidencia de aprendizaje de la unidad. 5.2.2. Acceso a sus elementos Para referenciar un elemento de la estructura se utiliza el operador punto . con la siguiente sintaxis: <idenficador_var>.<idenficadorEi> Este operador seguido del identificador del elemento, referencia el elemento indicado, de tal forma que la sentencia para asignar al paciente1 un nss de 23442145 ser: paciente1.nss = 23442145; Ahora, si se quiere asignar a la misma variable el nombre Pablo, la instruccin sera: paciente1.nombre = Pablo; Del mismo modo se realiza la impresin o lectura del elemento de la estructura, sin perder de vista su tipo. Para ilustrar esto se propone el siguiente ejemplo. Ejemplo 5.4: En el siguiente programa se declara una estructura de tipo perro, que tiene los siguientes elementos: Elemento Tipo Raza char[] Edad int Peso float

Fundamentos de programacin
Proama Desarrollado
Posteriormente se declaran dos variables de ste tipo, una se inicializa en la declaracin y a la otra se le asignan valores desde el teclado, ambos se muestran al final en pantalla. #include <stdio.h> #include <stdlib.h> #include <conio.h> main(){ /* Declaracin de la estructura perro*/ struct perro{ char raza[20]; int edad; float peso; } fido, pluto = {"labrador", 7, 20} ; /* inicializacin de la variable pluto*/ printf("*** **"); printf("\n* Comparando perros *"); printf("\n*** **"); printf("\n\nIngresa la raza de fido:"); scanf("%s",&fido.raza); /* lectura de un elemento */ printf("Ingresa la edad de fido en a%cos:", 164); scanf("%d",&fido.edad); /* lectura de un elemento */ printf("Ingresa el peso de fido en kilos de fido:"); scanf("%f",&fido.peso); /* lectura de un elemento */ /* impresin de los elementos de las estructuras */ printf("\nFido es de raza %s, tiene %d a%cos kilos\n",fido.raza,fido.edad,164,fido.peso); printf("\nPluto es de raza %s, tiene %d a%cos kilos\n",pluto.raza,pluto.edad,164,pluto.peso); /* comparacin de los nombres que son cadenas */ if(!strcmp(pluto.raza,fido.raza)) printf("\nPluto Y Fido son de la misma raza \n"); else printf("\nFido y Pluto son de razas distintas\n"); /* comparacin de elementos de tipo numrico */ if(pluto.peso > fido.peso)

y y

Fundamentos de programacin
Programa Desarrollado
printf("Pluto es m%cs pesado que Fido\n",160); else if(pluto.peso < fido.peso) printf("Fido es m%cs pesado que Pluto\n",160); else printf("Fido y Pluto pesan lo mismo\n"); if(pluto.edad > fido.edad) printf("Pluto es mas viejo que Fido\n"); else if(pluto.edad < fido.edad) printf("Fido es mas pesado que Pluto\n"); else printf("Fido y Pluto tienen la misma edad \n"); getch(); } Programa 5.4: perros.c Nota: Observa que en este caso, para poder imprimir la letra se utiliz su cdigo Ascii cual en la cadena de control del printf se escribi %c en donde se desea imprimir la . Este mismo truco se hizo para acentuar la letra a. En la siguiente figura se muestra una ejecucin del programa anterior.

Figura 5.11: Ejecucin del programa perros.c Actividad 1. Foro Estructuras de Datos -Ejercicio C Escribe, compila y ejecuta en la computadora el programa perros.c. Posteriormente, analiza cules son las principales diferencia entre las estructuras y los arreglos e ingresa tus comentarios en el Foro Estructuras de Datos.

Fundamentos de programacin
Programa Desarrollado
Para concluir con este captulo veamos el siguiente ejemplo donde se utilizan estructuras y arreglos: Ejemplo 5.5:Se requiere un programa que permita registrar los datos de los perros que ingresan a refugio para perros, y poder desplegar los datos de alguno de los perros, a cada perro se le asigna una clave numrica consecutiva. Los datos que se registran del perro son: la fecha de ingreso (cadena) nombre (cadena) raza (cadena) color (cadena) edad (entero) peso (flotante) El refugio tiene capacidad mxima para 100 perros. Para la solucin del problema se puede plantear un men que permita registrar a un perro, o bien, desplegar los datos del perro solicitados. En este caso tenemos como datos de entrada la opcin del men que elija el usuario. En el caso de que sea un registro tendremos tambin se tienen como datos de entrada los datos del perro. Para la opcin de despliegue se tendr que dar como datos de entrada la clave del perro y la salida sern los datos correspondientes a la clave. Para desplegar y repetir el men se requiere un ciclo y una estructura condicional que maneje las opciones del men. Para almacenar los datos del perro, se puede utilizar una estructura similar al ejemplo anterior. Mediante un arreglo de estas estructuras estaremos en capacidad para manipular los datos de varios perros, el tamao de este arreglo tendr que ser igual a la capacidad del refugio (100 perros), de tal forma que el ndice del arreglo que toca a cada perro corresponder con su clave. Una restriccin que hay que tomar en cuenta es que se debe verificar que no se sobre pase la capacidad de los 100 peros, tanto al ingresar datos como al recuperarlos, para ello se llevar un contador (c) que actualice el nmero de perros ingresados. Inicio c 0 Hacer Imprimir Refugio para perros -Ladrido Feliz- Imprimir 1) Registrar un perro Imprimir 2) Buscar un perro Imprimir 3) Salir Imprimir Elige una opcin: Leer op Casos para op Caso 1: Si c100 entonces

Fundamentos de programacin
Programa Desarrollado
Imprimir El refugio est lleno Si no Imprimir Ingresa los datos del perro: Imprimir Clave: c Imprimir fecha de ingreso[dd/mm/aa]: Leer perros[c].fecha Imprimir color: Leer perros[c].color Imprimir nombre: Leer perros[c].nombre Imprimir raza: Leer perros[c].raza Imprimir edad: Leer perros[c].edad Imprimir peso: Leer perros[c].peso c c+1 Fin si-si no Caso2: Imprimir Clave: Leer clave Mientras clave100 v clave <0 hacer Imprimir La calve no es vlida, ingresa nuevamente la clave: Leer clave Fin mientras Imprimir nombre:, perros[clave].nombre Imprimir fecha de ingreso:, perros[clave].fecha Imprimir color: , perros[clave].color Imprimir raza: , perros[clave].raza Imprimir edad: , perros[clave].edad Imprimir peso: , perros[clave].peso Caso 3: Otro caso: Imprimir Opcin no vlida Fin casos Mientras op3 Fin Hacer-mientras Fin Algoritmo 5.3. Registro perros

Fundamentos de programacin
Programa Desarrollado
La prueba de escritorio se deja como ejercicio al lector. En cuanto a la codificacin del algoritmo se muestra a continuacin.
#include <stdio.h> #include <stdlib.h> #include <conio.h> main(){ /* Declaracin del arreglo de tipo estructura perro */ struct perro{ char fecha[10]; char raza[30]; char color[50]; char nombre[30]; int edad; float peso; } perros[100]; int c=0, op, clave; do{ /* Inicio del ciclo que imprime el men*/ printf( "\n----------------------------------------\n"); printf( "\nRefugio para perros -Ladrido Feliz- \n" ); printf( "\n----------------------------------------\n"); printf( "1) Registrar un perro \n" ); printf( "2) Buscar un perro \n" ); printf( "3) Salir \n" ); printf( "Elige una opci%cn:",162 ); scanf("%d",&op); switch (op){ case 1: /*Opcin Registrar perro */ printf( "\n------------------------------\n"); if(c>=100) /* Verifica si hay espacio */ printf("El refugio esta lleno\n"); else{ /*Si hay espacio pide los datos del perro y Y los guarda en el registro c del arreglo */ printf( "Ingresa los datos del perro:"); printf( "Clave:%.3d\n", c); printf( "fecha de ingreso[dd/mm/aa]: "); scanf( "%s", perros[c].fecha); printf( "nombre: "); fflush(stdin); gets( perros[c].nombre); printf( "color: ");

Fundamentos de programacin
Programa Desarrollado
gets( perros[c].color); printf( "raza: "); gets( perros[c].raza); printf( "edad: "); scanf("%d" ,&perros[c].edad); printf( "peso: "); scanf("%f" ,&perros[c].peso); c++; } break; case 2: /* Opcin buscar perro */ printf( "\n-------------------------------\n"); printf( "Clave: "); scanf("%d",&clave); /* verifica que la clave sea vlida */ while(clave>=100 || clave <0){ printf("La calve no es vlida, ingresa nuevamente la clave:"); scanf("%d",&clave); } /* Imprime los datos del perro correspondiente a la clave */ printf("nombre:%s\n",perros[clave].nombre); printf( "fecha de ingreso: %s\n", perros[clave].fecha); printf( "color: %s\n", perros[clave].color); printf( "raza: %s\n", perros[clave].raza); printf( "edad: %d a%cos\n", perros[clave]edad,164); printf( "peso: %.2f kilos\n", perros[clave].peso); break; case 3: /* Caso salir, no hace nada */ break; default: /* Caso opcin invlida */ printf( "Opcion no valida\n"); } }while (op!=3); /* El ciclo do-while se repite mientras la opcin no sea salir (3) */ }

Programa 5.5: registroPerros.c

Fundamentos de programacin
Programa Desarrollado
Evidencia de aprendizaje. Programa en C. Avance de solucin del problema implementando las estructuras de datos Con ayuda de tu facilitador debers acotar el problema que describiste en la evidencia de la unidad 1, de tal manera que la solucin involucre a las estructuras de datos vistas en esta unidad. Para conocer los detalles de la actividad, ingresa al aula virtual. Consideraciones especficas de la unidad Para alcanzar los objetivos de esta unidad te recomendamos que escribas y compiles los programas que se desarrollaron a lo largo de la misma y realices una prueba de escritorio de cada uno de ellos, tal como se sugiere en las actividades opcionales. Referencias: Cairo Osvaldo, Guardati Buemo Silvia. (1993). Estructura de Datos. Mxico: McGraw-Hill. Deitel H. M., Deitel P. J. (1995). Cmo programar en C/C++. Mxico: Prentice Hall. Joyanes, L., & Zohanero, I. (2005). Programacin en C. Metodologa, algoritmos y estructuras de datos. aspao: Mc Graw Hill. (1991). El lenguaje de programcin C. Mxico: Prentice-Hall

Kernighan, B., & Ritchie, D. Hispanoamericana.

Lpez, L. (2005). Programacin estructurada en lenguaje C. Mxico: Alfaomega.

Fundamentos de programacin
Prrama Desarrollado
Propsitos En esta unidad: Identificars los sub-problemas en que puede dividirse un problema. Disears algoritmos modulares para solucionar un problema Construirs funciones en lenguaje C que realicen tareas especficas Competencia especfica Implementar funciones para resolver problemas a travs del desarrollo de programas modulares escritos en lenguaje C. Introduccin Hasta esta etapa del curso, has aprendido a utilizar las estructuras de control para disear soluciones de problemas simples. Tambin has conocido diferentes formas de representar los datos involucrados en un problema, desde simples hasta estructurados (como arreglos, cadenas y estructuras). Sin embargo, todas las soluciones propuestas constan nicamente de un mdulo (funcin), llamado principal (en C, main); lo cual no es conveniente cuando se trata de problemas complejos que requieran de una serie de tareas para lograr su solucin, pues sta sera muy grande y, por lo tanto, difcil de corregir o modificar. En estos casos lo recomendable es crear mdulos independientes que realicen cada una de las tareas especficas y que en conjunto implementen la solucin del problema. A esta metodologa se le llama diseo modular, y est inspirado en la estrategia divide y vencers. En esta unidad se explicarn las funciones, que son el medio por el cual se implementan los mdulos en lenguaje C. Se presentar la sintaxis para crear una funcin y la forma en la que se utilizan. Adems, se resolver un problema utilizando el diseo modular para ejemplificar el tema. 6.1. Diseo descendente La descomposicin de un programa en mdulos ms pequeos se conoce como el mtodo de divide y vencers (divide and conquer) o diseo descendente (top-down). Consiste en dividir un problema en unidades ms pequeas sucesivas hasta que sean directamente ejecutadas por el procesador, en otras palabras, la solucin del problema se divide una y otra vez hasta que est expresada en trminos de estructuras de control, cada uno de los niveles o pasos sucesivos se conoce como refinamiento (stepwise). La metodologa del diseo descendente consiste en efectuar una relacin entre las etapas de estructuracin de manera que se relacionen entre s a travs de entradas y salidas de datos. Es decir, dad 6: Funciones

Fundamentos de programacin
Proama Desarrollado
se descompone el problema en etapas de estructuracin jerrquicas, de forma que se pueda considerar cada estructura desde dos puntos de vista: qu hace? y cmo lo hace? Con lo anterior podemos decir que: un mdulo se caracteriza por realizar una tarea especfica, posee sus propios datos de entrada - llamados parmetros de entrada - y su resultado - llamado salida o valor de retorno -. El diseo de cada mdulo debe ser independiente de los otros; si es necesario que exista comunicacin entre ellos, sta nicamente podr realizarse a travs de los parmetros de entrada y del valor de retorno. En este sentido, puede ser visto, por otros mdulos, como una caja negra que hacia el exterior slo muestra qu hace y qu necesita, pero no cmo lo hace. La creacin de un modulo conlleva dos partes: la definicin del mdulo y la llamada o invocacin (ejecucin). La primera consta de tres partes: Definir los parmetros de entrada; Definir el valor de retorno; Escribir todas las instrucciones que le permitirn llevar a cabo la tarea, es decir, un algoritmo. La llamada o invocacin a un mdulo es el proceso de ejecutar el conjunto de instrucciones definidas en el mdulo dado un conjunto de entradas especfico. La forma general de invocar un mdulo es escribiendo su nombre y entre parntesis los valores de cada uno de los parmetros de entrada, respetando el orden que con el que se defini. No existe un mtodo para saber en cunto mdulos se debe dividir un problema, sin embargo es importante tener en cuenta los siguientes principios del diseo modular: Las partes altamente relacionadas deben pertenecer a un mismo mdulo. Las partes no relacionadas deben residir en mdulos diferentes. Para ejemplificar esta forma de resolver problemas y cmo implementarla, se presenta la siguiente situacin: Problema 6.1: Realiza el anlisis y diseo de un programa que lea las temperaturas promedio mensuales registradas en una ciudad a lo largo de un ao y calcule el promedio anual. Adems, debe convertir las temperaturas mensuales dadas en grados Celsius a grados Fahrenheit al igual que el promedio. Empecemos por hacer un bosquejo de los pasos que se tienen que realizar para llegar al resultado deseado. 1. Leer las doce temperaturas promedio mensuales 2. Calcular el promedio anual de las temperaturas 3. Convertir las temperaturas promedio mensuales de Celsius a Fahrenheit 4. Convertir el promedio anual de temperaturas a Fahrenheit 5. Imprimir las temperaturas mensuales en grados Fahrenheit y el promedio anual de las temperaturas, en Celsius y Fahrenheit.

Fundamentos de programacin
Programa Desarrollado
Para registrar las temperaturas mensuales proponemos utilizar un arreglo de tamao 12. Y de acuerdo con lo anterior, proponemos tres mdulos: El primero encargado de leer las temperaturas mensuales dadas en grados Celsius, este mdulo necesita el nombre del arreglo donde va a almacenar los datos. Otro mdulo encargado de calcular el promedio de las temperaturas, que recibe como parmetros de entrada el arreglo con las temperaturas mensuales y devuelve el promedio en grados Celsius. El ltimo mdulo slo convierte grados Celsius a grados Fahrenheit. Esta informacin se resume en el diagrama modular que se muestra a continuacin.

Figura 6.12: Diagrama modular del problema 6.1 Es mediante un diagrama modular como se representan de manera grfica los mdulos que integran la solucin del problema. Y una vez que se han definido, el siguiente paso es disear el algoritmo de cada uno de ellos. En primer lugar se muestra el pseudocdigo de los mdulos secundarios.

Fundamentos de programacin
Programa Desarrollado

Mdulo leerTemps(temp[ ]) Inicio Desde mes 1 mientras mes 12, mes mes + 1 Imprimir Proporciona la temperatura del mes, mes Leer temps[mes-1] Fin_Desde Fin

Algoritmo 6.4: Algoritmo del mdulo leerTemps(temp[]) Observa que el ciclo del mdulo leeTemps se inicia con mes igual a 1 y termina cuando mes es 13, se propone as porque se pide la temperatura de los mes 1, 2, 3,.. 12, as que la variable mes guardara el nmero de mes correspondiente a cada lectura, sin embargo para almacenar la temperatura en la posicin del arreglo indicada se resta uno (temps[mes-1]), as se guarda desde la posicin 0 y hasta la posicin 11.

Fundamentos de programacin
Programa Desarrollado

Mdulo promTemps(temp[]) Inicio suma 0 Desde mes 0 mientras mes 11, mes mes + 1 suma suma + temps[mes] Fin_Desde Regresa (suma/12) Fin

Algoritmo 6.2: Algoritmo del mdulo promTemps(temp[]) En contraste con el ciclo del mdulo leerTemp, en este mdulo el contador del ciclo se inicia en 0 y termina en 11 (aunque el valor que tiene al finalizar el ciclo es 12) pues se utiliza para ir sumando cada uno de los elementos del arreglo, as que la variable mes indicar cada una de las posiciones del arreglo. Mdulo aFahrenheit(tempC) Inicio tempF = 9 5 tempC + 32 Regresa tempF Fin

Algoritmo 6.2: Algoritmos de mdulos secundarios del problema 6.1 (pseudocdigo)

Fundamentos de programacin
Programa Desarrollado
A partir de los mdulos secundarios presentados se puede plantear el mdulo principal. Mdulo Principal Inicio /* Lectura de las temperaturas, invocando al mdulo leerTemps */ Imprimir Ingresa los promedios de temperaturas mensuales leerTemps(temps[]) /* Clculo del promedio utilizando el mdulo promTemps */ promC promTemps(temps[]) /* Conversin del promedio a grados Fahrenheit, invocando al mdulo aFahrenheit */ promF aFahrenheit(promC) /* Conversin de las temperaturas mensuales a grados Fahrenheit */ Desde mes 0 mientras mes 11, mes mes + 1 tempsF[mes] aFahrenheit(temps[mes]) Fin_Desde /* Impresin de temperaturas mensuales en Fahrenheit */ Desde mes 1 mientras mes 12, mes mes + 1 Imprimir Temperatura en Fahrenheit del mes, mes, es: , tempF[mes-1] Fin_Desde /* Impresin del promedio en grados Celsius y grados Fahrenheit */ Imprimir El promedio en grados Celsius es: , promC Imprimir El promedio en grados Fahrenheit es: , promF Fin Algoritmo 6.4: Algoritmo del mdulo principal del problema 6.1 (pseudocdigo) Por esta ocasin se deja como ejercicio al lector que realice las representaciones en diagrama de flujo del mdulo principal, considerando que el smbolo que se utiliza para llamar a mdulos que no devuelven ningn valor, como es el caso se leerTemps se muestra a continuacin:
leerTemps(temp[])

Esto no es caso, del resto de los mdulos secundarios que s devuelven un valor, as que se utiliza el smbolo de proceso (rectngulo). Con el ejemplo anterior resaltan indudablemente varias ventajas que proporciona un diseo modular: 1. Es posible reutilizar cdigo, sta indudablemente es una de las ms importantes ya que no es necesario escribir el mismo cdigo cada vez que deseamos realizar una tarea semejante. Por

Fundamentos de programacin
Programa Desarrollado
ejemplo, el mdulo aFahrenheit se utiliza 13 veces (12 en el ciclo y una para convertir el promedio) y slo basto definirlo una vez. 2. Fcil deteccin y correccin de errores, dado que el problema fue divido en pequeos mdulos cada uno responsable de una tarea, si en algn momento existiera un error en la solucin global, basta identificar cul de las tareas es la que no se est resolviendo adecuadamente y corregir nicamente aquellos mdulos involucrados. 3. Fcil modificacin o extensin, si se requiere modificar una tarea del problema o agregar una nueva, no ser necesario redisear todo el algoritmo, basta con hacer las modificaciones en los mdulos pertinente. 4. Un problema se vuelva ms sencillo de solucionar si pensamos de manera modular. Una vez que se ha ilustrado como realizar una solucin modular, lo siguiente es explicar cmo se codifica cada uno de los mdulos, tema que se abordar en las siguientes secciones. } Actividad 1. Foro Funciones En esta actividad reflexionars sobre las ventajas del diseo descendente y las funciones en Lenguaje C a partir de la solucin modular del problema que planteaste en las unidades anteriores. Conforme avances en el diseo modular del mismo ingresa tus comentarios al respecto en el Foro Funciones. 6.2. Definicin, declaracin e invocacin de funciones en C En el caso particular de C, un mdulo se implementa como una funcin, recuerda que en la unidad 3 se explico que un programa en C est integrado de varias funciones, donde una funcin se define como una porcin de cdigo (un conjunto de instrucciones agrupadas por separado) enfocado a realizar una tarea en especfico, resaltando la funcin principal main. Al igual que la funcin principal, cada una de las funciones existe de manera independiente, tiene sus propias variables, instrucciones y un nombre que las distingue de las otras. Adems de los parmetros de entrada (tambin llamados argumentos) que recibe y el tipo de dato que regresa. La forma general para definir una funcin es: <tipo entrada>) { de dato retorno><identificador de la funcin>( <parmetros de

<instrucciones de la funcin> return<expresin>; }

Fundamentos de programacin
Programa Desarrollado
El <tipo de dato retorno> indica el tipo de dato que la funcin devuelve (puede ser cualquiera de los tipos bsicos), para lo cual se utiliza la palabra reservada return . Cuando la funcin no va a devolver ningn dato se especifica mediante el tipo void y no debe incluir la palabra reservada return. El <identificador de la funcin> es el nombre que le vamos a dar a la funcin y mediante el cual vamos a hacer referencia a ella. Se deben seguir las mismas reglas que los identificadores de las variables y se recomienda que sea nemnicos. Enseguida del nombre y entre parntesis va la lista de parmetros, que consiste de una lista de declaraciones de variables locales que van a contener los datos de entrada para la funcin, se debe especificar explcitamente el tipo y nombre para cada uno, separados por comas, an cuando sean del mismo tipo: tipo1 param1, tipo2 param2,, tipoN paramN. Por ltimo, las instrucciones del cuerpo de la funcin van entre llaves. La primera lnea de la definicin de una funcin se conoce como encabezado de la funcin (en ingls header). Para ilustrar esto, a continuacin se muestra la codificacin del mdulo aFahrenheit definido en la seccin anterior.

float aFahrenheit(float tempC) { return ((9.0/5.0)*tempC+32); } Programa 6.1: Codificacin del mdulo aFahrenheit La llamada o invocacin a una funcin se realiza cuando se requiere que se ejecuten las instrucciones del cuerpo con valores de entrada determinados. Para invocar a una funcin se tiene que escribir el nombre seguido de los valores que deben coincidir con el orden, nmero y tipo de los parmetros de entrada dados en la definicin de la funcin y deben estar encerrados entre parntesis. La sintaxis general para invocar una funcin ya sea predefinida o definida por el programador, es la siguiente:

<identificador de la funcin>( <lista de valores>);

Los parmetros de entrada de una funcin son valores, por lo que pueden estar determinados por: valores constantes (8,a, 5.2, cadena constante) o una variable (lo que realmente se pasa a la funcin

Fundamentos de programacin
Programa Desarrollado
es el valor almacenado) o una expresin (el parmetro de entrada real es el resultado de la evaluacin). Por ejemplo, la llamada a la funcin que definimos se remarcar en la siguiente instruccin: promF = aFahrenheit(promC);

Al igual que las variables una funcin debe de ser declarada antes de utilizarse, es decir, antes de invocarla. La declaracin de una funcin se realiza escribiendo el prototipo de la funcin. El prototipo de una funcin coincide con el encabezado de la misma terminando con punto y como (;) El prototipo de una funcin slo indica al compilador que existe y cmo es, ms no lo que hace por lo tanto se debe definir despus. Por ejemplo, el prototipo de la funcin antes definida sera: float aFahrenheit(float tempC); Cabe sealar que en el prototipo de las funciones se puede omitir los identificadores de los parmetros, ms no los tipos. Para ilustrar todo lo anterior, a continuacin se muestra la codificacin del algoritmo modular diseado en la seccin anterior. /* Programa: promedioTemp.c * Descripcin: Calcula el promedio de las temperaturas promedio * mensuales registrada a lo largo de un ao*/ /* Biblioteca */ #include<stdio.h> #include<stdlib.h> /* Variables globales */ int meses = 12; /* Prototipos de las funciones */ /* Funcin que lee las temperaturas un ao*/ void leerTemps( float temps[]);

promedio

mensuales

registradas en

/* Funcin que calcula el promedio de las temperaturas promedio mensuales registradas en un ao*/ float promTemps( float temps[]); /* Funcin que convierte de grados Celsius a grados Fahrenheit */

Fundamentos de programacin
Program Desarrollado
float aFahrenheit(float tempC); /* Funcin principal */ main() { /* Declaracin de variables locales a main */ float temps[12], tempsF[12], promF, promC; int mes; /* Lectura de las temperaturas, invocando a leerTemps*/ printf(Ingresa los promedios de temperaturas mensuales\n); leerTemps(temps); /* Clculo del promedio utilizando la funcin promTemps */ promC = promTemps(temps); /* al mdulo aFahrenheit */ promF = aFahrenheit(promC); /* Conversin de las temperaturas promedio mensuales a Conversin del promedio a grados Fahrenheit, invocando

grados Fahrenheit, invocando al mdulo aFahrenheit */ for(mes = 0; mes<=11; mes++) tempsF[mes] = aFahrenheit(temps[mes]); /* Impresin de temperaturas promedio mensuales en grados Fahrenheti*/ for(mes = 1; mes<=12; mes++) printf(\n La temperatura en grados Fahrenheit del mes %d es %.2f: , mes, tempsF[mes-1]); /* Impresin del promedio */ printf(\n\n El promedio anual en grados Celsius es: %.2f , promC); printf(\n El promedio anual en grados Fahrenheit es: %.2f , promF); system(pause); } /* fin main */

Fundamentos de programacin
Programa Desarrollado
/* Definicin de funciones */ void leerTemps (float temps[]) { /* Definicin de variables locales a leerTemps */ int mes; for(mes = 1; mes<=12; mes++) { printf(\n Ingresa la temperatura mes); scanf(%f, &temps[mes-1]); } } /* fin leerTemps */

promedio

del

mes %d: ,

float promTemps (float temps[]) { /* Definicin de variables locales a promTemps */ int mes; float suma=0; for(mes = 0; mes<=11; mes++) suma = suma + temps[mes]; return (suma/12); /* fin leerTemps */

float aFahrenheit(float tempC) { return ((9.0/5.0)*tempC+32); } /* fin aFahrenheit */

Programa 6.1: promedioTemp.c

Fundamentos de programacin
Programa Desarrollado

Figura 6.2: Ejecucin del programa promedioTemp.c Actividad 2. Funciones En esta actividad presentars una versin preliminar del programa que has trabajado como parte de las evidencias de aprendizaje anteriores, el cual, ahora debe incorporar mdulos para hacer ms eficiente su funcionamiento. En el aula virtual encontrars ms detalles. 6.3. Alcance de las variables El alcance de las variables es la parte del programa dentro de la cual se pueden utilizar. Cuando son declaradas fuera del cuerpo de cualquier funcin se denominan variables globales y pueden ser utilizadas en cualquier punto del programa a partir del lugar donde fueron declaradas, en cambio cuando son declaradas dentro del cuerpo de alguna funcin se denominan variables locales a sta, es

Fundamentos de programacin
Programa Desarrollado
decir slo dentro de esa funcin pueden ser utilizadas. Las variables locales que tienen en el mismo nombre pero fueron declaradas en diferentes funciones, no tienen relacin, son espacios de memoria totalmente independientes uno de otro. Podemos decir que, son como dos personas diferentes que tienen el mismo nombre. Por otro lado las variables que se ponen como argumentos en la declaracin de una funcin se consideran locales a estas. Para ejemplificar lo anterior, se muestra el siguiente programa, en el cual se distinguen con diferentes colores el alcance de las variables. #include<stdio.h> #include<stdlib.h> int TAM = 5;
Variable global Variable local a inicializaA Referencia a una variable global

void inicializaA(int A[]) { Variable local int i; for (i=0; i<TAM; i++) A [i] = 0; } main() { int i; int A[] = {1,1,1,1,1};

Declaracin de variables locales a main

printf(Arreglo antes de la llamada a inicializaA: A = [); for (i=0; i<TAM; i++) { if(i< TAM -1) printf(%d ,,A[i]); else printf(%d ]\n\n\t,A[i]); } inicializaA(A); printf(Arreglo despues de la llamada a inicializaA: A = [); for (i=0; i<TAM; i++) { if(i< TAM -1) printf(%d ,,A[i]); else printf(%d ]\n\n\t,A[i]); } system(pause); } Programa 6.2: porReferencia.c

Fundamentos de programacin
Programa Desarrollado
Al utilizar variables globales todas las funciones pueden manipularlas, sus valores permanecen mientras el programa est en ejecucin. Sin embargo su uso puede promover errores de tipo lgico, ya que al modificar el valor de una variable dentro de una funcin puede afectar el resultado de otra. Por ejemplo, supongamos que la funcin inicializaA() modifica el valor de la variable TAM que almacena el nmero de elementos del arreglo A, este cambio repercutir en los ciclos de la funcin main, los cuales imprimen el arreglo A. En este caso se producir un error en la ejecucin, pues si el valor es menor a cinco no se imprimirn todos los valores y se es mayor entonces habr elementos indefinidos. Detectar y corregir este tipo de errores puede ser una tarea nada fcil, por lo que no se recomienda el uso de variables globales, lo cual no ocurre si son constantes. Las variables locales por otra parte favorecen mucho la reutilizacin de cdigo y la modularidad, ya que cada funcin declara y manipula sus propias variables sin depender de lo que ocurra en otras funciones, esto no significa que al utilizar solamente variables locales no sea posible compartir datos entre las diferentes funcione, esto se hace mediante sus datos de entrada y retorno, una posible desventaja es que el valor de las variables locales se pierde cada vez que la funcin termina. 6.4. Paso de parmetros EL paso de parmetros se refiere a la forma en la que se transfieren como parmetro una variable a una funcin, esencialmente, si se le otorgan o no permisos para modificar los valores originales. Cuando no se le otorga permisos para que la modifique se dice que es paso de parmetros por valor, pues en este caso slo se transfiere el valor de la variable, el cual se almacena en una variable local de la funcin que se est llamando. En cambio, cuando la funcin puede modificar el valor de la variable se dice que es un paso de parmetro por referencia, pues en este caso no se pasa slo el valor sino la direccin de memoria que le corresponde a la variable. En los siguiente subtemas se explica ms a detalle los dos tipos de paso de parmetro. 6.4.1. Por valor Cuando se realiza una llamada a una funcin por valor y en sta aparece una variable como uno de los argumentos, en realidad no se est pasando la variable sino una copia del valor que sta contiene, lo cual implica que si dentro de la funcin se modifica el argumento esto no se ve reflejado en el programa desde el cual se hizo la llamada, pues son localidades de memoria diferentes (recuerda que en cada llamada a una funcin se crean nuevas variables y se destruyen una vez finaliza la ejecucin). #include<stdio.h> #include<stdlib.h> void inicializa(int a) { a = 0;

Fundamentos de programacin
Programa Desarrollado
} main() { int a=10; /* Llamada a la funcin incializa */ printf("\nEl valor de \"a\" antes de la llamada es %i\n\n", a); inicializa(a); printf("\nEl valor de \"a\" despues de la llamada es %i\n\n", a); system("pause"); } Programa 6.3: porValor.c La ejecucin del programa es: printf("\nEl valor de la variable local \"a\" es %d\n\n",a);

Figura 6.3: Ejecucin del programa pasoValor.c En la ejecucin puedes ver que la variable local a main no se modifica, esto es porque se pasa una copia del valor que almacena cuando se realiza la llamada a la funcin inicializa(a). Este valor se guarda en un espacio de memoria, tambin llamado a, que es una variable local a la funcin y que existe mientras sta se ejecuta. Observa que el cambio si se realiza en la variable local de la funcin inicializa. 6.4.2. Por referencia La llamada a una funcin por referencia s modifica el valor de la variable, pues lo que realmente se est pasando es la direccin de memoria asignada a la variable para que la funcin pueda modificar el valor. En C los arreglos siempre se pasan por referencia, ya que el nombre del arreglo en realidad almacena la direccin de memoria donde se encuentra almacenado el primer elemento del arreglo. De esta manera cuando se realiza una llamada a una funcin y se escribe el identificador de un arreglo como

Fundamentos de programacin
Progrrrollado
parmetro, se est pasando la direccin. Para ejemplificar lo anterior se muestra la ejecucin del programa pasoReferencia.c que se present en un subtema anterior.

Figura 6.4: Ejecucin del programa pasoRefencia.c

En la ejecucin del programa se observa que despus de la llamada a la funcin cambia el estado del arreglo A. Finalmente, cabe mencionar que para realizar la llamada por referencia de una variable de tipo bsico en lenguaje C es necesario pasar la direccin de la variable para lo cual se utiliza el operador & seguido del nombre de la variable (&nombre), como se hace en la funcin scanf, este operador regresa la direccin de memoria que le corresponde a la variable indicada. Por otra parte, para almacenar la direccin de memoria de una variable se utiliza una variable de tipo apuntador. Una variable apuntador se encarga de almacenar una direccin de memoria, la declaracin de una variable apuntador es similar a la de cualquier otra variable, con la diferencia que se debe escribir un asterisco entre el tipo de la variable y el identificador. El tema de los apuntadores es muy interesante, sin embargo, no es uno de los objetivos de este curso. Para que apliques lo aprendido en esta unidad y a lo largo del curso se propone la siguiente evidencia de aprendizaje. Evidencia de aprendizaje: Programa en C. Entrega final del programa modular que soluciona el problema planteado Esta es la ltima evidencia, debers realizar el diseo modular del problema original que describiste en la evidencia de la unidad dos, as como la codificacin de tu solucin. Para conocer los detalles ingresa al aula virtual. Consideraciones especficas de la unidad Te sugerimos que escribas, compiles y ejecutes los programas que se desarrollaron a lo largo de esta unidad para que comprendas mejor los contenidos y te apropies de ellos.

Fundamentos de programacin
Programa Desarrollado
Referencias Deitel H, M., & Deitel P, J. Cmo programar en C/C++. Mxico: Prentice Hall. Joyanes, L., & Zohanero, I. (2005). Programacin en C. Metodologa, algoritmos y estructuras de datos. aspao: Mc Graw Hill. (1991). El lenguaje de programcin C. Mxico: Prentice-Hall

Kernighan, B., & Ritchie, D. Hispanoamericana.

Lpez, L. (2005). Programacin estructurada en lenguaje C. Mxico: Alfaomega. Prez, H. (1992). Fsica General (Primera Edicin ed.). Mxico: Publicaciones Cultura.

Potrebbero piacerti anche