Ir al contenido principal

Array en C. Parte 1: Vectores ...

Llega el turno de hablar de uno de los tipos de datos derivados que llamamos array (o arreglo en español) y que usaremos con frecuencia en muchos programas y en la implementación de algunas estructuras de datos, entre otros.

Se suele dividir a los arreglos en tres categorías: vectores, matrices y cadenas de caracteres, aunque la esencia se mantiene y sólo hay pequeñas variantes entre cada una de ellas. En esta entrada nos ocuparemos de la primera y dedicaremos las próximas a explicar las dos restantes.

Primero lo primero: ¿Qué es un array?


Un array es un espacio de almacenamiento continuo donde guardaremos elementos del mismo tipo bajo un mismo nombre (identificador) y a los que podremos acceder por medio de índices que nos indicarán la posición de cada uno de esos elementos. También podríamos decir que es un conjunto de variables homogéneas (del mismo tipo).

 Para darnos una idea observemos el siguiente esquema:

Cada casillero corresponde a una dirección de memoria en la que guardaremos los elementos de nuestro array y se podrá acceder a esas direcciones por medio de los índices que irán desde 0 hasta el tamaño del arreglo menos uno.



Para recordar: Hay que tener presente que los arreglos son homogéneos, es decir que todos los elementos que contienen deben tener el mismo tipo de dato.

Más adelante, cuando lleguemos al nivel avanzado, veremos que podemos crear arreglos que contengan elementos de diferentes tipos e incluso crear arreglos dinámicos, pero por ahora trabajaremos con arreglos homogéneos estáticos.
  


Vectores:

Ahora que tenemos una idea de lo que es un array veamos la forma de implementarlo a través de lo que llamamos vector.

En C los vectores son conjuntos de elementos numéricos del mismo tipo. Si hacemos referencia al esquema anterior podemos decir que esos elementos que estarán almacenados en las direcciones de memoria de nuestro vector compartirán el mismo tipo de datos.

Declarando un vector:

La forma general para declarar un vector es la siguiente:


Donde el número de elementos (o tamaño) debe ser una expresión constante entera y lo demás será igual que en la declaración de una variable.

Por lo que si, por ejemplo, queremos crear un vector de enteros que tenga 10 elementos y que se llame VECTOR podríamos declararlo de la siguiente manera:


También podríamos definir una constante  para declarar este vector:


Hay que notar que lo que hace el compilador en estas declaraciones es reservar espacios de memoria consecutivos para 10 elementos de tipo entero.

¿Qué contiene un vector sin inicializar?:

Una vez definido nuestro vector, alguien podría imaginarse que está vacío o que todos sus elementos están en 0, pero en realidad contiene lo que llamamos basura en cada una de sus posiciones de memoria. Veamos esto con un ejemplo:

Declaramos un vector y, mediante una iteración, utilizamos los índices para mostrar en pantalla el contenido de nuestro vector al que dejamos sin ningún elemento:

Ahora compilamos nuestro programa, lo ejecutamos y vemos qué contiene nuestro vector:


Y vemos claramente a lo que nos referimos con basura... tiene cualquier cosa, lejos de estar todo en cero.

Inicializando elementos en un vector:

Ahora que vimos lo que contiene un vector sin elementos, veamos cómo inicializar los elementos que queremos en nuestro vector.

Si vieron el código que mostraba lo que tenía el vector vacío y ahora suponen que para hacer esta inicialización debemos usar los índices: ¡BINGO! acertaron.

Y es que realmente es tan fácil como hacer una simple asignación teniendo en cuenta el índice. Veamos el ejemplo:

Aquí podemos ver que podemos asignar directamente un elemento del tipo correspondiente al índice en donde queremos guardarlo e incluso podemos operar con el nombre de vector y el índice del elemento como si fueran variables de ese tipo.

También podemos inicializar los elementos de nuestro vector mediante una estructura de control iterativa, por ejemplo si queremos colocar en 0 todos los elementos de nuestro vector de ejemplo, podríamos hacer lo siguiente:


Una opción alternativa que tenemos para hacer esto es realizar la inicialización de todos los elementos de la siguiente manera:


En este ejemplo, declaramos e inicializamos simultáneamente nuestro vector con los números del 0 al 9. En esta forma, los elementos que "guardamos" se asignan a las direcciones de memoria correspondientes empezando desde la primera.

 Esta forma de inicializar sólo la recomendamos cuando se trabaja con vectores de pocos elementos.

Usando scanf y printf con vectores:

En caso que queramos que el usuario ingrese algún elemento de nuestro vector o imprimir en pantalla el elemento de un vector lo haremos de la misma manera que ya vimos para variables sólo que siempre debemos recordar utilizar el índice.

Por ejemplo si queremos ingresar y mostrar por pantalla el elemento de índice 1 de VECTOR, haríamos lo siguiente, utilizando la marca de formato correspondiente al tipo de nuestro vector:



Hasta aquí llegamos con la explicación acerca de los vectores en C, en las próximas entradas veremos un poco más acerca de los array, en especial sobre matrices y cadenas de caracteres.




Comentarios

Entradas populares de este blog

C: Conversiones de tipo (casting) en C...

El casting o simplemente cast  nos permite hacer una conversión explícita de un tipo de dato a otro, a criterio del programador siempre y cuando estos tipos sean compatibles. Este cast se realiza a través de un operador de conversión de tipos (type casting operator) y es un recurso a tener en cuenta ya que hay situaciones en que nos puede resultar de gran utilidad. Hacer uso de un cast es tan sencillo como poner (tipo de dato)  delante de la expresión o variable a convertir. Veamos un ejemplo: Declaramos una variable de tipo int con un identificador tan creativo como "a" y le realizamos diferentes cast a a para mostrarlo como si fuera un float, un double y un char en un printf. Lo que obtendríamos en pantalla sería lo siguiente: Donde tenemos el valor de nuestro a, a convertido en float y double (mostrándolo con 3 cifras decimales) y a convertido en char. Si vemos este último caso, al hacer la conversión de "a" a char toma a como el código ascii de

C: Ejemplos: Congruencia de Zeller (nivel básico) ...

La Congruencia de Zeller es un algoritmo que se atribuye al matemático alemán Julius Christian Johannes Zeller que vivió en el siglo XIX. Este algoritmo nos permite determinar el día de la semana que le corresponde a una fecha determinada del calendario Gregoriano. La fórmula que nosotros usaremos (con algunas modificaciones respecto de la original para poder usarla en  informática) es la siguiente: Donde h es el día de la semana (entre 0 y 6), J es año/100 (la centuria) y K es año mod 100 (el año de la centuria). Y hay que tener en cuenta que los meses de enero y febrero cuentan como el mes 13 y 14 del año anterior. Ahora que tenemos la fórmula, programemos el algoritmo en C mediante el uso de una función: Analicemos el código paso a paso: Tenemos en cuenta el caso de enero y febrero: Dijimos que estos meses corresponden a los meses 13 y 14 del año anterior por lo que los asignamos como corresponde (mes + 12 , que dará 13 para enero y 14 para febrero) y le rest

Algoritmos: Resolución de problemas y refinamientos en pseudocódigo...

En otras entradas, vimos las partes que debe tener nuestro algoritmo en pseudocódigo y las estructuras que utilizaremos para resolverlo. Ahora llega el turno de implementar todo en conjunto para dar origen a nuestra creación. Pero ¿cómo resolvemos un problema así? Para hacerlo, utilizaremos lo que llamamos refinamientos sucesivos. Este concepto consiste en dividir el problema en subproblemas más pequeños y a estos, a su vez, en otros más pequeños; y así sucesivamente hasta que la solución de los últimos sea trivial, sencillo de resolver. Luego usaremos todas las soluciones obtenidas para armar la solución de nuestro problema mayor. Este principio, tiene base en parte de la técnica divide and conquer (dependiendo de la traducción: "divide y vencerás") que es una de las muchas técnicas de resolución de algoritmos existentes. Como vemos, al dividir el problema en otros más pequeños y más fáciles de resolver, podemos pasar de un problema complicado a uno cuya solución es much