Fundamentos de programación/Tipos de datos estructurados

Lección 10
Tipos de datos estructurados

Los tipos de datos primitivos definen como se almacena la información en la memoria de la computadora y los diferentes procesos que se pueden realizar sobre ella.[1] Son abstracciones útiles que facilitan el manejo de los datos, pero en la mayoría de los casos la información que se debe procesar está estructurada de alguna manera. Por eso la mayoría de los lenguajes de programación proporcionan uno o varios mecanismos para combinar los tipos primitivos en estructuras más complejas llamadas tipos de datos estructurados.[2] Estos tipos de datos al ser más complejos, tienen restricciones en su uso que los diferencian de los tipos de datos primitivos. Entre ellas, la mayoría de los lenguajes de programación no permiten regresarlos como resultado de una función.[3] Los más comunes son los arreglos (también "array's" o matrices), las cadenas de carácteres y los registros.

Arreglos o Matrices editar

Los arreglos o Matrices son el tipo de datos estructurado más común en los lenguajes de programación y posiblemente el más importante.[3] Consisten en un conjunto finito y ordenado de elementos del mismo tipo.[1] Todos los elementos están relacionados entre sí porque comparten el mismo nombre. Para referirse a un elemento específico se usa el nombre del arreglo y la posición del elemento en el grupo,[4] que normalmente se llama «subíndice» y se suele especificar al final del nombre del arreglo usando paréntesis cuadrados.[4]

Los subíndices están limitados a números enteros en la mayoría de los lenguajes de programación,[2] con 0 o 1 como el valor mínimo o límite inferior y con el tamaño del arreglo como límite superior (o con el tamaño menos uno si el límite inferior inicia en 0).[1] Para los propósitos de este proyecto de aprendizaje, supondremos que el índice del primer elemento del arreglo corresponde al número 1. Los valores usados como subíndices pueden ser constantes, variables o expresiones siempre que su resultado o tipo sea un número entero.[1]

Para declarar un arreglo, en el pseudocódigo utilizado en algunos proyectos de aprendizaje, se especifica el tipo de datos de los elementos, el nombre del arreglo y su tamaño en paréntesis cuadrados al final del arreglo:

[tipo de datos del arreglo] [nombre del arreglo] [ [tamaño del arreglo] ]

En este ejemplo se declara un arreglo que almacena 10 números enteros:

entero arreglo_de_enteros[10]

También es posible declarar arreglos multidimencionales o matrices.[1] Los lenguajes de programación procesan de forma diferente este tipo de estructuras, pero uno de los tipos de declaración posibles consiste en usar múltiples pares de paréntesis cuadrados:

[tipo de datos del arreglo] [nombre del arreglo] [ [tamaño de la primera dimensión] ][ [tamaño de la segunda dimensión] ]

En este otro ejemplo se declara un arreglo de dos dimensiones con 8 filas y 8 columnas para representar un tablero de ajedrez:

carácter tablero_de_ajedrez[8][8]

Para almacenar un valor en el arreglo, se usa su nombre como cualquier otra variable, pero indicando el subíndice de la posición que se desea usar al final del nombre:

[nombre del arreglo] [ [subíndice la posición a usar] ] := [expresión del tipo del arreglo]

En el código listado a continuación se almacena el valor 257 en la posición 5 del arreglo.

arreglo_de_enteros[5] := 257 

Si se desea almacenar un valor de un arreglo multidimencional, es necesario especificar un índice para cada una de sus dimensiones:

[nombre del arreglo] [ [subíndice de la primera dimensión] ][ [subíndice de la segunda dimensión] ] := [expresión del tipo del arreglo]

En este fragmento de programa el carácter 'C' representa la pieza llamada «caballo» y se almacena en la posición 3 de la primera dimensión del arreglo y en la dimensión 5 de la segunda dimensión.

tablero_de_ajedrez[3][5] := 'C'

Para recuperar el valor almacenado en el arreglo, se procede de la misma forma, usando el nombre del arreglo y especificando el subíndice correspondiente.

[nombre de una variable]  := [nombre del arreglo] [ [subíndice la posición a leer] ]

En este ejemplo se recupera el valor almacenado en la séptima posición del arreglo y se almacena en una variable sencilla:

entero valor_actual := arreglo_de_enteros[7]

Y se procede de la misma manera con las matrices:

[nombre de una variable]  := [nombre del arreglo] [ [subíndice la primera dimensión] ][ [subíndice la segunda dimensión] ]

Tal y como se puede ver en este ejemplo:

carácter pieza_actual := tablero_de_ajedrez[4][1]

Las diferentes posiciones de los arreglos se pueden usar en expresiones como cualquier otra variable. Esto se demuestra en la siguiente fragmento de código que suma todos los elementos de un arreglo:

entero arreglo_de_enteros[5]

arreglo_de_enteros[1] := 12
arreglo_de_enteros[2] := 159
arreglo_de_enteros[3] := 45
arreglo_de_enteros[4] := 78
arreglo_de_enteros[5] := 12

entero i

// Variable para almacenar el resultado de la suma.
entero total_suma

// Ciclo para realizar el cálculo
desde i := 1 hasta 5 hacer
    total_suma := total_suma + arreglo_de_enteros[i]
fin_desde

Al usar arreglos como parámetros de una llamada a una función, los lenguajes de programación suelen pasarlos por referencia, lo que significa que las modificaciones que se hagan a sus elementos serán visibles fuera del contexto de la función.[4] Para declarar un parámetro que le transmite una referencia a un arreglo a una función, usamos un nombre de variable, un tipo y los paréntesis cuadrados, pero sin indicar el tamaño:

subrutina [nombre de la subrutina] ( [tipo de datos del arreglo] [nombre del arreglo] [] )

En el siguiente ejemplo una función llamada realizar_jugada recibe un arreglo de dos dimensiones como uno de sus parámetros.

subrutina realizar_jugada (carácter tablero[][])
    // ...
fin_subrutina

Para invocar la subrutina se usa el nombre del arreglo pero sin incluir los paréntesis cuadrados, tal y como se muestra en este ejemplo:

realizar_jugada (tablero_de_ajedrez)

Cadenas de carácteres editar

Las cadenas de carácteres son simplemente secuencias de carácteres[2] y algunos lenguajes de programación las manejan como arreglos de tipo carácter.[3] En otros lenguajes se consideran un tipo de datos especial con operaciones específicas para manipularlos debido a la importancia del procesamiento de textos en una gran cantidad de aplicaciones informáticas.[3]

Prácticamente todos los lenguajes permiten usar constantes de tipo cadena, expresadas como secuencias de carácteres y delimitadas con comillas dobles u otro tipo de indicador para diferenciarlas de los carácteres individuales. También permiten incluir secuencias de escape para representar carácteres no imprimibles como los tabuladores y los cambios de línea, las comillas cuando son parte del texto y no indican el fin de la constante y otros elementos reservados del lenguaje.[3] Los lenguajes más modernos las suelen considerar un tipo de datos primitivo, permiten regresarlas como resultado de una función y proporcionan operaciones especiales para procesarlas, como la concatenación de carácteres y el emparejamiento de patrones.[2]

Para declarar una variable de tipo cadena de carácteres usaremos la palabra reservada cadena y usaremos las comillas dobles " para delimitar los datos de este tipo:

cadena nombre_proyecto := "Wikiversidad"

Para realizar operaciones con ellas supondremos que existe una biblioteca proporcionada por el lenguaje (cadenas.bib) con algunas de las funciones más comunes para el procesamiento de cadenas de texto:

entero subrutina largo_cadena (cadena texto)
Regresa la cantidad de carácteres presente en la cadena especificada.
cadena subrutina concatenar (cadena texto1, cadena texto2)
Regresa una cadena de texto compuesta de la cadena en el parámetro texto1 seguida del texto en el parámetro texto2
lógico subrutina iguales (cadena texto1, cadena texto2)
Regresa verdadero si las cadenas en los parámetros texto1 y texto2 son iguales. Regresa falso si son diferentes.
carácter subrutina carácterEn (cadena texto, entero posición)
Regresa el carácter de la cadena texto ubicado en la posición especificada por el segundo parámetro.
entero subrutina posiciónCarácter (cadena texto, carácter elemento)
Regresa la posición de la primera ocurrencia del carácter elemento en la cadena texto. Regresa 0 si el carácter no está presente en la cadena.
cadena subrutina subcadena (cadena texto, entero posición_inicial, entero posición_final)
Regresa la sección de la cadena texto ubicada entre las dos posiciones indicadas.
cadena subrutina subcadena_izquierda (cadena texto, entero posición)
Regresa la sección de la cadena texto ubicada a la izquierda de la posición indicada (sin incluir el carácter en esa posición).
cadena subrutina subcadena_derecha (cadena texto, entero posición)
Regresa la sección de la cadena texto ubicada a la derecha de la posición indicada (sin incluir el carácter en esa posición).

La biblioteca se cargaría con el siguiente código:

cargar ("cadenas.bib")

En el siguiente fragmento de código se usan las funciones indicadas anteriormente para determinar si una cadena contiene la palabra «vida»:

// Cargar la biblioteca para manipular cadenas
cargar ("cadenas.bib")

cadena verso := "¡Qué descansada vida la del que huye del mundanal ruido..."
cadena texto_de_interés := "vida"

lógico texto_presente := falso
entero posición_actual := 1

// Se le resta uno porque el primer carácter
// ya está en la posición actual.
entero largo_a_revisar := largo_cadena (texto_de_interés) - 1

entero posición_último_intento := largo_cadena (verso) - largo_cadena (texto_de_interés) + 1

mientras (posición_actual <= posición_último_intento)  y (texto_presente = falso) hacer

  subtexto_actual := subcadena (verso, posición_actual, largo_a_revisar)

  si iguales (subtexto_actual, texto_de_interés) = verdadero entonces

    texto_presente := verdadero

  fin_si

fin_mientras

Registros editar

Los registros son estructuras que almacenan diferentes tipos de datos bajo un mismo nombre[1] y que permiten mantenerlos agrupados como un único elemento.[2] Cada uno de los componentes de un registro recibe un nombre propio, también llamado nombre de campo, y se puede acceder para recuperar o almacenar información usando el nombre de la estructura y del campo.[2]

Para usar una estructura primero es necesario declarar su composición y darle un nombre de la siguiente forma:

estructura [nombre de la estructura] contenido
[tipo de dato] [nombre del campo]
[tipo de dato] [nombre del campo]
...
fin_estructura

Luego se declara la variable de tipo estructura usando el nombre como si fuera un tipo de dato:

[nombre de la estructura] [nombre de la variable]

Para asignarle valores a cada uno de los campos, se accede a ellos usando el nombre de la estructura, un punto y el nombre del campo:

[nombre de la estructura].[nombre del campo] := [valor a almacenar]

El método se usa para recuperar la información:

[nombre de variable] := [nombre de la estructura].[nombre del campo]

Una de las ventajas de las estructuras es que se pueden usar como tipos de datos en las declaraciones de los arreglos, lo que permite organizar grupos de datos que representan varias entidades complejas en la aplicación que se está desarrollando.[1] La declaraciones de los arreglos de estructuras tienen esta forma:

[nombre de la estructura] [nombre de variable] [[tamaño del arreglo]]

En el siguiente fragmento de programa se declara una estructura llamada empleado para almacenar datos de las personas que trabajan para una empresa, se crea un arreglo de 10 posiciones, donde cada una corresponde a una instancia de la estructura y luego se procede a completar la información del primero de los empleados.

estructura empleado contenido
  cadena nombre_empleado
  cadena apellido_empleado
  entero sueldo_mensual
fin_estructura 

empleado planilla_empresa[10]

planilla_empresa[1].nombre_empleado := "Juan"
planilla_empresa[1].apellido_empleado := "Perez"
planilla_empresa[1].sueldo_mensual := 125000

Otros tipos de datos complejos editar

Algunos lenguajes de programación tienen otros tipos de datos estructurados. Entre los más frecuentes están las uniones, los conjuntos y las listas. Las uniones permiten almacenar más de un tipo de valor en la misma ubicación y con el mismo nombre, los conjuntos implementan colecciones no ordenadas de elementos distintos[2] y las listas son estructuras de datos abstractas que se definen recursivamente como una lista vacía o como un par que incluye un dato y otra lista.[3]

Resumen de la lección editar

  • Los tipos de datos estructurados combinan tipos de datos primitivos en estructuras complejas.
  • Los tipos de datos estructurados permiten representar la estructura de la información que el programa debe procesar.
  • Los arreglos consisten en un conjunto finito y ordenado de elementos del mismo tipo.
  • Las cadenas de carácteres son arreglos de carácteres que algunos lenguajes de programación procesan de forma especial para facilitar el manejo de textos.
  • Los registros son estructuras que almacenan diferentes tipos de datos bajo un mismo nombre y que permiten mantenerlos agrupados como un único elemento.
  • Algunos lenguajes de programación permiten trabajar con otros tipos de datos estructurados como las uniones, los conjuntos, las listas, tuplas y diccionarios.

Términos clave editar

Lecturas adicionales editar

Bibliografía editar

  1. 1,0 1,1 1,2 1,3 1,4 1,5 1,6 Joyanes Aguilar, Luis (2013). Fundamentos generales de programación (1.ª edición). Ciudad de México, México: McGraw Hill. p. 368. ISBN 978-607-15-0818-8. 
  2. 2,0 2,1 2,2 2,3 2,4 2,5 2,6 Appleby, Doris; Vandekopple, Julius J. (1998). Programming Languages: Paradigm and practice [Lenguages de programación: Paradigma y práctica] (1.ª edición). México D. F., México: McGraw Hill. p. 492. ISBN 970-10-1945-8. 
  3. 3,0 3,1 3,2 3,3 3,4 3,5 Scott, Michael L. (2000). Programming Language Pragmatics (en inglés) (1.ª edición). California, Estados Unidos: Morgan Kaufmann. p. 858. ISBN 1-55860-578-9. 
  4. 4,0 4,1 4,2 Deitel, H. M.; Deitel, P. J. (1995). C How to program [Cómo programar en C/C++] (2.ª edición). México: Prentice Hall Hispanoamericana, S. A. p. 927. ISBN 968-880-471-1. 


Proyecto: Fundamentos de programación
Anterior: Tercera evaluación parcial — Tipos de datos estructurados — Siguiente: Evaluación de la lección 10