Structs
¿Qué es un struct?
Hasta ahora, has usado variables individuales para almacenar datos: un nombre aquí, una edad allá, un puntaje en otro lado. Pero ¿qué pasa si quieres agrupar datos relacionados?
Un struct (abreviatura de "structure", estructura) te permite crear tu propio tipo de dato agrupando variables. Piensa en él como un formulario: un formulario de "Persona" tiene campos para nombre, edad y ciudad — y cada persona que creas llena esos mismos campos.
Definir un struct
struct Persona { nombre: String, edad: int, ciudad: String }
Esto define un nuevo tipo llamado Persona con tres campos. No se crea ningún dato todavía — esto es solo la plantilla.
Crear una instancia
Para crear una Persona real, llena los campos:
struct Persona { nombre: String, edad: int, ciudad: String } fn main() { let alice: Persona = Persona { nombre: "Alice", edad: 30, ciudad: "Berlín" } print(alice.nombre) // Alice print(alice.edad) // 30 print(alice.ciudad) // Berlín }
La notación con punto (alice.nombre) accede a un campo del struct.
Modificar campos
Usa var para crear un struct mutable, luego modifica sus campos:
struct Contador { valor: int } fn main() { var c: Contador = Contador { valor: 0 } print(c.valor) // 0 c.valor = c.valor + 1 c.valor = c.valor + 1 print(c.valor) // 2 }
Structs como parámetros de funciones
Puedes pasar structs a funciones:
struct Rectangulo { ancho: int, alto: int } fn area(r: Rectangulo) -> int { return r.ancho * r.alto } fn perimetro(r: Rectangulo) -> int { return 2 * (r.ancho + r.alto) } fn main() { let rect: Rectangulo = Rectangulo { ancho: 10, alto: 5 } print(area(rect)) // 50 print(perimetro(rect)) // 30 }
Structs como valores de retorno
Las funciones también pueden devolver structs:
struct Punto { x: int, y: int } fn crear_punto(x: int, y: int) -> Punto { return Punto { x: x, y: y } } fn sumar_puntos(a: Punto, b: Punto) -> Punto { return Punto { x: a.x + b.x, y: a.y + b.y } } fn main() { let p1: Punto = crear_punto(3, 4) let p2: Punto = crear_punto(1, 2) let p3: Punto = sumar_puntos(p1, p2) print(p3.x) // 4 print(p3.y) // 6 }
¿Por qué usar structs?
Sin structs, una función que describe a una persona podría verse así:
fn describir(nombre: String, edad: int, ciudad: String) { print(nombre + " tiene " + int_to_string(edad) + " años, de " + ciudad) }
Con tres parámetros es manejable. Pero ¿qué pasa si una persona tiene 10 campos? La firma de la función se vuelve ilegible. Los structs resuelven esto:
struct Persona { nombre: String, edad: int, ciudad: String } fn describir(p: Persona) { print(p.nombre + " tiene " + int_to_string(p.edad) + " años, de " + p.ciudad) } fn main() { let alice: Persona = Persona { nombre: "Alice", edad: 30, ciudad: "Berlín" } describir(alice) // Alice tiene 30 años, de Berlín }
Un parámetro en vez de tres. Y si agregas más campos después, la firma de la función no cambia.
Structs con arrays
Puedes poner structs en arrays:
struct Estudiante { nombre: String, nota: int } fn mejor_estudiante(estudiantes: Array) -> String { var mejor_nombre: String = "" var mejor_nota: int = 0 var i: int = 0 while i < estudiantes.length() { let s: Estudiante = estudiantes[i] if s.nota > mejor_nota { mejor_nota = s.nota mejor_nombre = s.nombre } i += 1 } return mejor_nombre } fn main() { let estudiantes: Array = [ Estudiante { nombre: "Alice", nota: 92 }, Estudiante { nombre: "Bob", nota: 88 }, Estudiante { nombre: "Charlie", nota: 97 } ] print(mejor_estudiante(estudiantes)) // Charlie }
Ejemplo práctico: un inventario simple
struct Articulo { nombre: String, cantidad: int, precio: int } fn valor_total(articulos: Array) -> int { var total: int = 0 var i: int = 0 while i < articulos.length() { let item: Articulo = articulos[i] total += item.cantidad * item.precio i += 1 } return total } fn main() { let inventario: Array = [ Articulo { nombre: "Manzana", cantidad: 50, precio: 2 }, Articulo { nombre: "Pan", cantidad: 20, precio: 3 }, Articulo { nombre: "Leche", cantidad: 30, precio: 4 } ] print(valor_total(inventario)) // 50*2 + 20*3 + 30*4 = 280 }
Ejercicios
- Define un struct
Librocontitulo: String,autor: Stringypaginas: int. Crea 3 libros e imprime sus títulos.
- Escribe una función
libro_mas_largo(libros: Array) -> Stringque devuelva el título del libro con más páginas.
- Define un struct
Circuloconradio: int. Escribe funcionesarea_circulo(c: Circulo) -> intycircunferencia_circulo(c: Circulo) -> intque calculen valores aproximados (usa 3 como aproximación de pi).
- Define un struct
CuentaBancariaconpropietario: Stringysaldo: int. Escribe funcionesdepositar(cuenta: CuentaBancaria, monto: int) -> CuentaBancariayretirar(cuenta: CuentaBancaria, monto: int) -> CuentaBancariaque devuelvan nuevas cuentas con saldos actualizados.
- Crea un array de 5 structs
Punto. Escribe una función que encuentre el punto más cercano al origen (0, 0). Usa distancia al cuadrado (xx + yy) para evitar necesitar raíces cuadradas.
Resumen
struct Nombre { campo: Tipo, ... }define un nuevo tipo de dato.Nombre { campo: valor, ... }crea una instancia.- Accede a campos con notación de punto:
instancia.campo - Los structs se pueden pasar a funciones y devolver desde funciones.
- Usa structs para agrupar datos relacionados.
- Structs + arrays te permiten trabajar con colecciones de datos complejos.
Siguiente capítulo: Tu primer proyecto →