Sunteți pe pagina 1din 15

Programacion en C++ : Arreglos Dinamicos Superoptimo: El mejor sitio para aprender a programar Programacion en C/C++ Programacion en C++ : Arreglos

os Dinamicos En c++, las cadenas de texto se representan con arreglos de caracteres. Estos caracteres son representados en memoria como valores enteros ASCII. Los arreglos de caracteres deben tener en la ultima posicin el caracter nulo (0 en cdigo ASCII). Un arreglo como el siguiente:
char cadena[200]; cadena[0] = 0;

Es equivalente a una cadena vacia, a pesar de que tiene asignado un buffer de memoria de 200. El caracter 0 marca el final de esa cadena. Una constante como "" es tambin equivalente a una cadena vacia de longitud 0. En el siguiente ejemplo se representa una cadena de texto de 5 caracteres:
char cadena[100] = {'c', 'a', 'm', 'p', 'o', 0};

Notese que cada letra est delimitada por comillas simples ('). Y aunque la palabra "campo" tiene 5 caracteres, el arreglo se asignado con una mayor capacidad de caracteres. En el siguiente fragmento, se modifica el anterior arreglo para componer una cadena mas larga:
cadena[5] = ' '; cadena[6] = 's'; cadena[7] = 'a'; cadena[7] = 'n'; cadena[7] = 't'; cadena[7] = 'o'; cadena[7] = 0;// fin de cadena

La forma anterior de declarar arreglos limita el tamao del arreglo de forma predefinida sin posibilidad de cambiar sus dimensiones. Por eso existe un mecanismo para declarar arreglos dinmicos cuyo tama no es constante sino mas bien depende de algn parametro o variable:
char * cadena_dinamica = NULL; // arreglo vacio. int cantidad = 0; //obtenemos un valor de cantidad capturado de consola cout<< "Por favor digite el tamao del arreglo "; cin>>cantidad; // creamos el arreglo dinmico con el parametro capturado cadena_dinamica = new char[cantidad];

En el codigo anterior creamos un arreglo dinmico cuyo numro de elementos es especificado como usuario. Notese que cadena dinmica se declara como un apuntador

de memoria, el cual har referencia al espacio de memorio creado con la instruccin "new char[cantidad]". Sin embargo, se requiere liberar la memoria asignada del arreglo cuando finalize nuestra aplicacin o cuando el arreglo no tenga ms utilidad. Recurrimos entonces a la siguiente rutina de liberacin de recursos:
delete [] cadena_dinamica; // liberamos la memoria de la cadena cadena_dinamica = NULL;

Esta clase ArregloCaracteres tiene mecanismos para manipular una cadena con un tamao variable de forma segura y controlada. Como invariante se tiene que la cadena de este objeto siempre estar terminada en null. A continuacion encontrarn el cdigo fuente de una implementacion de arreglos dinmicos para c++: ArregloDinamico_20080425.zip

Metodologa
Usted deber leer el presente documento e ir corriendo los programas en C++, cuidando de leer bien las instrucciones y tratar de entenderlas por completo. Est escrito de una forma escalonada para que alcance el conocimiento de C++ y programacin por objetos de forma progresiva. Se recomiendo leerlo con cuidado, porque aunque no es demasiado extenso si contiene mucha informacin que usted debe ir asimilando. Si va muy rpido llegar un punto en que no entender. Resuelva los ejercicios y presntelos al profesor.

El Primer Programa
El programa ms sencillo en C++ sera el siguiente: prog1
main () { cout << "Hola" << endl; }

Sin embargo da un error que seala que cout no est definido. Eso significa que no tiene incluida la librera de iostream.h. prog2
# include "iostream.h" main () { cout << "Hola" << endl; }

La librera iostream.h es la primera librera de C++ que se usar y permite entre otras cosas el uso de las instrucciones cin y cout para la entrada de datos. Dentro de este programa podremos definir variables globales que pueden ser de tipo primitivos, estructuras, clases y apuntadores.

Definicin de un tipo primitivo


Los tipos primitivos de datos son int, short, float, byte, char, etc. A continuacin hay una definicin de una variable global de un tipo primitivo. prog3
# include "iostream.h" int variableGlobal = 0; main () { int variableLocal = 5; cout << "El valor global es:" << variableGlobal << endl; cout << "El valor local es:" << variableLocal << endl; }

Se ha definido una variable global de un tipo primitivo, as como una variable local que son mostradas por pantalla.

Definicin de una estructura


prog4
# include "iostream.h" struct Estructura1 { int campoEntero; char campoCaracter; float campoFlotante; }; main () { struct Estructura1 registro; registro.campoEntero = 4; registro.campoCaracter = 63; registro.campoFlotante = 5; cout << "Campo Entero:" << registro.campoEntero << endl; cout << "Campo Caracter:" << registro.campoCaracter << endl; cout << "Campo Flotante:" << registro.campoFlotante << endl; }

En este caso se define una estructura con tres campos uno entero, otro de caracter y otro flotante. Posteriormente se les asigna un valor a cada uno y luego se muestra por pantalla. (Identifique cada una de las acciones dentro del codigo).

Definicin de una clase


prog5
# include "iostream.h" class Clase1 { public: int campoEntero; char campoCaracter; float campoFlotante; }

main () { Clase1 registro; registro.campoEntero = 4; registro.campoCaracter = 3; registro.campoFlotante = 5; cout << "Campo Entero:" << registro.campoEntero << endl; cout << "Campo Caracter:" << registro.campoCaracter << endl; cout << "Campo Flotante:" << registro.campoFlotante << endl; }

En este caso se define una clase con tres campos: uno entero, otro de caracter y otro flotante. Posteriormente se les asigna un valor a cada uno y luego se muestra por pantalla. (Identifique cada una de las acciones dentro del codigo).

Ejercicio No. 1

Escriba las similitudes y diferencias entre la definicin de una estructura y la definicin de una clase.

Definicin de un apuntador
Un apuntador en C++ es una variable que guarda la direccin de un valor en memoria. Esto crea una distincin entre las variables por valor como la siguiente:
int a,b;

y las variables por referencia

int *c,*d;

Las variables a y b, guardan directamente el valor de la variable, en cambio, c y d guardan la direccin donde el sistema operativo ha guardado el valor de la variable.

Apuntadores a valores primitivos


Una variable por valor (es decir, que no usa apuntadores) tiene varias fases en su uso:
o o o o

definicin: la variable se define con un tipo de dato: int a asignacin: se le asigna un valor: a = 5 uso: se usa el valor de la variable: a = a+1; a++; comparacin: el valor se compara con otra variable o con un valor: (a == 3); (a != b);

Una variable por refencia o apuntador tiene otras fases en su uso:


o o

definicin: la variable se define con un tipo de dato: int *b; localizacin de memoria: Debe primero localizarse memoria para la variable del tamao adecuado que es el tamao del tipo: b
= new int;

o o o o

asignacin: se le asigna un valor: *b = 5 uso: se usa el valor de la variable: *b = *b+1; *b++; comparacin: el valor se compara con otra variable o con un valor: (*b == 3); (*b != a); liberacin de la memoria: Luego de usar la memoria esta debe devolverse al sistema operativo: delete b;

prog6
# include "iostream.h" main () { // definicin de las variables int a,*b; // localizacin de la memoria necesaria (solo para el apuntador) b = new int(0); // asignacin de los valores a = 5; *b = 123; // uso de las variables. Se procesa algo de informacin a++; *b = a * a; a = (*b)--; // comparacin if (a == 36) cout << "el valor de a es correcto:" << a << endl; if (*b != a)

cout << "el programa original est bien" << endl; cout << "los valores son: " << a << " y " << *b << endl; // liberacin de memoria usada (solo para el apuntador) delete b; }

Apuntadores a estructuras
Cuando se usan apuntadores a estructuras el manejo de los campos vara. Cuando se usan campos de estructuras sin apuntador se hace de la siguiente forma: Usando una definicin como la siguiente:
struct Registro { int edad; char letra; float numero; }

Tendremos una variable estructura sin usar apuntador.


// creacin de la variable struct Registro miRegistro; // uso del campo miRegistro.edad = 18;

Cuando se usa una variable con apuntador a un registro ya no se usa el punto para conectar el nombre de la variable y el campo, sino la flecha compuesta por un guin y el smbolo de mayor as: "->". Observe como se accede al campo. Es importante resaltar la localizacin de la memoria
// creacin de la variable struct Registro *miApuntador; // localizacin de la memoria miApuntador = new struct Registro; // uso del campo. miApuntador->edad = 18;

Los apuntadores a estructuras tienen los mismos pasos que los apuntadores a tipos primitivos. Por favor estudie el siguiente programa: prog7
# include "iostream.h" struct Registro { int edad; char letra; float numero; } main () { // definicin de las variables

struct Registro *miRegistro; // localizacin de la memoria necesaria miRegistro = new struct Registro; // asignacin de los valores miRegistro->edad = 18; miRegistro->letra = 'B'; miRegistro->numero = 3.5; // uso de las variables. Se procesa algo de informacin miRegistro->edad++; miRegistro->letra+=6; miRegistro->numero=miRegistro->numero / 2; cout << " La edad es : " << miRegistro->edad << endl; cout << " La letra es: " << miRegistro->letra << endl; cout << " El numero es: " << miRegistro ->numero << endl; // comparacin if (miRegistro->edad < 18) cout << "Tenemos un menor de edad:" << miRegistro->edad << endl; else cout << "Tenemos a un mayor de edad:" << miRegistro->edad << endl; if (miRegistro->letra < 70) cout << "La letra es:" << miRegistro->letra << endl; // liberacin de memoria usada delete miRegistro; }

NOTA: Leyendo los comentarios del programa usted debe ser capaz de entender lo que est haciendo el programa.

Ejercicio Resuelto A

Transforme este programa en: a) un programa que use apuntadores a enteros; b) un programa que usa una un apuntador a una estructura cuyos campos son a y b. c) un programa que usa una clase con dos campos pblicos a y b
#include "iostream.h" main() { int existencia,vendidos; cout << "Escriba un valor entero:"; cin >> existencia; vendidos = 10; existencia++; cout << "El valor de la suma de existencia y vendidos es " existencia + vendidos; }

<<

Solucin

a) apuntadores a tipos primitivos


#include "iostream.h"

main() { int *existencia,*vendidos; existencia = new int; vendidos = new int; cout << "Escriba un valor entero:"; cin >> *existencia; *vendidos = 10; (*existencia)++; cout << "El valor de la suma de existencia y vendidos es " *existencia+*vendidos; }

<<

b) apuntadores a estructuras
#include "iostream.h" struct Estructura { int existencia,vendidos; } main() { struct Estructura *estruc1; estruc1 = new struct Estructura; cout << "Escriba un valor entero:"; cin >> estruc1->existencia; estruc1->vendidos = 10; estruc1->existencia++; cout << "El valor de la suma de existencia y vendidos es " estruc1->existencia+estruc1->vendidos << endl; }

<<

c) clase
#include "iostream.h" class Clase { public: int existencia,vendidos; } main() { Clase estruc1; cout << "Escriba un valor entero:"; cin >> estruc1.existencia; estruc1.vendidos = 10; estruc1.existencia++; cout << "El valor de la suma de existencia y vendidos es " estruc1.existencia + estruc1.vendidos << endl; }

<<

Ejercicio No. 2

Transforme este programa en: a) un programa que use apuntadores a enteros; b) un programa que usa una un apuntador a una estructura cuyos campos son

perros, gatos, pajaritos y mamiferos. c) un programa que usa una clase con dos campos pblicos perros, gatos, pajaritos y mamiferos.
#include "iostream.h" // Guarderia veterinaria "mi primer mundo" main() { int perros,gatos,pajaritos,mamiferos; cout << "Cuantos perros hay en la guardera:"; cin >> perros; cout << "Cuantos gatos hay en la guardera:"; cin >> gatos; cout << "Cuantos pajaritos hay en la guardera:"; cin >> pajaritos; mamiferos = perros + gatos cout << "El valor de la suma de existencia y vendidos es " mamiferos+pajaritos; }

<<

Creacin de arreglos dinmicos


Arreglos dinmicos unidimensionales
Los arreglos estticos (que no usan apuntadores se definan y usaban tal como explica el siguiente programa: prog8
#include "iostream.h" main() { // definicion del arreglo int arreglo[5]; // llenado del arreglo arreglo[0] = 1; arreglo[1] = 3; arreglo[2] = 89; arreglo[3] = 24; arreglo[4] = 16; // uso de los datos del arreglo for (int j=0; j<5; j++) { cout << arreglo[j] << endl; } }

Los nuevos arreglos dinmicos se definen como un apuntador y tienen una instruccin adicional de localizacin de memoria antes de poder usar los datos. Como todos los apuntadores deben tener una instruccin para devolver el espacio pedido al sistema operativo.

prog9
#include "iostream.h" main() { // definicion del arreglo int *arreglo; // localizacin en memoria arreglo = new int[5]; // llenado del arreglo arreglo[0] = 1; arreglo[1] = 3; arreglo[2] = 89; arreglo[3] = 24; arreglo[4] = 16; // uso de los datos del arreglo for (int j=0; j<5; j++) { cout << arreglo[j] << endl; } delete arreglo; }

Ejercicio Resuelto B

Explicar porqu el siguiente programa no est bien:


#include "iostream.h" main() { char vector; vector= new char[5]; for (i = 0; i < 5; i++) vector[i] = i*i; for (i = 0; i < 5; i++) cout << vector[i] << endl; }

Respuesta:

Razones en las que falla el programa:


La variable vector est definida como un caracter, y no como un apuntador a caracter El vector que se supone es dinmico no es liberado mediante un delete vector antes de terminar el programa.

Matrices dinmicas
Para declarar una matriz dinmica (2-dimensiones) tenemos que definir la variable con un doble asterisco anterior. Se debe tener en cuenta que para localizar la memoria primero se debe localizar un vector y luego por cada posicin del vector se inicializa un nuevo vector formando as las filas y las columnas. a continuacin hay un ejemplo. Supongamos una matriz de enteros de 5x4 posiciones, el manejo se har de la siguiente forma: prog10
#include "iostream.h" main() { // definicion de la matriz. Se usa doble asterisco para indicar que es // apuntador con dos dimensiones int **matriz; // localizacin en memoria. En las matrices dinmicas se debe localizar primero // una dimensin matriz = new int*[5]; // y luego la otra. Observe como cada posicin del primer arreglo localizado crea // un nuevo arreglo de 4 posiciones. matriz[0] = new int[4]; matriz[1] = new int[4]; matriz[2] = new int[4]; matriz[3] = new int[4]; matriz[4] = new int[4]; // llenado del arreglo. Ahora se llena el arreglo con una funcin // f(i,j) = (i*i) + j int i,j; for (i=0; i<5; i++) for (j=0; j<4; j++) matriz[i][j] = i*i+j; // uso de los datos del arreglo (mostrarlos en pantalla) for (i=0; i<5; i++) { for (j=0; j<4; j++) cout << matriz[i][j] << " "; cout << endl; } }

Estos arreglos dinmicos tienen la ventaja de permitir que su longitud sea escogida al momento de ejecucin y no ser conocido de antemano por el programador.

Uso de funciones
Las funciones permiten encapsular fragmentos de cdigo que van a permitir cortar el cuerpo de un programa para que no quede completamente en el main del programa. Vamos a hacer una conversin de un programa que ya hallamos mirado antes y vamos a convertir en funcin fragmentos del cdigo. Retomamos el programa 4 de esta lectura que a continuacin recordamos. prog4
# include "iostream.h" struct Estructura1 { int campoEntero; char campoCaracter; float campoFlotante; }; main () { struct Estructura1 registro; registro.campoEntero = 4; registro.campoCaracter = 63; registro.campoFlotante = 5; cout << "Campo Entero:" << registro.campoEntero << endl; cout << "Campo Caracter:" << registro.campoCaracter << endl; cout << "Campo Flotante:" << registro.campoFlotante << endl; }

Ahora vamos a crear dos funciones que se van a encargar de inicializar los campos del registro y posteriormente otra funcin se encargar de mostrar los resultados prog11
# include "iostream.h" struct Estructura1 { int campoEntero; char campoCaracter; float campoFlotante; } registro; // void inicializarRegistro(int p1, char p2, float p3) { registro.campoEntero = p1; registro.campoCaracter = p2; registro.campoFlotante = p3; } void mostrarDatos(){ cout << "Campo Entero:" << registro.campoEntero << endl; cout << "Campo Caracter:" << registro.campoCaracter << endl; cout << "Campo Flotante:" << registro.campoFlotante << endl; }

main () { inicializarRegistro(4,63,5); mostrarDatos(); }

Si observa los programas 4 y 11, el main que originalmente era as:


main () { struct Estructura1 registro; registro.campoEntero = 4; registro.campoCaracter = 63; registro.campoFlotante = 5; cout << "Campo Entero:" << registro.campoEntero << endl; cout << "Campo Caracter:" << registro.campoCaracter << endl; cout << "Campo Flotante:" << registro.campoFlotante << endl; }

Luego de usar las funciones se convierte en esto:


main () { inicializarRegistro(4,63,5); mostrarDatos(); }

Es importante anotar que la variable local registro se convierte en una variable global en el caso de las funciones. Esto es porque no es pasada como parmetro a las funciones.

Ejercicio No. 3

Hacer una versin del programa 11 en el cual la variable de estructura registro no es una variable global sino local. prog11
# include "iostream.h" struct Estructura1 { int campoEntero; char campoCaracter; float campoFlotante; } registro; // void inicializarRegistro(int p1, char p2, float p3) { registro.campoEntero = p1; registro.campoCaracter = p2; registro.campoFlotante = p3; } void mostrarDatos(){ cout << "Campo Entero:" << registro.campoEntero << endl; cout << "Campo Caracter:" << registro.campoCaracter << endl;

cout << "Campo Flotante:" << registro.campoFlotante << endl; } main () { inicializarRegistro(4,63,5); mostrarDatos(); }

Ejercicio Resuelto C

Elaborar un programa en C++ que lea dos variables enteras long1i y long2. Utilizando estas dos variables, crear dinmicamente dos arreglos palabra1[] y palabra2[]. Luego de tener en la memoria dinmica los dos arreglos, escriba las instrucciones necesarias para leer dos palabras. La primera palabra la almacena en el arreglo palabra1[] y la segunda palabra la almacena en el arreglo palabra2[]. El programa debe escribir la palabra "homfonas" en caso de que las palabras almacenadas en los arreglos lo sean, de lo contrario debe escribir el literal "no homfonas". una palabra ses homfona si tiene el mismo sonido pero est escrita con diferentes consonantes. Por ejemplo, atajo y hatajo, vacilo y bacilo.
Solucin:

Los pasos para la solucin del problema son los siguientes: 1. Leer las variables long1 y long2, que definirn el tamao del arreglo dinmico. 2. Crear los dos arreglos palabra1[] y palabra2[], y localizar la memoria correspondiente. 3. Leer las dos palabras y almacenarlas en palabra1 y en palabra2 correspondientemente. 4. Detectar si las palabras son homfonas y mostrar el resultado. Inicialmente no hemos resuelto como comparar si son homfonas o no.
#include "iostream.h" int homofonas(char *p1, char* p2) { // retornara 1 si son homofonas y 0 si no. // Esta funcion no ha sido resuelta. return 1; } main() { // 1. Leer las variables long1 y long2, que definirn el tamao del // arreglo dinmico. int long1,long2; cout << "Escriba la longitud del primer arreglo:"; cin >> long1; cout << "Escriba la longitud del segundo arreglo:"; cin >> long2;

// 2. Crear los dos arreglos palabra1[] y palabra2[], y localizar la // memoria correspondiente. Observe el tamao del vector que es la // variable que nos dan char *palabra1,*palabra2; palabra1 = new char[long1]; palabra2 = new char[long2]; // 3. Leer las dos palabras y almacenarlas en a y en b correspondientemente. cout << "Escriba la primera palabra:"; cin >> palabra1; cout << "Escriba la sengunda palabra:"; cin >> palabra2; // 4. Detectar si las palabras son homfonas. Hacemo uso de una funcin // llamada homofonas que devuelve un entero (1:homofonas, 0:no homofonas) // Esta funcion inicialmente no est implementada deber hacerla usted. if (homofonas(palabra1,palabra2)) cout << "homofonas"; else cout << "no homofonas"; return 0; }

S-ar putea să vă placă și