Programación en C++/Arrays y cadenas de texto

De Wikilibros, la colección de libros de texto de contenido libre.

Streams Desarrollo Orientado a Objetos

Contenido

[editar] Arrays y cadenas de texto

Los arreglos son usados extensamente por los programadores para contener listas de datos en la memoria, por ejemplo, los datos almacenados en un disco suelen leerse y ponerse dentro de un arreglo con el objetivo de facilitar la manipulación de dichos datos, ya que los datos en memoria pueden ser modificados, clasificados, marcados para su eliminacion, etc. para luego ser reescritos al disco. Otro ejemplo podría ser el de un menú de opciones que se desplegarán dentro de una ventana para que el usuario pueda elegir una de éstas, en tales casos y cuando las opciones son numerosas, solamente se ponen unas cuantas de ellas dentro de la ventana pero se le da al usuario la oportunidad de poder subir y bajar a su antojo para ver el resto de opciones que, aunque no se vean en la ventana, forman parte del menú o arreglo de opciones.

Arreglo:

Un arreglo es un conjunto de datos del mismo tipo ordenados en forman líneal uno despues de otro. Los componentes de un arreglo se han de referenciar por medio del nombre del arreglo y un índice de desplazamiento para indicar el componente deseado.

[editar] Indices de un arreglo

Los índices son números que se utilizan para identificar a cada uno de los componentes de un arreglo. A manera de ejemplo, podemos pensar que los índices son como los números de cuartos de un hotel, es decir, para poder dirijirnos a un hotel específico es necesario saber el nombre del mismo, luego, si queremos llegar a un cuarto específico de dicho hotel necesitaremos, ademas del nombre del hotel, el número de cuarto deseado. También, podemos pensar en los casilleros del estante de paquetería de un supermercado, asi que si deseamos guardar o retirar un paquete nos direjimos a paquetería el cual sería el nombre del arreglo; luego, el empleado guarda nuestro paquete dentro de un casillero con un número específico el cual sería el índice para identificar el lugar del casillero en paquetería donde quedó guardado el paquete. Supongamos que el empleado nos entrega una ficha con el número 12 impreso sobre la misma; de tal manera que podemos decir que nuestro paquete está guardado en paqueteria(12) ó paqueteria[12].

El gobierno de ARISTIDEs ASCANIO fue unos de los gobierno mas relevante

[editar] Dimensiones de un arreglo

De acuerdo a la forma en que se construye o declara un arreglo, éste puede ser clasificado como: unidimensional, bidimensional y multidimensional. Los arreglos que se emplean con mucha más frecuencia son los estructurados a manera de vector ( arreglo unidimensional ) y los estructurados a manera de matriz ( arreglo bidimensional ), así, aunque en C++ se pueden crear estructuras multidimensionales, en este capítulo solo trataremos con vectores y matrices.

[editar] Arreglo unidimensional


Una arreglo uni-dimensional es aquel en donde los componentes son accesados por medio de uno y solamente un índice que apunte al componente requerido. Los arreglos de este tipo son conocidos también con el nombre de vectores. Conceptualmente, podemos pensar en un arreglo unidimensional como en una lista compuesta de líneas o filas en donde para referinos a una de ellas emplearemos un número para indicar la posición de la misma dentro de la lista. Por ejemplo, consideremos el caso de la tabla o arreglo VentaSemanal, la cual está pensada para registrar las ventas de cada uno de los días de la semana. Luego, de manera conceptual podemos ver al arreglo como se muestra en seguida.

Nota: en C++ los arreglos estan basados en 0 ( cero ), es decir, el primer elemento de un arreglo se indexa mediante el 0, y el índice para el último de los elementos es igual al número de componentes menos uno.

arreglo: VentaSemanal

+------+
| dato | <-- componente 0, ( fila 0 )
|------|
| dato | <-- componente 1, ( fila 1 )
|------|
| dato | ...
|------|
| dato | ...
|------|
| dato | ...
|------|
| dato | ...
|------|
| dato | <-- componente 6, ( fila 6 )
|------|

Si en el arreglo VentaSemanal queremos que el elemento 4 ( por ejemplo ) contenga el valor de 8987 lo podemos lograr con la instrucción: VentaSemanal[4] = 8987; y el estado del arreglo sería:

arreglo: VentaSemanal

+------+
| dato |
|------|
| dato |
|------|
| dato |
|------|
| dato |
|------|
| 8987 | <--- componente 4
|------|
| dato |
|------|
| dato |
|------|

[editar] Arreglo bidimensional


Una arreglo bi-dimensional es aquel en donde los componentes son accesados por medio de una pareja de índices que apunten a la fila y columna del componente requerido. Los arreglos de este tipo son conocidos también con el nombre de matrices. Conceptualmente, podemos pensar en un arreglo bidimensional como en una lista compuesta de filas y columnas, en donde para referinos a una de ellas emplearemos un número para indicar la posición de fila y otro número para indicar la posición de la columna del componente deseado. Por ejemplo, consideremos el caso de la tabla o arreglo VentaSemanaQ, la cual está pensada para registrar las ventas de cada uno de los días de la semana por cuatro semanas, o sea , una tabla de 7 x 4 elementos. Luego, de manera conceptual podemos ver al arreglo como se muestra en seguida.

arreglo: VentaSemanaQ

           C O L U M N A S  

        +--- componente ( 0, 0 )
        |
    +------+------+------+------+
    | dato | dato | dato | dato |
    |------|------|------|------|
 F  | dato | dato | dato | dato |
    |------|------|------|------|
 I  | dato | dato | dato | dato |
    |------|------|------|------| 
 L  | dato | dato | dato | dato |
    |------|------|------|------|
 A  | dato | dato | dato | dato |
    |------|------|------|------|
 S  | dato | dato | dato | dato |
    |------|------|------|------|
    | dato | dato | dato | dato |
    +------+------+------+------+
                             |
                             +---- componente ( 6, 3 )

Si en el arreglo VentaSemanaQ queremos que el elemento de la fila 4, columna 3 ( por ejemplo ) contenga el valor de 5000 lo podemos lograr con la instrucción: VentaSemanaQ[4][3] = 5000; y el estado del arreglo sería:

arreglo: VentaSemanaQ

    +--- componente ( 0, 0 )
    |
+------+------+------+------+
| dato | dato | dato | dato |
|------|------|------|------|
| dato | dato | dato | dato |
|------|------|------|------|
| dato | dato | dato | dato |
|------|------|------|------|
| dato | dato | dato | dato |
|------|------|------|------|
| dato | dato | dato | 5000 | <-- componente ( 4, 3 )
|------|------|------|------|
| dato | dato | dato | dato |
|------|------|------|------|
| dato | dato | dato | dato |
+------+------+------+------+
                         |
                         +---- componente ( 6, 3 )

[editar] Declaración de arreglos en C, C++

En C, C++ para declarar un arreglo se emplea la sintaxis:

tipo identificador [tamaño]   = { lista de inicialización }  ;

donde,

  • tipo se refiere al tipo de datos que contendrá el arreglo. El tipo puede ser cualquiera de los tipos estándar (char, int, float, etc.) o un tipo definido por el usuario. Es más, el tipo del arreglo puede ser de una estructura creada con: struct, union y class.
  • identificador se refiere al nombre que le daremos al arreglo.
  • tamaño es opcional e indica el número de elementos que contendrá el arreglo. Si un arreglo se declara sin tamaño, el mismo no podrá contener elemento alguno a menos que en la declaración se emplee una lista de inicialización.
  • lista de inicialización es opcional y se usa para establecer valores para cada uno de los componentes del arreglo. Si el arreglo es declarado con un tamaño especifíco el número de valores inicializados no podrá ser mayor a dicho tamaño.

Ejemplos:

int  intA[5];
long longA[5] = { 1, 2, 3, 4, 5 };
char charA[]  = { 'a', 'b', 'c' );

[editar] Iteraciones dentro de un arreglo (vector)

El termino Iterar se refiere al hecho de acceder ( con el fin de leer o escribir) sobre cada uno de los componentes de un arreglo. Así, para poner un ejemplo reconsideremos el caso de la tabla VentaSemanal (vista en una sección anterior), y que dicho sea de paso es un arreglo de 7 elementos de tipo double. Luego, vamos a mostrar como ejemplo un programa completo en el cual se declara el arreglo mencionado con valores inicializados, mismos que serán mostrados en pantalla y al final la suma de estos. Observe que la variable i usada para iterar dentro del arreglo va desde 0 hasta FILAS - 1 ( FILAS es el tamaño del arreglo ).

Nota: por motivos de simplificación el programa está escrito al estilo de C estándar. Sin embargo puede ser compilado y ejecutado en un compilador de C++.

#include <stdio.h>
#include <stdlib.h>
 
#define FILAS 7
 
int main()
{
    float ventas[FILAS] = {
    123.50, 234.60, 345.45, 321.40, 345.00, 456.65, 0.0 };
 
    float total = 0;
    int i;
 
    puts("Ventas de la semana");
    puts("-------------------");
 
    for (i=0; i<FILAS; i++) {
        total += ventas[i];
        printf( "%8.2f\n", ventas[i] );
    }
 
    puts("--------");
    printf("%8.2f\n", total );
 
    system("pause");
    return 0;
}
 
Esta es la salida del programa:
Ventas de la semana
-------------------
  123.50
  234.60
  345.45
  321.40
  345.00
  456.65
    0.00
--------
 1826.60

[editar] Iteraciones dentro de un arreglo (matriz)

Con el fin de leer o escribir sobre cada uno de los componentes de una matriz se deben crear dos ciclos de iteración. Así, para poner un ejemplo reconsideremos el caso de la tabla VentaSemanaQ (vista en una sección anterior), y que dicho sea de paso es un arreglo de 7 x 4 elementos de tipo double. Luego, vamos a mostrar como ejemplo un programa completo en el cual se declara el arreglo mencionado con valores inicializados, mismos que serán mostrados en pantalla y al final la suma de estos. Observe que en este caso se utilizan dos variables, una para iterar sobre las filas y otra para iterar sobre las columnas de la matriz.

#include <stdio.h>
#include <stdlib.h>
 
#define FILAS 7
#define COLS  4
 
int main()
{
    float VentaSemanaQ[FILAS][COLS] = {
    123.50, 234.60, 345.45, 321.40,
    345.00, 456.65, 123.50, 234.60,
    345.45, 321.40, 345.00, 456.65,
    123.50, 234.60, 345.45, 321.40,
    345.00, 456.65, 123.50, 234.60,
    345.45, 321.40, 345.00, 456.65,
    0.0, 0.0, 0.0, 0.0 };
 
    float totales[COLS] = { 0.0, 0.0, 0.0, 0.0 };
    float grantotal = 0;
 
    int f, c, t = 0 ; /* indices para filas, columnas y totales */
 
    puts("Ventas de cuatro semanas");
    puts("------------------------");
 
    for (f=0; f<FILAS; f++) {
        for (c=0; c<COLS; c++) {
            totales[c] += ventas[f][c];
            printf("%8.2f  ", ventas[f][c] );
        }
        puts("");
    }
 
    puts("--------------------------------------");
    for (t=0; t<COLS; t++) {
        printf("%8.2f  ", totales[t] );
        grantotal += totales[t];
    }
 
    printf("\n\nGran total: %10.2f\n", grantotal);
    system("pause");
    return 0;
}
 
 
Salida del programa:
 
Ventas de cuatro semanas
------------------------
  123.50    234.60    345.45    321.40
  345.00    456.65    123.50    234.60
  345.45    321.40    345.00    456.65
  123.50    234.60    345.45    321.40
  345.00    456.65    123.50    234.60
  345.45    321.40    345.00    456.65
    0.00      0.00      0.00      0.00
--------------------------------------
 1627.90   2025.30   1627.90   2025.30
 
Gran total:    7306.40

[editar] Cadenas de caracteres

En C,C++ las cadenas de caracteres no son más que arreglos de caracteres, salvo que a este tipo de arreglos el compilador les da un tratamiento especial. Usted puede manipular las cadenas de caracteres de la misma manera en que manipula cualquier otro tipo de arreglo, sin embargo, es preferible hacer uso de una librería estándar especialmente escrita para manipulacion de cadenas de caracteres, me refiero a la librería <string.h> y que viene incluida con todo compilador de C,C++.

Para comenzar y antes de ver algunas de las funciones de la mencionada librería, tenemos los siguientes ejemplos:

1. char   nombre[]  = "Oscar";
2. char   nombre2[] = { 'O', 's', 'c', 'a', 'r', '\0' };
  • En el ejemplo 1 se está declarando la variable nombre como una cadena de caracteres y cuyo contenido inicial es "Oscar".
  • En el ejemplo 2 se está declarando la variable nombre2 como una cadena de caracteres y cuyo contenido inicial es { 'O', 's', 'c', 'a', 'r', '\0' };.

En ambos casos el resultado es el mismo, es decir, al final se obtiene la misma cadena, pero usted debe poner atención al hecho de que toda cadena de caracteres en C,C++ debe terminar con el caracter NULL, mismo que normalmente es igual a cero y se puede escribir como '\0'. Ahora bien, cuando usted usa la sintaxis mostrada en el ejemplo 1 no tiene que preocuparse por agregar el caracter NULL, ya que esto lo hace el compilador automáticamente.

[editar] La biblioteca string

Los compiladores de C, C++ dan soporte a la biblioteca de funciones <string.h>, misma que accesible por medio de la directiva #include <string.h>. No veremos en detalle todas las funciones contenidas en dicha biblioteca, y nos limitaremos a mostrar algunos ejemplos de ciertas funciones importantes.


strlen(): Obtener longitud de cadenas

Sintaxis: size_t strlen(const char *s);
Comentarios: La función strlen() devuelve la longitud de la cadena s.

Ejemplo:

char  *nombre = "Oscar E. Palacios";
cout  << strlen(nombre) << endl;

strcpy(): Copiar cadenas

Sintaxis: char *stpcpy(char *dest, const char *src);
Comentarios: stpcpy copia la cadena src hacia dest, la función termina hasta haber encontrado en src el caracter de terminación null.

Ejemplo:

char  *nombre = "Oscar E. Palacios";
char  copia[80];
strcpy(copia, nombre);
cout  << copia << endl;

strcat(): Concatenar cadenas

Sintaxis: char *strcat(char *dest, const char *src);
Comentarios: strcat agrega la cadena src a dest, la función termina hasta haber encontrado en src el caracter de terminación null.

Ejemplo:

char  nombre[]  = "Oscar E.";
char  copia[80] = " Palacios";
strcat(copia, nombre);
cout  << copia << endl;

strlwr(): Convertir a minúsculas.

Sintaxis: char *strlwr(char *dest);
Comentarios: strlwr convierte todos los caracteres alfabéticos ( 'A' .. 'Z' ) en dest a sus correspondientes caracteres alfabéticos ( 'a' .. 'z' ).

Ejemplo:

char  nombre[]  = "Oscar E. Palacios";
strlwr(nombre);
cout  << nombre << endl;

strupr(): Convertir a mayúsculas.

Sintaxis: char *strupr(char *dest);
Comentarios: strupr convierte todos los caracteres alfabéticos ( 'a' .. 'z' ) en dest a sus correspondientes caracteres alfabéticos ( 'A' .. 'Z' ).

strchr(): Buscar caracter ( hacia adelante )

Sintaxis: char *strchr(char *s, int c);
Comentarios: strchr busca en s el caracter c. La busqueda se lleva a cabo desde el inicio hasta el final de s.
Regreso: si la operación es exitosa strchr regresa un puntero hacia la primera ocurrencia de c en s, en caso contrario strchr regresa null.

Ejemplo:

char  nombre[]  = "Oscar E. Palacios";
char  *p;
 
p := strchr(nombre, 'E'):
if (p) {
         cout << "nombre contiene a E" << endl;
         cout << "indice = " << (p - nombre) << endl;
       }
else cout << "E no está en nombre" << endl;


strrchr(): Buscar caracter ( hacia atras )

Sintaxis: char *strrchr(char *s, int c);
Comentarios: strchr busca en s el caracter c. La busqueda se lleva a cabo desde el final hasta el inicio de s.
Regreso: si la operación es exitosa strchr regresa un puntero hacia la última ocurrencia de c en s, en caso contrario strchr regresa null.

Ejemplo:

char  nombre[]  = "Oscar E. Palacios";
char  *p;
 
p := strrchr(nombre, 'E'):
if (p) {
         cout << "nombre contiene a E" << endl;
         cout << "indice = " << (p - nombre) << endl;
       }
else cout << "E no está en nombre" << endl;


strstr(): Buscar subcadena

Sintaxis: char *strstr(const char *s1, char *s2);
Comentarios: strstr busca en s1 la subcadena s2. La busqueda se lleva a cabo desde el el inicio hasta el final de s1.
Regreso: si la operación es exitosa strstr regresa un puntero hacia la primera ocurrencia de s2 en s1, en caso contrario strstr regresa null.

Ejemplo:

char  s[]  = "Un barco de tristeza";
char  *p;
 
p = strstr(s, "barco"):
if (p) {
         cout << "barco está en s" << endl;
         cout << "indice = " << (p - s) << endl;
       }
else cout << "barco no está en s" << endl;

[editar] Cadenas en C++

En la sección anterior descubrimos algunas funciones para trabajar con cadenas de caracteres al estilo de C estándar, si bien no está de más tener tal conocimiento tambien es cierto que C++ es un lenguaje de programacíón orientado al objeto, de tal manera que ciertos compiladores ( como el gcc, utilzado por Bloodshed Dev-C++ y otros tantos entornos de desarrolo ) dan soporte a la clase cstring, que no debe confundires con la <string.h>.

Nota: Bloodshed Dev-C++ es un IDE (Editor con Depurador Integrado) para programar en C++ en un ambiente gráfico para Windows, distibuido gratuitamente bajo licencia GPL GNU y usted puede encontrarlo aquí: www.bloodshed.net. Actualmente (febrero de 2008) se recomienda bajar la versión Dev-C++ 4.9.9.2.

Una de las ventajas que ofrece la clase cstring es que, a diferencia de las cadenas estándar, ésta posee la capacidad de crecer o disminuir su tamaño en tiempo de ejecución. Además, entre otras caracteristicas destacables, la clase string soporta operaciones de asignación tales como: =, +, +=, etc.; y de comparación tales como: ==, <=, etc.

Para tener una idea básica sobre las cadenas en C++ veamos el siguiente programa:

Nota: en el programa se debe de observar el uso del operador de asignación +=, algo que no es posible hacer con las cadenas estándar.
// Ejemplo: demostración de la clase string
// Compilado y ejecutado con exito en Bloodshed Dev-C++
#include <cstdlib>
#include <iostream>
 
using namespace std;
 
int main(int argc, char *argv[])
{
    string s("Hola, ");
    s += "cómo estan ustedes...";
    cout << s << endl;
    system("PAUSE");
    return EXIT_SUCCESS;
}

Un estudio exaustivo sobre la clase string requiere de un capítulo completo, ya que la misma, según el manual de referencia de C++, posee aproximadamente 33 métodos y unos 7 constructores; además de los atributos.

[editar] Arreglos en C++

Así como C++ da aternativas elegantes para la manipulación de cadenas de caracteres, también da el soporte para la manipulacíon de arreglos dinámicos. Este tema será ampliado en el capítulo Libreria de Plantillas Estándar STL, sin embargo para tener una idea de lo que vendrá mostraremos aquí un ejemplo sencillo en donde se usará la clase plantilla vector.

// Ejemplo: demostración de la clase vector
// Compilado y ejecutado con exito en Bloodshed Dev-C++
#include <cstdlib>
#include <iostream>
#include <vector>
 
using namespace std;
 
int main(int argc, char *argv[])
{
    // creación de un vector de enteros
    vector<int> v;
 
    // metiendo datos en el vector
    for (int x = 500; x<1000; x+=50)
        v.push_back(x);
 
    // desplegando los datos del vector
    for (int x = 0; x < v.size(); x++)
        cout << "v[" << x << "] = " << v[x] << endl;
 
    system("PAUSE");
    return EXIT_SUCCESS;
}
Streams Arriba Desarrollo Orientado a Objetos
Herramientas personales