ARRAYS 4
De Bachillerato a Ingeniería (IV)
Funciones y paso de parámetros en C++
Cómo dividir un programa grande para que compile y no se convierta en una pesadilla
“Un buen programa no es un bloque enorme de código. Es una colección de pequeñas soluciones que trabajan juntas.”
En las entregas anteriores hemos aprendido tres ideas fundamentales:
- Recorrer arrays.
- Insertar y eliminar elementos.
- Trabajar con estructuras (
struct) y arrays de estructuras.
Con eso ya podemos resolver ejercicios bastante serios. Pero en la universidad aparece un nuevo problema: los programas empiezan a crecer.
Un examen como el de Programación I de Ingeniería de Telecomunicación puede pedir gestionar un tren completo, imprimir sus vagones, calcular ratios, insertar cafeterías y eliminar vagones obsoletos.
Si intentamos escribirlo todo dentro del main, el programa se vuelve inmanejable.
La solución es usar funciones.
1. ¿Para qué sirve una función?
Una función permite separar una tarea concreta.
Por ejemplo:
void saluda()
{
cout<<"Hola"<<endl;
}
Y la usamos así:
saluda();
Cada vez que llamamos a saluda(), se ejecuta su código.
2. Funciones que reciben datos
void muestraNumero(int x)
{
cout<<x<<endl;
}
Uso:
muestraNumero(7);
La variable x recibe el valor 7.
3. Funciones que devuelven un resultado
int doble(int x)
{
return x*2;
}
Uso:
int resultado=doble(5);
cout<<resultado;
Salida:
10
4. Funciones con estructuras
Supongamos esta estructura:
struct Libro
{
string isbn;
string titulo;
string autor;
int paginas;
int anio;
};
Podemos hacer una función para imprimir un libro.
void imprimeLibro(Libro l)
{
cout<<l.isbn<<"-";
cout<<l.titulo<<"-";
cout<<l.autor<<"-";
cout<<l.paginas<<"-";
cout<<l.anio<<endl;
}
Uso:
imprimeLibro(biblioteca[0]);
5. Funciones con arrays de estructuras
Ahora imprimimos toda la biblioteca.
void imprimeBiblioteca(Libro biblioteca[], int n)
{
cout<<"Lista de libros"<<endl;
for(int i=0;i<n;i++)
{
imprimeLibro(biblioteca[i]);
}
}
Observa algo importante:
El array se pasa como parámetro:
Libro biblioteca[]
Y también pasamos el número real de elementos:
int n
Nunca debemos depender de MAX para saber cuántos libros hay realmente.
6. Función para buscar
Buscar es una de las funciones más importantes.
int buscaISBN(Libro biblioteca[], int n, string isbn)
{
for(int i=0;i<n;i++)
{
if(biblioteca[i].isbn==isbn)
return i;
}
return -1;
}
Devuelve:
- la posición si lo encuentra;
-1si no lo encuentra.
Uso:
int pos=buscaISBN(biblioteca,n,"978844153210");
if(pos==-1)
cout<<"No encontrado";
else
cout<<"Encontrado en la posicion "<<pos;
7. Función para comprobar si existe
Podemos aprovechar la función anterior.
bool existeISBN(Libro biblioteca[], int n, string isbn)
{
return buscaISBN(biblioteca,n,isbn)!=-1;
}
Esto es muy elegante.
Una función puede llamar a otra función.
8. Función para añadir al final
bool anyadeLibro(Libro biblioteca[], int &n, Libro nuevo)
{
if(n==MAX)
return false;
if(existeISBN(biblioteca,n,nuevo.isbn))
return false;
biblioteca[n]=nuevo;
n++;
return true;
}
Aquí aparece algo importantísimo:
int &n
Ese símbolo & significa que la función puede modificar la variable original.
Si no ponemos &, la función recibiría una copia y el cambio no afectaría al main.
9. Paso por valor y paso por referencia
Paso por valor
void cambia(int x)
{
x=99;
}
Uso:
int a=5;
cambia(a);
cout<<a;
Salida:
5
No cambia, porque la función recibe una copia.
Paso por referencia
void cambia(int &x)
{
x=99;
}
Uso:
int a=5;
cambia(a);
cout<<a;
Salida:
99
Ahora sí cambia.
Por eso, cuando una función debe modificar n, escribimos:
int &n
10. Función para eliminar
bool eliminaLibro(Libro biblioteca[], int &n, string isbn)
{
int pos=buscaISBN(biblioteca,n,isbn);
if(pos==-1)
return false;
for(int i=pos;i<n-1;i++)
{
biblioteca[i]=biblioteca[i+1];
}
n--;
return true;
}
Esta función combina:
- búsqueda;
- desplazamiento;
- modificación de
n; - devolución de éxito o fracaso.
Es exactamente el tipo de función que aparece en exámenes universitarios.
11. Plantilla completa
#include <iostream>
using namespace std;
const int MAX=100;
struct Libro
{
string isbn;
string titulo;
string autor;
int paginas;
int anio;
};
void imprimeLibro(Libro l)
{
cout<<l.isbn<<"-";
cout<<l.titulo<<"-";
cout<<l.autor<<"-";
cout<<l.paginas<<"-";
cout<<l.anio<<endl;
}
void imprimeBiblioteca(Libro biblioteca[], int n)
{
cout<<"Lista de libros"<<endl;
for(int i=0;i<n;i++)
imprimeLibro(biblioteca[i]);
}
int buscaISBN(Libro biblioteca[], int n, string isbn)
{
for(int i=0;i<n;i++)
{
if(biblioteca[i].isbn==isbn)
return i;
}
return -1;
}
bool existeISBN(Libro biblioteca[], int n, string isbn)
{
return buscaISBN(biblioteca,n,isbn)!=-1;
}
bool anyadeLibro(Libro biblioteca[], int &n, Libro nuevo)
{
if(n==MAX)
return false;
if(existeISBN(biblioteca,n,nuevo.isbn))
return false;
biblioteca[n]=nuevo;
n++;
return true;
}
bool eliminaLibro(Libro biblioteca[], int &n, string isbn)
{
int pos=buscaISBN(biblioteca,n,isbn);
if(pos==-1)
return false;
for(int i=pos;i<n-1;i++)
biblioteca[i]=biblioteca[i+1];
n--;
return true;
}
int main()
{
Libro biblioteca[MAX];
int n=0;
Libro l1={"978001","Fundacion","Asimov",296,1951};
Libro l2={"978002","Dune","Herbert",688,1965};
anyadeLibro(biblioteca,n,l1);
anyadeLibro(biblioteca,n,l2);
imprimeBiblioteca(biblioteca,n);
eliminaLibro(biblioteca,n,"978001");
cout<<endl<<"Despues de eliminar:"<<endl;
imprimeBiblioteca(biblioteca,n);
return 0;
}
12. Relación directa con el examen de Teleco
En el examen de los vagones tendríamos una estructura parecida:
struct Vagon
{
string codigo;
int tipo;
int capacidad;
int fabricacion;
int revision;
};
Y funciones como estas:
void imprimeVagon(Vagon v);
void imprimeTren(Vagon tren[], int n);
int buscaCodigo(Vagon tren[], int n, string codigo);
bool existeCodigo(Vagon tren[], int n, string codigo);
bool anyadeCafeteria(Vagon tren[], int &n, Vagon nuevo);
void actualizaTren(Vagon tren[], int &n);
Fíjate en una cosa: ya no parece tan difícil.
El examen no es “hacer un programa enorme”.
Es hacer varias funciones pequeñas.
13. Errores típicos con funciones
❌ Olvidar declarar la función antes del main.
❌ Cambiar n dentro de una función sin pasarlo por referencia.
int n
cuando debería ser:
int &n
❌ Olvidar devolver un valor en una función bool o int.
❌ Usar return dentro de una función void.
❌ Confundir el nombre del array en el main con el nombre del parámetro.
❌ Escribir una función demasiado grande que intenta hacerlo todo.
Reto final
Crea un programa para gestionar una lista de alumnos.
Cada alumno tendrá:
DNI
nombre
nota
edad
El programa debe tener funciones para:
- imprimir un alumno;
- imprimir todos los alumnos;
- buscar por DNI;
- comprobar si existe;
- añadir un alumno;
- eliminar un alumno;
- calcular la nota media;
- mostrar el alumno con mejor nota.
Condiciones:
- máximo 30 alumnos;
- no puede haber dos alumnos con el mismo DNI;
- las funciones que modifiquen el número de alumnos deben recibir
int &n.
Consejo final
Cuando un programa no compila, no intentes arreglarlo todo a la vez.
Compila después de cada función.
Primero:
imprimeAlumno()
Luego:
imprimeTodos()
Después:
buscaDNI()
Y así sucesivamente.
Un programa grande que compila poco a poco es mucho más fácil de corregir que un monstruo de 300 líneas escrito de golpe.
En la próxima entrega…
Llegamos al corazón de los exámenes de Ingeniería: algoritmos típicos con arrays de estructuras.
Aprenderemos a calcular ratios, insertar elementos en una posición concreta, respetar un orden y eliminar varios elementos de una sola pasada.
Es decir, exactamente lo que hace falta para resolver el examen de los vagones.
Etiqueta:c++, ies monterroso, PROGRAMACIÓN, TELECO, tic
