Funciones con vectores y matrices1

11
UNIVERSIDAD UNIVERSIDAD UNIVERSIDAD UNIVERSIDAD TÉCNICA DE AMBATO TÉCNICA DE AMBATO TÉCNICA DE AMBATO TÉCNICA DE AMBATO FACULTAD DE CIENCIAS HUMANAS Y DE LA EDUCACIÓN CARRERA DE: CARRERA DE: CARRERA DE: CARRERA DE: DOCENCIA EN INFORMATICA DOCENCIA EN INFORMATICA DOCENCIA EN INFORMATICA DOCENCIA EN INFORMATICA MATERIA MATERIA MATERIA MATERIA: : : : PROGRAMACIÓN PROGRAMACIÓN PROGRAMACIÓN PROGRAMACIÓN CURSO: CURSO: CURSO: CURSO: TERCER TERCER TERCER TERCER SEMESTRE “U” SEMESTRE “U” SEMESTRE “U” SEMESTRE “U” DOCENTE: DOCENTE: DOCENTE: DOCENTE: ING. MSC. WILMA GAVILANES ING. MSC. WILMA GAVILANES ING. MSC. WILMA GAVILANES ING. MSC. WILMA GAVILANES REALIZADO POR. REALIZADO POR. REALIZADO POR. REALIZADO POR. MARLENE PALLO MARLENE PALLO MARLENE PALLO MARLENE PALLO 13 13 13 13- - -ENERO ENERO ENERO ENERO- - -2012 2012 2012 2012

description

FUNCIONES

Transcript of Funciones con vectores y matrices1

Page 1: Funciones con vectores y matrices1

UNIVERSIDAD UNIVERSIDAD UNIVERSIDAD UNIVERSIDAD

TÉCNICA DE AMBATOTÉCNICA DE AMBATOTÉCNICA DE AMBATOTÉCNICA DE AMBATO

FACULTAD DE CIENCIAS HUMANAS Y DE LA

EDUCACIÓN

CARRERA DE: CARRERA DE: CARRERA DE: CARRERA DE:

DOCENCIA EN INFORMATICA DOCENCIA EN INFORMATICA DOCENCIA EN INFORMATICA DOCENCIA EN INFORMATICA

MATERIAMATERIAMATERIAMATERIA: : : :

PROGRAMACIÓN PROGRAMACIÓN PROGRAMACIÓN PROGRAMACIÓN

CURSO: CURSO: CURSO: CURSO:

TERCERTERCERTERCERTERCER SEMESTRE “U”SEMESTRE “U”SEMESTRE “U”SEMESTRE “U”

DOCENTE:DOCENTE:DOCENTE:DOCENTE:

ING. MSC. WILMA GAVILANES ING. MSC. WILMA GAVILANES ING. MSC. WILMA GAVILANES ING. MSC. WILMA GAVILANES

REALIZADO POR.REALIZADO POR.REALIZADO POR.REALIZADO POR.

MARLENE PALLOMARLENE PALLOMARLENE PALLOMARLENE PALLO

13131313----ENEROENEROENEROENERO----2012201220122012

Page 2: Funciones con vectores y matrices1

FUNCIONESFUNCIONESFUNCIONESFUNCIONES EN CEN CEN CEN C

Funciones es un grupo de sentencias bajo el mismo nombre que realizan una tarea específica.

Utilización de las funciones.

La utilización de funciones nos permite dividir un programa extenso en pequeños segmentos que

realizan tareas concretas. Probablemente, dentro de un mismo programa se realicen las mismas

tareas varias veces, lo que se facilita mediante la utilización de funciones. Sin embargo, es probable

que ciertas funciones no sean reutilizables, pero al usarlas se mejora la legibilidad del programa.

En que se basa las funciones.

La filosofía en la que se base el diseño de C es el empleo de funciones. Por esta razón,un programa en

C contiene al menos una función, la función main. Esta función es particular dado que la ejecución del

programa se inicia con las instrucciones contenidas en su interior. Una vez iniciada la ejecución del

programa, desde la función main se puede llamar a otras funciones y, posiblemente, desde estas

funciones a otras. Otra particularidad de la función main es que se llama directamente desde el

sistema operativo y no desde ninguna otra función. De esta manera, un programa en C sólo puede

contener una función main.

Propósito de las funciones.

Con el propósito de permitir un manejo eficiente de los datos, las funciones en C no se pueden

anidar. En otras palabras, una función no se puede declarar dentro de otra función, por lo que

todas las funciones son globales o externas, lo que hace que puedan llamarse desde cualquier

parte de un programa.

Se puede acceder (llamar) a una determinada función desde cualquier parte de un programa.

Cuando se llama a una función, se ejecutan las instrucciones que constituyen dicha función.

Una vez que se ejecutan las instrucciones de la función, se devuelve el control del programa a

la siguiente instrucción (si existe) inmediatamente después de la que provocó la llamada a la

función.

Cuando se accede a una función desde un determinado punto del programa, se le puede

pasar información mediante unos identificadores especiales conocidos como argumentos

(también denominados parámetros). Una vez que la función procesa esta información,

devuelve un valor mediante la instrucción return.

La estructura general de una función en C es la siguiente:

tipo_de_retorno nombre_de_la_función (lista_de_parámetros)

{

cuerpo_de_la_función

return expresión

}

Donde:

Page 3: Funciones con vectores y matrices1

• Tipo_De_Retorno: es el tipo del valor devuelto por la función, o, en caso de que la función no

devuelva valor alguno, la palabra reservada void.

• Nombre_De_La_Función: es el nombre o identificador asignado a la función.

• Lista_De_Parámetros: es la lista de declaración de los parámetros que son pasados a la

función. Éstos se separan por comas. Debemos tener en cuenta que pueden existir funciones

que no utilicen parámetros.

• Cuerpo_De_La_Función: está compuesto por un conjunto de sentencias que llevan

• a cabo la tarea específica para la cual ha sido creada la función.

• Return Expresión: mediante la palabra reservada return, se devuelve el valor de la función, en

este caso representado por expresión.

Ejemplo

Vamos a suponer que queremos crear un programa para calcular el precio de un producto basándose

en el precio base del mismo y el impuesto aplicable. A continuación mostramos el código fuente de

dicho programa:

#include <stdio.h>

float precio(float base, float impuesto); /* declaración */

main()

{

float importe = 2.5;

float tasa = 0.07;

printf("El precio a pagar es: %.2f\n", precio(importe, tasa));

return 0;

}

float precio(float base, float impuesto) /* definición */

{

float calculo;

calculo = base + (base * impuesto);

return calculo;

}

El ejemplo anterior se compone de dos funciones, la función requerida main y la función creada por el

usuario precio, que calcula el precio de un producto tomando como parámetros su precio base y el

impuesto aplicable. La función precio calcula el precio de un producto sumándole el impuesto

correspondiente al precio base y devuelve el valor calculado mediante la sentencia return.

Por otra parte, en la función main declaramos dos variables de tipo float que contienen el precio base

del producto y el impuesto aplicable. La siguiente sentencia dentro de la función main es la llamada a

la función de biblioteca printf, que recibe como parámetro una llamada a la función precio, que

Page 4: Funciones con vectores y matrices1

devuelve un valor de tipo float. De esta manera, la función printf imprime por la salida estándar el

valor devuelto por la función precio. Es importante tener en cuenta que las variables importe y tasa

(argumentos) dentro de la función main tienen una correspondencia con las variables base e impuesto

(parámetros) dentro de la función precio respectivamente.

Declaración de una función

Las funciones de biblioteca se declaran en lo que se conocen como ficheros de cabecera o ficheros .h

(del inglés headers, cabeceras). Cuando deseamos utilizar alguna de las funciones de biblioteca,

debemos especificar el fichero .h en que se encuentra declarada la función, al inicio de nuestro

programa. Por ejemplo, si deseamos utilizar la función printf en nuestro programa, debemos incluir el

fichero stdio.h que contiene el prototipo de esta función.

Tras declarar una función, el siguiente paso es implementarla. Generalmente, este paso se conoce

como definición. Es precisamente en la definición de una función donde se especifican las instrucciones

que forman parte de la misma y que se utilizan para llevar a cabo la tarea específica de la función. La

definición de una función consta de dos partes, el encabezado y el cuerpo de la función. En el

encabezado de la función, al igual que en el prototipo de la misma, se tienen que especificar los

parámetros de la función, si los utiliza y el tipo de datos que devuelve, mientras que el cuerpo se

compone de las instrucciones necesarias para realizar la tarea para la cual se crea la función.

Definición de una función

Como ya hemos visto, a los argumentos que recibe la función también se les suele llamar parámetros.

Sin embargo, algunos autores consideran como parámetros a la lista de variables entre paréntesis

utilizada en la declaración o en la definición de la función, y como argumentos los valores utilizados

cuando se llama a la función. También se utilizan los términos argumentos formales y argumentos

reales, respectivamente, para hacer esta distinción.

Cuando un programa utiliza un número elevado de funciones, se suelen separar las declaraciones de

función de las definiciones de las mismas. Al igual que con las funciones de biblioteca, las

declaraciones pasan a formar parte de un fichero cabecera (extensión .h), mientras que las

definiciones se almacenan en un fichero con el mismo nombre que el fichero .h, pero con la extensión

.c. En algunas ocasiones, un programador no desea divulgar el código fuente de sus funciones. En

estos casos, se suele proporcionar al usuario el fichero de cabecera, el fichero compilado de las

definiciones (con extensión .o, de objeto) y una documentación de las mismas. De esta manera,

cuando el usuario desea hacer uso de cualquiera de las funciones, sabe qué argumentos pasarle y qué

tipo de datos devuelve, pero no tiene acceso a la definición de las funciones.

Devolución de valores

De que la función a la que se quiere acceder no utilice argumentos, se deben colocar los paréntesis

vacíos.

Cualquier expresión puede contener una llamada a una función. Esta llamada puede ser parte de una

expresión simple, como una asignación, o puede ser uno de los operandos de una expresión más

compleja. Por ejemplo:

a = cubo(2);

calculo = b + c / cubo(3);

Page 5: Funciones con vectores y matrices1

Debemos recordar que los argumentos que utilizamos en la llamada a una función se denominan

argumentos reales. Estos argumentos deben coincidir en el número y tipo con los argumentos

formales o parámetros de la función. No olvidemos que los argumentos formales son los que se

utilizan en la definición y/o declaración de una función.

Los argumentos reales pueden ser variables, constantes o incluso expresiones más complejas.

El valor de cada argumento real en la llamada a una función se transfiere a dicha función y se le

asigna al argumento formal correspondiente.

Generalmente, cuando una función devuelve un valor, la llamada a la función suele estar dentro de

una expresión de asignación, como operando de una expresión compleja o como argumento real de

otra función. Sin embargo, cuando la función no devuelve ningún valor, la llamada a la función suele

aparecer sola. Veamos un ejemplo:

z = potencia( a, b);

imprime valores (x, y, z);

FUNCIONES CON FUNCIONES CON FUNCIONES CON FUNCIONES CON VECTORESVECTORESVECTORESVECTORES

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};

Page 6: Funciones con vectores y matrices1

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.

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; } /* 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 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.

Otra función clásica es la búsqueda de un máximo o mínimo, que podemos escribirla de la siguiente manera:

int buscar_maximo(double valores[], int num_valores) { int maximo_pos = 0; for (int i = 1; i < num_valores; i++) { if (valores[i] > valores[maximo_pos]) { maximo_pos = i; }

Page 7: Funciones con vectores y matrices1

} return maximo_pos; } }

Cuando una función recibe un vector por parámetro y cambia su contenido y el cambio es permanente (se ve aún fuera de la función). Esto puede parecer extraño después del énfasis que pusimos en resaltar que todos los parámetros de una función se reciben por valor, pero se aclarará en el siguiente capitulo.

Mientras tanto usemos esto para definir una función que le aplique otra función que recibe por parámetro a cada elemento del vector, guardando el resultado en el mismo vector y una llamada de ejemplo a esta.

void cuadrados(double vector[], int largo) { for (int i=0;i<largo;i++) { vector[i]=cuadrado(vector[i]); } } ... double cuadrado(double valor) { return valor*valor; } ... cuadrados(elementos,num_elem); ...

De la misma forma que venimos usando vectores de tipos básicos, podemos tener vectores de vectores, estos se declaran de la siguiente forma:

int matriz[3][7]; int tabla[3][4]={ { 1, 2, 3, 4}, { 5, 6, 7, 8}, /* los espacios y saltos de líneas no son tomados en cuenta */ { 9,10,11,12} }; double v[2][2][2]; ... printf("tabla[0][1]: %i\n", tabla[0][3]); // Imprime 4 printf("tabla[2][0]: %i\n", tabla[2][0]); // Imprime 9 ...

En este ejemplo tabla es un vector de longitud 3, cuyos elementos son vectores de longitud 4 de elementos de tipo int.

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]

Page 8: Funciones con vectores y matrices1

FUNCIONES CON MATRICESFUNCIONES CON MATRICESFUNCIONES CON MATRICESFUNCIONES CON MATRICES

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:

func (int (*dias)[12]) {...}

Que indica explícitamente el hecho de que el parámetro es un puntero-a-matriz de 12 int.

Ejemplo:

#include <stdio.h>

void escribe(int a[][12], int x, int y); // prototipo

void escribo(int (*a)[12], int x, int y); // prototipo

Page 9: Funciones con vectores y matrices1

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

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

Por último, podemos trabajar de forma similar con paso de matrices a funciones. Cuando el vector a pasar es bidimensional tendremos que tener cuidado con la definición de la función, puesto que el compilador debe conocer exactamente, cual es el tamaño de la segunda dimensión. Vemos un ejemplo.

void main(void)

{

int b[6][5];

void funcion2(int [][5]); //la segunda dimensión hay que dársela

funcion2 ( b ); // llamada: paso la matriz como puntero

}

Page 10: Funciones con vectores y matrices1

La función deberá estar definida con el tamaño de la segunda dimensión:

void funcion2(int pmatriz[][5])

{

pmatriz [0][0]= pmatriz [1][1];

// pmatriz[0][5] no es válido, accede a una columna que no existe

// pmatriz[6][4] no es válido si la matriz original es b[6][5]

// se accede a una fila que no existe

...

}

Por otra parte, como mencionamos en los arrays unidimensionales, se han construido librerías

estándar de tratamiento de cadenas que copian, comparan, etc. cadenas de cara

parámetros de entrada son cadenas de caracteres, que se suponen que acaban en el carácter especial

de fin de cadena (ASCII 0x0). Por tanto estas funciones trabajan o iteran con los elementos de las

cadenas hasta que se topan con tal carácter de

A continuación se explican algunas de las más comunes:

gets (char *cadena) Lee de teclado una cadena de 'cadena'.

puts (char *cadena) Imprime en pantalla la cadena de caracte'cadena'.

strlen (char *cadena) Devuelve la longitud de la cadena de ca'cadena'. Devuelve la longitud de la cadena.

strcat (char *cadena1, char *cadena2)Concatena la cadena de caracteres dada por 'cadena1' con la 'cadena2', es decir, añade al final de 'cadena1' la 'cadena2'.

strcmp (char *cadena1, char *cadena2)Compara la cadena de ca

strcpy (char *cadena1, char *cadena2)

Copia la cadena de caracteres dada por 'cadena1' en la 'cadena2'

La función deberá estar definida con el tamaño de la segunda dimensión:

pmatriz [0][0]= pmatriz [1][1];

// pmatriz[0][5] no es válido, accede a una columna que no existe

válido si la matriz original es b[6][5]

// se accede a una fila que no existe

Por otra parte, como mencionamos en los arrays unidimensionales, se han construido librerías

estándar de tratamiento de cadenas que copian, comparan, etc. cadenas de caracteres. Los

parámetros de entrada son cadenas de caracteres, que se suponen que acaban en el carácter especial

de fin de cadena (ASCII 0x0). Por tanto estas funciones trabajan o iteran con los elementos de las

cadenas hasta que se topan con tal carácter de fin de cadena.

A continuación se explican algunas de las más comunes:

Lee de teclado una cadena de caracteres y la introduce a partir de la dirección dada por

Imprime en pantalla la cadena de caracteres que viene a partir de la dirección dada por

Devuelve la longitud de la cadena de caracteres que viene a partir de la dirección dada por 'cadena'. Devuelve la longitud de la cadena. strcat (char *cadena1, char *cadena2) Concatena la cadena de caracteres dada por 'cadena1' con la 'cadena2', es decir, añade al final de 'cadena1' la 'cadena2'. strcmp (char *cadena1, char *cadena2) Compara la cadena de caracteres dada por 'cadena1' con la 'cadena2'. strcpy (char *cadena1, char *cadena2)

Copia la cadena de caracteres dada por 'cadena1' en la 'cadena2'.

Por otra parte, como mencionamos en los arrays unidimensionales, se han construido librerías

cteres. Los

parámetros de entrada son cadenas de caracteres, que se suponen que acaban en el carácter especial

de fin de cadena (ASCII 0x0). Por tanto estas funciones trabajan o iteran con los elementos de las

caracteres y la introduce a partir de la dirección dada por

res que viene a partir de la dirección dada por

racteres que viene a partir de la dirección dada por

e caracteres dada por 'cadena1' con la 'cadena2', es decir, añade al

Page 11: Funciones con vectores y matrices1