ARREGLOS Y CADENAS en C++

| 2013-04-23 | No hay comentarios »

Como ya sabemos, los programas almacenan información en las variables. Hasta ahora, las variables utilizadas sólo guardaban un valor. Sin embargo, en muchos casos los programas necesitarán guardar muchos valores al mismo tiempo, tales como 50 calificaciones, 100 nombres de archivo o 1000 títulos de libros. Cuando los programas necesitan almacenar muchos valores definen un arreglo. Es decir que un arreglo es una variable capaz de guardar uno o más valores.

Cómo declarar una variable arreglo

Al igual que las variables que se han utilizado hasta este momento, un arreglo debe tener un tipo (como int, char o float) y un nombre. Además, habrá que especificar el número de valores que almacenará.

Todos los valores que se almacenen en un arreglo deben ser del mismo tipo.

La siguiente declaración crea un arreglo llamado “calificaciones” que puede contener 100 calificaciones de exámenes expresadas como números enteros:   int calificaciones [100];

Cuando el compilador encuentra la declaración de variable, asignará la suficiente memoria para que contenga 100 valores del tipo int. Cada valor es un elemento del arreglo.

Cómo utilizar los elementos de un arreglo

Veamos el programa  30ARREGLO.CPP:


#include <iostream.h>

main()

{

int valores[5];                   // Declaración del arreglo

&nbsp;

valores[0] = 100;

valores[1] = 200;

valores[2] = 300;

valores[3] = 400;

valores[4] = 500;

&nbsp;

cout << "El arreglo contiene los siguientes valores: ";

cout << valores[0] << ' ' << valores[1] << ' ' <<

valores[2] << ' ' << valores[3] << ' ' << valores[4];

&nbsp;

}

En primer lugar se define un arreglo de tipo int llamado “valores”. Los corchetes “[]” definen una matriz con subíndice, y en el caso del ejemplo, el 5 entre corchetes define 5 campos de datos, tipo int, todo ello definido como variable “valores”. En C, los subíndices empiezan desde 0, y se incrementan de uno en 1 hasta el máximo valor, en este caso, 4. Tenemos, por tanto, 5 variables tipo int, denominadas: “valores[0]”, “valores[1]”, hasta “valores[4]”.

Recordemos siempre que al partir de 0, los subíndices tienen como máximo valor una posición menos que en su definición.

Cuando los programas utilizan arreglos, el procedimiento más común es utilizar una variable índice para indicar a los elementos del arreglo. En el siguiente programa, 31ARREGLO2.CPP, se utiliza el índice dentro de un bucle for, que inicia al índice “i” en 0. El bucle termina cuando “i” es mayor que 4 (el último elemento del arreglo):


#include <iostream.h>

main()

{

int valores[5];                   // Declaración del arreglo

int i;

&nbsp;

valores[0] = 100;

valores[1] = 200;

valores[2] = 300;

valores[3] = 400;

valores[4] = 500;

&nbsp;

cout << "El arreglo contiene los siguientes valores: ";

&nbsp;

for (i=0; i<5; i++)

cout << valores[i] << ' ';

&nbsp;

}

Cada vez que el bucle for incrementa a la variable “i”, el programa imprime el siguiente elemento del arreglo.

Inicializar un arreglo en la declaración

Como ya se ha visto, C++ permite inicializar las variables en el momento de su declaración. Lo mismo puede hacerse con un arreglo, especificando los valores iniciales colocándolos entre llaves. Por ej:  int valores[5] = {100, 200, 300, 400, 500 };

Si no se especifica el tamaño de un arreglo que se inicializa en una declaración, C++ asignará la suficiente memoria para que contenga el número de valores especificados, por ejemplo, la siguiente declaración crea un arreglo capaz de guardar cuatro valores enteros:

int numeros[ ] = {1, 2, 3, 4 };

Las funciones trabajan con arreglos

Una función puede inicializar al arreglo, operar con sus valores o mostrarlos por pantalla.

Para que la función trabaje con el arreglo se debe especificar su tipo, no necesariamente su tamaño. Normalmente se pasará un parámetro que especifique el número de elementos que hay en el arreglo.

El programa 32ARR_FUN.CPP pasa los arreglos a la función “mostrar_arreglo”, que presenta los valores por pantalla:


#include <iostream.h>

void mostrar_arreglo(int arreglo[], int nro_elementos)

{

int i;

for (i=0; i < nro_elementos; i++)

cout << arreglo[i] << ' ';

}

main()

{

int nros_chicos[5] = {1, 2, 3, 4, 5};

int nros_grandes[3] = {1000, 2000, 3000};

mostrar_arreglo(nros_chicos, 5);

mostrar_arreglo(nros_grandes, 3);

}

El programa anterior simplemente pasa el arreglo a la función por medio del nombre. El siguiente programa, 33TRAERARR.CPP, utiliza la función “traer_valores” para asignar tres valores al arreglo “numeros”:


#include <iostream.h>

void traer_valores(int arreglo[], int nro_elementos)

{

int i;

for (i=0; i < nro_elementos; i++)

{

cout << "Introducir valor " << i << " : ";

cin >> arreglo[i];

}

}

&nbsp;

main()

{

&nbsp;

int numeros[3];

int i;

&nbsp;

traer_valores(numeros, 3);

cout << "Los valores del arreglo son : ";

&nbsp;

for (i=0; i < 3; i++)

cout << numeros[i] << ' ';

&nbsp;

}

ARREGLOS MULTIDIMENSIONALES

 

Veamos el programa 34MULTIARR.CPP como un ejemplo del trabajo con arreglos multidimensionales (matrices):


#include <iostream.h>

#include <stdio.h>

&nbsp;

main()

{

int i,j;

int arr1[8][8];

int arr2[25][12];

&nbsp;

for (i = 0;i < 8;i++)

for (j = 0;j < 8;j++)

arr1[i][j] = i * j;       // Esto es una tabla de multiplicar

&nbsp;

for (i = 0;i < 25;i++)

for (j = 0;j < 12;j++)

arr2[i][j] = i + j;           // Esto es una tabla de suma

arr1[2][6] = arr2[24][10]*22;

arr1[2][2] = 5;

arr1[arr1[2][2]][arr1[2][2]] = 177;     // esto es arr1[5][5] = 177;

&nbsp;

for (i = 0;i < 8;i++) {

for (j = 0;j < 8;j++)

printf("%5d ",arr1[i][j]);

printf("\n");               // nueva línea para cada suma de i

}

}

La variable “arr1” es un arreglo de 8×8, que contiene 8 veces 8, o 64 elementos en total. El primer elemento es “arr1[0][0]”, y el último “arr1[7][7]”. Otro arreglo, “arr2” es también de este tipo, pero no es cuadrado, para que se vea que un arreglo multidimensionado no debe ser necesariamente cuadrado. Ambos arreglos están rellenos con datos, que representan una tabla de multiplicar, y, una tabla de sumar, el otro.

Para ilustrar que elementos individuales pueden ser modificados, a uno de los elementos de “arr1” se le asigna uno de los elementos de “arr2”, tras ser multiplicado por 22 (línea 18). En la siguiente línea, se le asigna a “arr1[2][2]” el valor arbitrario 5, y se lo usa para el subíndice del siguiente mandato de asignación. El tercer mandato de asignación es en realidad “arr1[5][5] = 177”, porque cada uno de los subíndices contiene el valor 5. Esto sirve a título de ilustración de que cualquier expresión valida puede usarse como subíndice, sólo debe cumplir 2 reglas, una es que debe ser un entero (aunque un “char” numérico también valdría), y la otra es que debe estar en el límite del subíndice del arreglo, y no sobrepasarlo.

El contenido total de la matriz “arr1” se imprime por pantalla, en forma de cuadrado, con lo cual podemos comprobar por los valores si el programa hace lo que imaginábamos.

 

Declaración de una cadena de caracteres

Las cadenas de caracteres almacenan información tal como nombres de archivos, títulos de libros, nombres de empleados, y otras combinaciones de caracteres.

C++ guarda las cadenas de caracteres en un arreglo del tipo char que termina con un caracter nulo (NULL), por lo tanto, para declarar una cadena de caracteres simplemente se declara un arreglo de tipo char con los suficientes elementos como para contener los caracteres deseados. Por ejemplo, la siguiente declaración crea un nombre de variable de cadenas de caracteres  “nombre_archivo” capaz de almacenar 13 caracteres (el caracter NULL es uno de estos 13):    char nombre_archivo[13];

La diferencia principal entre las cadenas de caracteres y otros tipos de arreglos es cómo C++ indica el final del arreglo.

Este final se representa utilizando un caracter NULL (NULO), que C++ representa con el caracter especial “\0”. Cuando se asignan caracteres a la cadena, se debe poner el caracter null después del último elemento. Por ejemplo, el programa 35ALFABETO.CPP, asigna las letras de la A a la Z a la variable “alfabeto” utilizando un ciclo for:


#include <iostream.h>

&nbsp;

main()

{

char alfabeto[27]; // 26 letras más NULL

char letra;

int i;

for (letra='A', i = 0; letra <='Z'; letra++, i++)

alfabeto[i] = letra;

&nbsp;

alfabeto[i] = NULL;

cout << "Las letras son: " << alfabeto;

}

Como puede verse, en la línea 13, el programa asigna el caracter NULL a la cadena para indicar el último caracter de la misma.

Cuando el operador cout presenta la cadena, muestra los caracteres hasta  llegar al nulo.

 

Veamos ahora el bucle for  que aparece en la línea 10. Este bucle inicializa e incrementa dos variables. Cuando un bucle for inicializa o incrementa más de una variable se separan las operaciones utilizando una coma “,”.

En qué difiere ‘A’ de “A”

Al examinar los programas de C++ podemos ver caracteres contenidos dentro de apóstrofes (Ej: ‘A’) y caracteres dentro de comillas (“A”). Un caracter que está entre apóstrofes es un caracter constante. El compilador de C++ solamente asigna un byte de memoria para guardar un caracter constante. Sin embargo, un caracter encerrado entre comillas contiene una cadena constante.

El caracter y un caracter nulo que asigna el compilador (el compilador asigna automáticamente el caracter NULL a una cadena constante). Por lo tanto, el compilador asignará dos bytes para guardar esta cadena.

 

Cómo inicializar una cadena de caracteres

Para inicializar una cadena de caracteres en la declaración, simplemente se especifica la cadena deseada encerrándola entre comillas, ej: char titulo[40] = “Aprenda C++”;

Si el número de caracteres asignado a la cadena es menor que el tamaño del arreglo, la mayoría de los compiladores del C++ asignarán caracteres NULL al resto de la cadena.

Como ya se ha visto para los arreglos, si no se especifica el tamaño de la cadena, el compilador de C++ asignará la suficiente memoria como para contener las letras especificadas, más el caracter NULL. Ej: char titulo[] = “Aprenda C++”;

Cadenas y funciones

Como en el caso de cualquier arreglo, para trabajar con una cadena en una función, simplemente debemos especificar el tipo de arreglo (char). No se tiene que especificar el tamaño de la cadena. Por ejemplo, en el programa 36SHOW_CAD.CPP, se utiliza la función “mostrar_cadena” para mostrar por pantalla una cadena de caracteres:


#include <iostream.h>

&nbsp;

void mostrar_cadena(char cadena[])

{

cout << cadena;

}

&nbsp;

main()

{

&nbsp;

mostrar_cadena("Cadena de caracteres: ");

mostrar_cadena("Una cadena es un arreglo de tipo char.");

&nbsp;

}

Como ya sabemos, C++ utiliza el caracter NULL para indicar el final de una cadena. A continuación veremos el programa 37LONG_CAD.CPP, que contiene una función que busca el caracter NULL para determinar el número de caracteres que contiene una cadena.

Cuando examinemos más programas C++ encontraremos que muchas funciones buscan en esta forma el caracter NULL dentro de una cadena de caracteres.


#include <iostream.h>

&nbsp;

int long_cadena(char cadena[])

{

int i;

for (i = 0; cadena[i] != '\0'; i++);  // Establece un ciclo

// buscando el siguiente caracter

&nbsp;

return(i); // Longitud de la cadena

}

&nbsp;

main()

{

&nbsp;

char titulo[] = "Aprenda C++";

char capitulo[] = "Arreglos y Cadenas";

&nbsp;

cout << "La cadena '" << titulo << "' contiene " <<

long_cadena(titulo) << " caracteres.\n";

&nbsp;

cout << "La cadena '" << capitulo << "' contiene " <<

long_cadena(capitulo) << " caracteres.";

&nbsp;

}

La biblioteca string.h

El archivo string.h contiene muchas funciones para manipular cadenas. Por ejemplo, la función strupr convierte una cadena de caracteres a mayúsculas. De igual forma, la función strlwr convierte la cadena a minúsculas. Mientras que strlen regresa el número de caracteres que hay en una cadena. El programa 38STRING.CPP ilustra el empleo de las dos primeras:


#include <iostream.h>

#include <string.h>

&nbsp;

main()

{

&nbsp;

char titulo[] = "Aprenda C++";

char capitulo[] = "Arreglos y Cadenas";

&nbsp;

cout << "Mayúsculas: " << strupr(titulo);

cout << "\n\nMinúsculas: " << strlwr(capitulo);

&nbsp;

}
<h2>SUBRUTINAS DE CADENAS</h2>
Veamos otras funciones de la biblioteca string.h en el programa <b>39<i>CADENAS.CPP</i></b>:

&nbsp;

#include <iostream.h>

#include <stdio.h>

#include <string.h>

&nbsp;

main()

{

char nombre1[12],nombre2[12],cadena[25];

char titulo[20];

strcpy(nombre2,"Pedro");   strcpy(nombre1,"Margarita");

strcpy(titulo,"Trabajando con cadenas");

&nbsp;

printf("     %s\n\n",titulo);

printf("Nombre 1 es %s\n",nombre1);

printf("Nombre 2 es %s\n",nombre2);

strcpy(cadena,nombre1);   if(strcmp(nombre1,nombre2)>0)  // devuelve 1 si nombre1 > nombre2

else

strcpy(cadena,nombre2);

&nbsp;

printf("El nombre mayor alfabéticamente es %s\n",cadena);

&nbsp;

strcpy(cadena,nombre1);
strcat(cadena,nombre2);   strcat(cadena,"  ");

printf("Ambos nombres son %s\n",cadena);

}

Primero se definen 4 cadenas. Después, en la línea 10, se utiliza una función de nombre “strcpy”, función de copia de cadenas. Copia una cadena a otra mientras no aparezca NULL en la cadena origen. Tras la ejecución de este mandato, “nombre1” contendrá  “Margarita” pero sin las dobles comillas, que son sólo para el compilador (así sabe que estamos definiendo una cadena). De la misma forma, en la siguiente línea “Pedro” se copia en “nombre2”, y luego se copia “titulo”. Nótese que no es necesario para la definición de cadena el que las dos cadenas (origen – destino) sean de la misma longitud, tan solo con que destino sea igual a origen+NULL, ya vale.

En la línea 18 vemos la función “strcmp”, o función de comparación de cadenas. Devolverá 1 si la primera cadena es más larga que la segunda, 0 si las 2 tienen la misma longitud y los mismos caracteres, y -1 si la primera cadena es menor que la segunda. Una de las cadenas, dependiendo del resultado se copia en la variable “cadena”, y se imprime el nombre más largo alfabéticamente. No debería sorprendernos que “Pedro” gane, ya que es alfabéticamente mayor, no importa su longitud. También hay que señalar que el resultado varía influido por mayúsculas o minúsculas.

El mandato en la línea 26 tiene otra utilidad, “strcat” o función concatenadora de cadenas (“Suma” de caracteres). Esta función simplemente añade los caracteres de una cadena al final de otra, tomando cuidado de eliminar el NULL intermedio. En este caso, “nombre1” es copiado en “cadena” en la línea anterior, luego se concatenan los 2 blancos, y finalmente la combinación se concatena con “nombre2”. El resultado se imprime, con los dos nombres en “cadena”.

Acerca del autor: Rodrigo Paszniuk

Ingeniero Informático, amante de la tecnología, la música, el ciclismo y aprender cosas nuevas.

Posts Relacionados

  • Arrays y cadenas en PHP
  • Manual intermedio de C++
  • ENTRADAS/SALIDAS STANDARD en C++
  • Manual básico de C++



SEGUÍNOS EN FACEBOOK


GITHUB