Sei sulla pagina 1di 6

UNIVERSIDAD DE EL SALVADOR

FACULTAD DE INGENIERIA Y ARQUITECTURA


ESCUELA DE INGENIERIA DE SISTEMAS INFORMATICOS
ESTRUCTURAS DE DATOS

GUIA DE LABORATORIO Nº 1
Funciones y Tipos Abstractos de Datos

Introducción

El concepto de tipo de abstracto de datos se introdujo durante la década de los años setenta. Se
refiere a la especificación del tipo de dato que puede expresarse de modo independiente de su
implementación. Un Tipo Abstracto de Datos (TAD) es un modelo matemático con una serie de
operaciones definidas.

Los TAD combinan en una sola unidad datos y funciones que operan sobre esos datos, uno de los
problemas más comunes en el empleo de funciones es el traslado de parámetros realizados desde
los algoritmos de control por lo que se hace necesario estudiar desde la práctica dicha temática.
Esta guía proporciona una serie de ejemplos relacionados al paso de parámetros y adicionalmente
ejemplos de especificaciones de TAD para que sean implementados en lenguaje C.

Objetivos:

 Conocer las diferentes formas de pasar argumentos a las funciones en lenguaje


C/C++.
 Diseñar tipos abstractos de datos empleando notación semiformal para las
especificaciones de los mismos.

Paso de argumentos:

En C el paso de argumentos a las funciones se hace por valor. Se pueden pasar argumentos
utilizando apuntadores a los mismos para simular un paso por referencia.

En C++ el paso de argumentos se hace por valor o por referencia. Por defecto los argumentos se
pasan por valor (excepto arrays).

Parámetros por valor.


El paso por valor significa que al compilar la función y el código que llama a la función, la función
recibe una copia de los valores de los parámetros pasados como argumentos a esa función. Las
variables reales no se pasan a la función, solo copias de su valor.
El siguiente programa muestra el uso de parámetros por valor:

#include <stdio.h>

#include <conio.h>

void doble ( float dato, int num );


main ( )
{
float dato = 1.5;
doble ( dato, 3 );
printf ( "El valor de dato es: % 10.2f\n", dato);

ESTRUCTURAS DE DATOS 1
getch();
}
void doble ( float dato, int num )
{
int i;
for ( i = 0; i < num; i++)
dato = dato * 2.0;
printf ( "El resultado es: % 10.2f\n", dato);

getch();
}

Parámetros por puntero.


Es posible simular una llamada por referencia pasando un puntero al argumento, entonces, al
pasar la dirección, es posible cambiar el valor de la variable usada en la llamada.
Este argumento formal tendrá la forma : tipo_i *arg_i , y a la hora de realizar la llamada, el
parámetro real tendrá el formato : &param

Ejemplo:
void factorial (int n, int *fact)
{
int i;
*fact = 1;
if (n > 1)
for (i = 2; i <= n; i++) *fact = *fact * i;
}

Y un ejemplo de llamada a esta función:

int a;
factorial (3, &a);

Si en una función quisiéramos modificar un parámetro que fuera un puntero, sería necesario pasar
como argumento la dirección del mismo, es decir, doble indirección. Y así sucesivamente si el
argumento fuera doble puntero, triple puntero, etc.
Parámetros por referencia.
Cuando su función debe modificar el valor de la variable pasada como parámetros y que esta
modificación retorne a la función llamadora, se debe pasar el parámetro por referencia. En este
método el compilador no pasa una copia del valor del argumento; en su lugar, pasa una referencia,
que indica a la función dónde existe la variable en memoria.
La referencia que una función recibe es la dirección de la variable.
La llamada a la función será:
IntercambiarInt( x, y);

La función se definirá de modo más elegante, así:


void IntercambiarInt( int &i, int &j)
{
int aux;
aux = i ;
i=j;
j = aux;
}

ESTRUCTURAS DE DATOS 2
Una referencia se indica por el operador de dirección ( & ) de igual modo que el operador de
indirección ( * ) indica un puntero.

Las referencias son particularmente útiles cuando se pasan estructuras grandes y objetos a una
función. Utilizando una referencia para un parámetro, solo se pasa la dirección, no la estructura o
el objeto completo.

Comparación de paso por valor, paso por puntero y paso por referencia.
Cuando se utilizan parámetros por valor y por referencia se deben tener presentes los siguientes
aspectos:
 Los parámetros por valor reciben copias de los valores de los argumentos pasados a ellos.
 Las asignaciones a parámetros por valor en una función nunca cambian los valores de
argumentos originales pasados a los parámetros.
 Los parámetros por referencia (declarados con &) reciben la dirección de valores de
argumentos pasados a ellos.
 En una función, las asignaciones a parámetros referencia cambian los valores de los
argumentos originales.

Nota: Todos los parámetros de una función en C se pasan por valor. C no tiene equivalente a los
parámetros referencia en C++.

Ejercicio No. 1

El siguiente ejercicio muestra que los parámetros pasados por valor se pueden modificar dentro de
la función sin cambiar la variable que representa al parámetro en el llamador. Digite (póngale
extensión .cpp a su archivo), compile y ejecute el programa.

#include <iostream.h>
void DemoLocal( int valor )
{
cout << “Dentro de DemoLocal, valor =” << valor << endl;
valor = 75;
cout << “Dentro de DemoLocal, valor =” << valor << endl;
}
void main( void)
{
int n = 10;
cout << “Antes de llamar a DemoLocal, n= “ << n << endl;
DemoLocal(n);
cout << “Después de llamar a DemoLocal, n= “ << n << endl;
cout << “Pulse Intro para continuar”;
cin.get(); //pausa la pantalla
}

¿Cómo cambia el valor de n, si es que lo hace?


_______________________________________________________________________________
_______________________________________________________________________________
_______________________________________________________________________________
_______________________________________________________________________________

ESTRUCTURAS DE DATOS 3
Ejercicio No. 2
El siguiente ejemplo muestra el uso de tres rutinas de intercambio de datos diferentes. Digite
(póngale extensión .cpp a su archivo), compile y ejecute el programa.

#include <stdio.h>
#include <conio.h>
void Intercambio(int, int);
void Intercambio(int *, int *);
void Intercambio(int, int &, int &);

main() {
int x = 22, y = 33;
printf("x = %d\t y = %d\n", x, y);
Intercambio(x,y); // llamada por valor
printf("x = %d\t y = %d\n", x, y);
Intercambio(1, x, y); // llamada por referencia
printf("x = %d\t y = %d\n", x, y);
Intercambio(&x, &y); // llamada por puntero
printf("x = %d\t y = %d\n", x, y);
getch();
}

void Intercambio( int a, int b)


{
int aux;
aux = a;
a = b;
b = aux;
}
void Intercambio(int *a, int *b)
{
int aux;
aux = *a;
*a = *b;
*b = aux;
}
void Intercambio( int i, int &a, int &b)
{
int aux=i;
aux = a;
a = b;
b = aux;
}

Como resultado de la llamada a Intercambio por valor (la primera llamada de Intercambio()), ¿se
cambian los valores de a y b? __________________ ¿por qué?____________________________
_______________________________________________________________________________
_______________________________________________________________________________

Después de la segunda llamada a Intercambio() (llamada por referencia), ¿hubo modificación de a


y b?____________________¿por qué?_______________________________________________
_______________________________________________________________________________
_______________________________________________________________________________
_______________________________________________________________________________

ESTRUCTURAS DE DATOS 4
¿Es equivalente la tercer llamada a Intercambio() con la segunda llamada a la misma función?
_________________________¿por qué?______________________________________________
_______________________________________________________________________________
_______________________________________________________________________________

 Ejercicios Propuestos:
1. Escribir una función mayor() que intercambie dos valores cuando el primero sea mayor
que el segundo. Hacer un programa que la utilice.

2. Escribir una función que multiplique un valor por 10 y devuelva el valor modificado. Hacer
un programa que la utilice.

3. Escribir una función potencia(), que calcule la potencia de un número n (tipo double)
elevado a un exponente p (tipo int). Escribir un programa que haga uso de esta función.

4. Diseñar una función area() que pueda calcular el área de un cuadrado y un cubo. Escribir
un programa que haga uso de esta función.

5. Escribir una función menorAcero() al que se pasan dos argumentos int por referencia y a
continuación fijar el menor de los dos números a 0. Escribir un programa que utilice esta
función.

II. Tipos Abstractos de Datos.

Ejemplo

Diseñe un TAD para determinar la longitud de una cadena, invertir una cadena.

/* definición de valor */
abstract typedef <<char>> String ; /* Es una secuencia de caracteres
condition String Є { a - z, A - Z , 0 - 9 } ;

/* definición de operador */
/* Esta función encuentra el tamaño o longitud de la cadena de caracteres.*/
abstract int longitudcadena(cadena1);
String cadena1;
int i = 1 ;
Precondition cadena1 != null;
Postcondition
Mientras cadena1[i] != ‘/0’
longitudcadena = i = i + 1;
Fin Mientras

/* Operación que invierte una cadena de caracteres dada en texto1.


abstract String invertircadena (texto1, texto2)
String texto1, texto2 ;
int i, j = 1 ;
Precondition texto1 != null and texto2 = null
Postcondition

ESTRUCTURAS DE DATOS 5
i = longitudcadena(texto1) ;
Mientras i > 0
Invertircadena = texto2[ j ] = texto1[ i ] ;
i=i–1;
j=j+1;
Fin Mientras

 Ejercicios Propuestos
1. Implementar en lenguaje Dev C, el diseño planteado en clase sobre los números
racionales.

2. Definimos un string como una serie de caracteres almacenados en un vector. Diseñe el


TAD correspondiente a un string con las funciones imprimir, calcular longitud, copiar,
buscar carácter, invertir cadena, convertir a mayúsculas o minúsculas. Luego implemente
la solución en Dev C.

3. Diseñe un TAD que contemple un conjunto de enteros y que permita realizar las siguientes
operaciones sobre los elementos de ese conjunto. Ingresar elementos, eliminar elementos,
imprimir el mínimo, imprimir el máximo, listar los elementos del conjunto, e identificar si un
determinado valor se encuentra en el conjunto. Implemente la solución.

4. Crear un TAD que permita manipular un rectángulo en pantalla. El perímetro del rectángulo
estaría formado por asteriscos (ver figura abajo), las operaciones que manipularán la figura
son las siguientes: mostrarlo en pantalla, moverlo al centro, moverlo a la derecha, moverlo
a la izquierda, moverlo hacia abajo, moverlo hacia arriba. Para cada movimiento el número
de posiciones a trasladar estará dado por n donde n>0.

Figura: Rectángulo en pantalla

******* *******
* * * *
* * * *
******* *******

Movimiento horizontal Moverlo a la derecha

Implemente la solución en Dev C.

5. Diseñar el TAD Bolsa como una colección de elementos no ordenados y que pueden estar
repetidos. Las operaciones: CrearBolsa, Añadir un elemento, BolsaVacía (verifica si tiene
elementos), Dentro (verifica si un elemento pertenece a la bolsa), Cuantos (determina el
número de veces que se encuentra el elemento), Unión y Total.

ESTRUCTURAS DE DATOS 6

Potrebbero piacerti anche