Issuu on Google+

UNIVERSIDAD TECNICA DE AMBATO

UNIVERSIDAD TECNICA DE AMBATO. FECH CARRERA: DOCENCIA EN INFORMATICA Y COMPUTACION. MATERIA: PROGRAMACION II PROFESOR: LICDA. WILMA GAVILANES. TEMA: FUNCIONES CON VECTORES Y MATRICES. REALIZADO POR: EDISSON GOMEZ FECHA: 13/01/2012

1


UNIVERSIDAD TECNICA DE AMBATO

Funciones Como vimos anteriormente C tiene como bloque básico la función. main() es una función, printf() otra, y hay muchas más funciones predefinidas, pero nosotros mismos también podemos definir nuestras propias funciones. De hecho, es fundamental hacerlo. Podemos definir una función cualquiera de la misma manera en que definimos la función main(). Basta con poner su tipo, su nombre, sus argumentos entre paréntesis y luego, entre llaves, su código: /* Inclusión de archivos */ #include <stdio.h>

void holamundo(void) /*Función donde se ejecuta la lógica del programa*/ { printf("Hola Mundo\n"); /*imprime la cadena*/ return; /*sale de la función*/ }

int main(void) /*Función principal del programa*/ { holamundo(); /*llamada a la función que lleva el peso*/ return 0; /*sale del programa: correcto*/ } Este código es en todo equivalente al "Hola Mundo" original, sólo que nos muestra cómo escribir y cómo utilizar una función. Y además nos muestra un principio de buena programación: meter las sentencias que "hacen el trabajo" en otras funciones específicas para sacarlas de main(), dejando en ésta tan sólo un guión general de lo que hace el programa, no las órdenes específicas. De esta manera se facilita la comprensión del programa, y por tanto el futuro trabajo de modificarlo. De la misma manera que tenemos que declarar una variable antes de utilizarla, no es indiferente el orden en que se sitúen las diferentes funciones en el fichero: las funciones deben declararse antes de ser llamadas.

2


UNIVERSIDAD TECNICA DE AMBATO Igualmente vemos que, para una función void, la sentencia de control return no puede llamarse como pseudofunción, porque en dicho caso la función void (en nuestro caso holamundo()) devolvería un valor, cosa que su definición no permite. Las funciones también permiten recibir tipos de datos, así pues las funciones nos sirven para hacer de un gran problema pequeñas partes de un problema o sea dividir un gran problema en diferentes problemas más pequeños. Así que las funciones también pueden retornar un tipo de dato que hemos definido dentro de la misma. La definición de una función para sumar dos números sería de la siguiente manera: #include <stdio.h>

int sumar(int numero1, int numero2); /* prototipo de la función */

int main(void) { int suma; /* definimos una variable*/

suma = sumar(5, 3); /* la variable obtiene el valor retornado de sumar * puede verse que entre los paréntesis se mandan los valores * de los números que se desean sumar en este caso 5 y 3 * pueden haberse declarados estos dos números en otras variables * int dato = 4, valor = 3; * suma = sumar(dato, valor); */

/* imprimimos la suma de los dos números */ printf("La suma es: %d ", suma);

return 0; }

int sumar(int numero1, int numero2)

3


UNIVERSIDAD TECNICA DE AMBATO { int retsuma; /* creamos la variable a retornar*/

retsuma = numero1 + numero2; /* asignamos a esa variable la suma de número 1 y 2*/

return retsuma; /* retornamos la suma de los números */ } Paso de Parámetros Las funciones pueden recibir datos como lo hemos observado, pero existen dos formas importantes de enviar los datos hacia una función por valor y por referencia, con las cuales observarse que son muy diferentes y que una puede ser muy diferente de la otra, haciendo modificaciones en nuestro programa. Por Valor El paso por valor envía una copia de los parámetros a la función por lo tanto los cambios que se hagan en ella no son tomados en cuenta dentro de la función main(). Ejemplo: #include <stdio.h>

void sumar_valor(int numero); /* prototipo de la función */

int main(void) { int numero = 57; /* definimos numero con valor de 57*/

sumar_valor(numero); /* enviamos numero a la función */

printf("Valor de numero dentro de main() es: %d\n", numero); /* podemos notar que el valor de numero se modifica * sólo dentro de la función sumar_valor pero en la principal * número sigue valiendo 57 */

4


UNIVERSIDAD TECNICA DE AMBATO

return 0; }

void sumar_valor(int numero) { numero++; /* le sumamos 1 al numero */

/* el valor de número recibido se aumenta en 1 * y se modifica dentro de la función sumar_valor() */ printf("Valor de numero dentro sumar_valor() es: %d\n", numero);

return; } Por Referencia El paso por referencia se hace utilizando apuntadores. Se envía la dirección de memoria de la variable, por lo tanto los cambios que haga la función si afectan el valor de la variable. Ejemplo: #include <stdio.h>

void sumar_referencia(int *numero); /* prototipo de la función */

int main(void) { int numero = 57; /* definimos numero con valor de 57*/

sumar_referencia(&numero); /* enviamos numero a la función */

printf("\nValor de numero dentro de main() es: %d ", numero);

5


UNIVERSIDAD TECNICA DE AMBATO /* podemos notar que el valor de numero se modifica * y que ahora dentro de main() también se ha modificado * aunque la función no haya retornado ningún valor. */

return 0; }

void sumar_referencia(int *numero) { *numero += 1; /* le sumamos 1 al numero */

/* el valor de numero recibido se aumenta en 1 * y se modifica dentro de la función */ printf("\nValor de numero dentro sumar_referencia() es: %d", *numero);

return; } Variables Locales y Globales Además de pasar valores a una función, también se pueden declarar tipos de datos dentro de las funciones, estos tipos de datos declarados dentro de una función solo son accesibles dentro de esta misma función y se les conocen como variables locales, así pues podemos definir los mismos nombres de variables en diferentes funciones, ya que estas variables solo son accesibles dentro de esas funciones. Ejemplo: #include <stdio.h>

void funcion1() { int dato = 53; /* definimos dato en 53*/ char num1 = 'a'; /* num1 vale a */

6


UNIVERSIDAD TECNICA DE AMBATO /* imprimimos */ printf("Funcion1, dato=%d, num1=%c\n", dato, num1);

return; }

void funcion2() { int dato = 25; /* definimos dato en 25*/ char num2 = 'z'; /* num2 vale z*/

/* imprimimos */ printf("Funcion2, dato=%d, num2=%c\n", dato, num2);

return; }

int main(void) { funcion1(); /* llamamos a funcion1() */

funcion2(); /* llamamos a funcion2() */

return 0; } En este caso la variable dato, esta definida dentro de cada una de las funciones y son totalmente distinta una de otra y no se puede utilizar fuera de esta, as铆 pues num2 no puede ser utilizada por la funcion1() y num1 tampoco puede ser utilizada por funcion2(). Existen pues variables que se definen fuera de la funci贸n principal main() y fuera de cualquier otra funci贸n creada por nosotros, estas variables se les conoce con el nombre de Variables Globales ya que se pueden utilizar dentro de main() y dentro de cualquier funci贸n creada por nosotros. Ejemplo: #include <stdio.h>

7


UNIVERSIDAD TECNICA DE AMBATO

int variable_global = 99; /* inicializamos la variable global */

void funcion();

int main(void) { /* imprimimos el valor*/ printf("main(), acceso a variable_global %d\n", variable_global);

/* llamamos a la función */ funcion();

return 0; }

void funcion() { /* imprimimos el valor*/ printf("funcion(), acceso a variable_global %d\n", variable_global);

return; } Funciones Recursivas La recursividad (recursión) es la propiedad por la cual una función se llama a sí misma directa o indirectamente. La recursión indirecta implica utilizar más de una función. Se puede considerar la recursividad como una alternativa a la iteración. La recursión permite especificar soluciones naturales, sencillas, que serían, en caso contrario, difíciles de resolver. Toda función recursiva debe contemplar un caso base o condición de salida, para terminar, o la recursividad no podrá terminar nunca. Una función recursiva podría definirse así:

8


UNIVERSIDAD TECNICA DE AMBATO funcion_recursiva( /* parámetros recibidos por la función */ ) { /* Código */ funcion_recursiva( ); /* llamada a la función misma */ /* Código */ }

Uno

de

los

ejemplos

más

representativos

en

la

recursividad

es

el

factorial

de un numero ( n) la definición de recursividad del factorial es: En esta definición, n = 0, es nuestro caso base, que le da fin a la recursividad. También existen otros tipos de funciones recursivas como lo es el producto de dos números. El producto de a, b, donde a y b son números enteros positivos seria: Solución recursiva: Así pues es: Podemos ver que la multiplicación de dos números a, b se puede transformar en otro problema más pequeño multiplicar a por (b-1), el caso base se produce cuando b = 0 y el producto es 0. Ejemplo: #include <stdio.h>

int producto(int a, int b) { if (b == 0) /* caso base */ return 0; /* como b = 0, se retorna 0*/ else return a + producto (a, b - 1); /* llamada a esta misma función */ }

int main(void) { /* en este caso se llama a la función y se imprime directamente*/ printf("%i ", producto( 7, 3));

9


UNIVERSIDAD TECNICA DE AMBATO

return 0; } Vectores Los vectores son una forma de almacenar datos que permiten contener una serie de valores del mismo tipo, cada uno de los valores contenidos tiene una posición asociada que se usará para accederlos. Está posición o índice será siempre un número entero positivo. En C la cantidad de elementos que podrá contener un vector es fijo, y en principio se define cuando se declara el vector. Los vectores se pueden declarar de la siguiente forma: tipo_elemento nombre[largo]; Esto declara la variable nombre como un vector de tipo_elementos que podrá contener largo cantidad de elementos, y cada uno de estos elemento podrá contener un valor de tipo tipo_elemento. Por ejemplo: double valores[128]; En este ejemplo declaramos un vector de 128 elementos del tipo double, los índices de los elementos irían entre 0 (para el primer elemento y 127 para el último). De la misma forma que con las otras declaraciones de variables que hemos visto se le puede asignar un valor iniciar a los elementos. O también se pueden declarar: tipo_elemento nombre[largo]={valor_0, valor_1, valor_2}; En caso estamos asignadole valores a los primeros 3 elementos del vector nombre. Notar que largo debe ser mayor o igual a la cantidad de valores que le estamos asignando al vector, en el caso de ser la misma cantidad no aporta información, por lo que el lenguaje nos permite escribir: tipo_elemento nombre[]={valor_0, valor_1, valor_2};

10


UNIVERSIDAD TECNICA DE AMBATO Que declarará nombre como el vector de largo 3. Para acceder a un elemento accederemos a través de su posición. Es decir: tipo_elemento elemento; ... elemento = nombre[2]; Asumiendo que tenemos el vector anterior definido estaríamos guardando valor_2 en elemento. Veamos un ejemplos: /* * Ejemplo : El producto escalar de dos vectores */ #include <stdio.h>

double producto_escalar(double v1[], double v2[], int d);

int main() { const int largo = 3; double vector_1[] = {5,1,0}; double vector_2[] = {-1,5,3};

double resultado = producto_escalar(vector_1, vector_2, largo);

// imprime el resultado printf("(%f, %f, %f) . (%f, %f, %f) = %f\n", vector_1[0], vector_1[1], vector_1[2], vector_2[0], vector_2[1], vector_2[2], resultado); return 0; }

11


UNIVERSIDAD TECNICA DE AMBATO /* producto escalar entre dos vectores */ double producto_escalar(double v1[], double v2[], int d) { double resultado = 0; int i; for (i=0; i < d; i++) { resultado += v1[i] * v2[i]; } return resultado; } En el ejemplo anterior usamos los vectores de C para representar vectores matemáticos y calcular el producto vectorial entre ellos. Una peculiaridad que se puede notar es que al recibir un arreglo en una función no se especifica el largo, volveremos a esto en un capítulo posterior. En resumen, suponiendo que v[n] es un vector de cualquier tipo de dato con n cantidad de posiciones, al vector v se le aplican las siguientes reglas: 1. La primera posición siempre será v[0] 2. La última posición es v[n-1] 3. En versiones previas a C99 n es una constante definida antes de la declaración de v[n] Matrices Observación No confundir el paso de una matriz en su conjunto (multidimensional o no) como argumento de una función, con el paso de un elemento de una matriz. Ejemplo: int dias[2][12] = { {31,28,31,30,31,30,31,31,30,31,30,31}, {31,29,31,30,31,30,31,31,30,31,30,31} }; .... x = fun1(dias, f, c, d, e); // paso de matriz z = fun2(dias[f][c], d, e); // paso de elemento

12


UNIVERSIDAD TECNICA DE AMBATO Sinopsis Cuando hay que pasar una matriz bidimensional como argumento a una función, la declaración de parámetros formales de esta debe incluir el número de columnas, ya que la función receptora debe conoce la estructura interna de la matriz, para poder para acceder a sus elementos, y esto solo es posible informándole de su tipo y dimensiones. En el caso que nos ocupa las dimensiones son dos, por lo que la definición de la función llamada sería algo así: func (int dias[2][12]) {...}

//

Observe que en la expresión anterior está incluida toda la información necesaria: número de filas, número de columnas y tamaño de cada elemento (un int). Desde luego la función receptora necesita conocer también la dirección de inicio del almacenamiento, pero ya hemos señalado que "el identificador de una matriz puede ser utilizado como un puntero a su primer elemento", con lo que si mentalmente sustituimos dias por un puntero al número 31 (primer elemento) de la primera matriz, la información pasada es completa. Ya se ha señalado que C++ no contiene operadores para manejar matrices como una sola unidad. Al contrario de lo que ocurre en otros lenguajes (por ejemplo Java), en C++ es responsabilidad del programador no salirse del ámbito de la matriz al acceder a sus elementos, lo que una vez aceptado, nos conduce a que en realidad es innecesario conocer la primera dimensión. En efecto, en nuestro caso, el primer elemento (primera sub-matriz), es accedido directamente mediante el puntero dias; su tamaño ya lo conocemos (12 int), y con esta información es suficiente para acceder a cualquier otro elemento n. Solo es necesario desplazar el puntero los las posiciones de memoria correspondientes. La conclusión anterior estaba ya implícitamente establecida en, donde hemos visto que, en una matriz bidimensional m[F][C], la posición Pf,c respecto del comienzo del elemento m[f][c] viene determinado por: Pf,c = ( C * f ) + c expresión que es independiente del valor F (número de filas). Como consecuencia, la definición podría ser del tipo: func (int dias[][12]) {...}

//

El primer paréntesis vacío es necesario para colocar el segundo, que es el que interesa. La expresión es conceptualmente equivalente a:

13


UNIVERSIDAD TECNICA DE AMBATO func (int (*dias)[12]) {...}

//

que indica expl铆citamente el hecho de que el par谩metro es un puntero-a-matriz de 12 int. Comprobamos la veracidad de lo expuesto a un sencillo ejemplo: #include <stdio.h> void escribe(int a[][12], int x, int y); // prototipo void escribo(int (*a)[12], int x, int y); // prototipo

void main () {

// =============

int dias[2][12] = { { 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12}, {13,14,15,16,17,18,19,20,21,22,23,24} }; escribe(dias, 1, 3); escribe(dias, 0, 7); escribo(dias, 1, 3); escribo(dias, 0, 7); }

void escribe(int a[][12], int f, int c) { // definici贸n printf("Valor [%2i,%2i] = %3i\n", f, c, a[f][c]); }

void escribo(int (*a)[12], int f, int c) { // definici贸n printf("Valor [%2i,%2i] = %3i\n", f, c, a[f][c]); } Salida: Valor [ 1, 3] = 16 Valor [ 0, 7] = 8 Valor [ 1, 3] = 16 Valor [ 0, 7] = 8 Ejercicio con matriz y vectores.

14


UNIVERSIDAD TECNICA DE AMBATO #include<conio.h> #include<stdio.h> int vector[20],col,aux,fila,vector1[20],vector2[20],i,j,k,l,a,op,c; void borde() { textcolor(18); for(i=2;i<=78;i++) { gotoxy(i,2);cprintf("*"); gotoxy(i,24);cprintf("*"); } for(i=2;i<=24;i++) { gotoxy(2,i);cprintf("*"); gotoxy(78,i);cprintf("*"); } } void ingreso(int l) { col=5;fila=10; gotoxy(15,6);cprintf("Ingrese el Primer Vector==> "); textcolor(53); gotoxy(3,10);cprintf("1 Vector"); for(i=1;i<=l;i++) { do{ gotoxy(47,6);printf(" "); gotoxy(47,6);scanf("%d",&a); }while(a<3||a>53); vector[i]=a; gotoxy(col,fila+=2);cprintf("%d. %d",i,vector[i]); if(fila>20) { col=col+8; fila=10; } } col=15;fila=10; textcolor(15); gotoxy(15,8);cprintf("Ingrese el Segundo Vector==> "); textcolor(53); gotoxy(13,10);cprintf("2 Vector"); for(i=1;i<=l;i++) { do{

15


UNIVERSIDAD TECNICA DE AMBATO gotoxy(47,8);printf(" "); gotoxy(47,8);scanf("%d",&a); }while(a<3||a>53); vector1[i]=a; gotoxy(col,fila+=2);cprintf("%d. %d",i,vector1[i]); if(fila>20) { col=col+8; fila=10; } } } void intercalar() { j=0;col=26;fila=10;k=1;a=1; textcolor(53); gotoxy(24,10);cprintf("Vector Intercalado"); for(i=1;i<=l*2;i++) { if(j==0) { vector2[i]=vector[a]; gotoxy(col,fila+=2);cprintf("%d. %d",i,vector2[i]); j++; a++; } else if(j==1) { vector2[i]=vector1[k]; gotoxy(col,fila+=2);cprintf("%d. %d",i,vector2[i]); j--; k++; } if(fila>20) { col=col+8; fila=10; } } } void orden() { col=36;fila=10; for(i=1;i<=l*2;i++)

16


UNIVERSIDAD TECNICA DE AMBATO { for(j=1;j<=l*2;j++) { if(vector2[i]<=vector2[j]) { aux=vector2[i]; vector2[i]=vector2[j]; vector2[j]=aux; } } } col=50;fila=10; textcolor(53); gotoxy(45,10);cprintf(" Ascendente"); for(i=1;i<=l*2;i++) { gotoxy(col,fila+=2);cprintf("%d",vector2[i]); if(fila>20) { col=col+8; fila=10; } } col=62;fila=10; textcolor(53); gotoxy(58,10);cprintf(" Descendente"); for(i=l*2;i>0;i--) { gotoxy(col,fila+=2);cprintf("%d",vector2[i]); if(fila>20) { col=col+8; fila=10; } } } void main() { do{ clrscr(); borde(); gotoxy(25,4);printf("Ingrese el Lยกmite==> ");scanf("%d",&l); ingreso(l); intercalar(); orden();

17


UNIVERSIDAD TECNICA DE AMBATO gotoxy(25,22);printf("Desea volver==> ");scanf("%d",&op); }while(op==1); getch(); }

Conclusión El uso de funciones nos permite ir realizando paso a paso los procesos que se van a ejecutar el programa principal VOID MAIN ( ) es mucho mas fácil y mejor estructurada, el uso de los vectores es una forma de almacenar datos en con posiciones que luego los datos podemos utilizarlos de distintas maneras ya que en un vector los datos se almacenar con posiciones desde cero sin importar el valor del dato entrante de esa manera luego es muy fácil y practico buscar un dato y almacenar en un nuevo vector, y las matrices nos permiten almacenar datos de forma cuadrática secuencialmente uno tras de otro hasta que su fila y columna se llene, el uso de funciones, vectores, matrices nos van a permitir que nuestra programación sea mas básica y estructurada.

18


funciones vactores y matrices