Site hosted by Angelfire.com: Build your free website today!
[ Volver al indice de C++ ]

Capítulo 1. Introducción a C++

Juan Carlos Diaz
jcdiaz@cable.net.co

Metodología

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 programación por objetos de forma progresiva. Se recomiendo leerlo con cuidado, porque aunque no es demasiado extenso si contiene mucha información que usted debe ir asimilando. Si va muy rápido llegará un punto en que no entenderá.

Resuelva los ejercicios y preséntelos al profesor.
 

El Primer Programa

El programa más sencillo en C++ sería el siguiente:

prog1

main () {
 cout << "Hola" << endl;
}

Sin embargo da un error que señala que cout no está definido. Eso significa que no tiene incluida la librería de iostream.h.

prog2

# include "iostream.h"

main () {
 cout << "Hola" << endl;
}

La librería iostream.h es la primera librería 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.
 

Definición de un tipo primitivo


Los tipos primitivos de datos son int, short, float, byte, char, etc. A continuación hay una definición 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.
 

Definición 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).
 

Definición 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 definición de una estructura y la definición de una clase.

Definición de un apuntador

Un apuntador en C++ es una variable que guarda la dirección de un valor en memoria. Esto crea una distinción 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 dirección 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:
    • definición: la variable se define con un tipo de dato: int a
    • asignación: se le asigna un valor: a = 5
    • uso: se usa el valor de la variable: a = a+1; a++;
    • comparación: 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:

    • definición: la variable se define con un tipo de dato: int *b;
    • localización de memoria: Debe primero localizarse memoria para la variable del tamaño adecuado que es el tamaño del tipo: b = new int;
    • asignación: se le asigna un valor: *b = 5
    • uso: se usa el valor de la variable: *b = *b+1; *b++;
    • comparación: el valor se compara con otra variable o con un valor: (*b == 3); (*b != a);
    • liberación de la memoria: Luego de usar la memoria  esta debe devolverse al sistema operativo: delete b;
    prog6

    # include "iostream.h"

    main () {
      // definición de las variables
     int a,*b;
      // localización de la memoria necesaria (solo para el apuntador)
     b = new int(0);
      // asignación de los valores
     a = 5;
     *b = 123;
      // uso de las variables. Se procesa algo de información
     a++;
     *b = a * a;
     a = (*b)--;
      // comparación
     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;
      //  liberación de memoria usada (solo para el apuntador)
     delete b;
    }
     

Apuntadores a estructuras

Cuando se usan apuntadores a estructuras el manejo de los campos varía. Cuando se usan campos de estructuras sin apuntador se hace de la siguiente forma:

Usando una definición como la siguiente:

struct Registro {
 int edad;
 char letra;
 float numero;
}

Tendremos una variable estructura sin usar apuntador.

  // creación 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 guión y el símbolo de mayor así: "->". Observe como se accede al campo. Es importante resaltar la localización de la memoria

  // creación de la variable
struct Registro *miApuntador;
  // localización 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 () {
  // definición de las variables
 struct Registro *miRegistro;
  // localización de la memoria necesaria
 miRegistro = new struct Registro;
  // asignación de los valores
 miRegistro->edad = 18;
 miRegistro->letra = 'B';
 miRegistro->numero = 3.5;
  // uso de las variables. Se procesa algo de información
 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;
  // comparación
 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;
  //  liberación 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 públicos 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;
}
 

Solución
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 públicos 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 guardería:";
    cin >> perros;
    cout << "Cuantos gatos hay en la guardería:";
    cin >> gatos;
    cout << "Cuantos pajaritos hay en la guardería:";
    cin >> pajaritos;
    mamiferos = perros + gatos
    cout << "El valor de la suma de existencia y vendidos es "  << mamiferos+pajaritos;
}



 

Creación de arreglos dinámicos

Arreglos dinámicos unidimensionales


Los arreglos estáticos (que no usan apuntadores se definían 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 dinámicos se definen como un apuntador y tienen una instrucción adicional de localización de memoria antes de poder usar los datos. Como todos los apuntadores deben tener una instrucción para devolver el espacio pedido al sistema operativo.

prog9

#include "iostream.h"

main() {
    // definicion del arreglo
 int *arreglo;
    // localización 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 dinámico no es liberado mediante un delete vector antes de terminar el programa.


 

Matrices dinámicas

Para declarar una matriz dinámica (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 posición del vector se inicializa un nuevo vector formando así las filas y las columnas. a continuación 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;

    // localización en memoria. En las matrices dinámicas se debe localizar primero
    // una dimensión
 matriz = new int*[5];

    // y luego la otra. Observe como cada posición 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 función
    // 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 dinámicos tienen la ventaja de permitir que su longitud sea escogida al momento de ejecución y no ser conocido de antemano por el programador.
 

Uso de funciones

Las funciones permiten encapsular fragmentos de código que van a permitir cortar el cuerpo de un programa para que no quede completamente en el main del programa. Vamos a hacer una conversión de un programa que ya hallamos mirado antes y vamos a convertir en función fragmentos del código. Retomamos el programa 4 de esta lectura que a continuación 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 función 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 parámetro a las funciones.


Ejercicio No. 3
Hacer una versión 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 dinámicamente dos arreglos palabra1[] y palabra2[]. Luego de tener en la memoria dinámica 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 "homófonas" en caso de que las palabras almacenadas en los arreglos lo sean, de lo contrario debe escribir el literal "no homófonas". una palabra ses homófona si tiene el mismo sonido pero está escrita con diferentes consonantes. Por ejemplo, atajo y hatajo, vacilo y bacilo.
 
Solución:
Los pasos para la solución del problema son los siguientes:

1. Leer las variables long1 y long2, que definirán el tamaño del arreglo dinámico.
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 homófonas y mostrar el resultado.

Inicialmente no hemos resuelto como comparar si son homófonas 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 definirán el tamaño del
  // arreglo dinámico.
 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 tamaño 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 homófonas. Hacemo uso de una función
  // 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;
}


Ejercicio No. 4
Diseñar la función que toma las dos palabras y las compara para ver si son homófonas o no.

int homofonas(char *p1, char* p2) {
   // retornara 1 si son homofonas y 0 si no.
   // Usted deberá implementar esta función

   // ???
   // ???

 return 1;
}



 

Declaración de Clases

Las clases en C++ funciona de forma similar a las estructuras definidas con la palabra struct, pero con algunas mejoras que permiten mayor unidad de los datos. Las estructuras solo contienen datos, las clases además de contener datos, contienen las funciones que los manejan y además tienen control de acceso a dichos datos.

Veremos un ejemplo de una estructura y como se maneja para luego convertirla en una clase.

prog12

#include "iostream.h"

struct Paciente {
    int numeroHistClin;
    char *nombre;
    char *Direccion;
    char *Telefono;
    int edad;
};

main () {
 Paciente Registro1;
 Registro1.nombre = new char[50];
 Registro1.Direccion = new char[50];
 Registro1.Telefono = new char[50];

 cout << "Escriba los datos del paciente" << endl;
 cout << "Número de la historia clinica:";
 cin >> Registro1.numeroHistClin;
 cout << "Nombre del Paciente:";
 cin >> Registro1.nombre;
 cout << "Direccion:";
 cin >> Registro1.Direccion;
 cout << "Telefono:";
 cin >> Registro1.Telefono;
 cout << "Edad:";
 cin >> Registro1.edad;

 cout << endl;
 cout << "Historia Clínica No. " << Registro1.numeroHistClin << endl;
 cout << "Nombre: " << Registro1.nombre << endl;
 cout << "Direccion: " << Registro1.Direccion << endl;
 cout << "Telefono: " << Registro1.Telefono << endl;
 cout << "Edad: " << Registro1.edad << endl;

 delete Registro1.nombre;
 delete Registro1.Direccion;
 delete Registro1.Telefono;

 return 0;
}

Vamos ahora a hacer una versión de este programa con una clase que tiene todos sus campos públicos

prog13 -  clase con todos los campos públicos

#include "iostream.h"

class Paciente {
public:
    int numeroHistClin;
    char *nombre;
    char *Direccion;
    char *Telefono;
    int edad;
};

main () {
 Paciente Registro1;
 Registro1.nombre = new char[50];
 Registro1.Direccion = new char[50];
 Registro1.Telefono = new char[50];

 cout << "Escriba los datos del paciente" << endl;
 cout << "Número de la historia clinica:";
 cin >> Registro1.numeroHistClin;
 cout << "Nombre del Paciente:";
 cin >> Registro1.nombre;
 cout << "Direccion:";
 cin >> Registro1.Direccion;
 cout << "Telefono:";
 cin >> Registro1.Telefono;
 cout << "Edad:";
 cin >> Registro1.edad;

 cout << endl;
 cout << "Historia Clínica No. " << Registro1.numeroHistClin << endl;
 cout << "Nombre: " << Registro1.nombre << endl;
 cout << "Direccion: " << Registro1.Direccion << endl;
 cout << "Telefono: " << Registro1.Telefono << endl;
 cout << "Edad: " << Registro1.edad << endl;

 delete Registro1.nombre;
 delete Registro1.Direccion;
 delete Registro1.Telefono;

 return 0;
}

Aquí pueden observar que al cambiarlo a una clase con las variables públicas no cambia mucho con respecto a la estructura. (Se han resaltado los  cambios).

Las clases tienen adicionalmente la capacidad de inicializar los datos y de destruirlos, eso haría que cambiara la estructura del programa al meter una parte del main en las rutinas de constructor y destructor. Estas rutinas llevan el mismo nombre de la clase y se ejecutan al crear o destruir la variable de esta clase.

prog 14

#include "iostream.h"

class Paciente {
public:
    int numeroHistClin;
    char *nombre;
    char *Direccion;
    char *Telefono;
    int edad;
 Paciente() { // constructor. note que no lleva void
  nombre = new char[50];
  Direccion = new char[50];
  Telefono = new char[50];
 }
 void recopilarDatos () { // rutina que recopila datos
  cout << "Escriba los datos del paciente SIN ESPACIOS BLANCOS" << endl;
  cout << "Número de la historia clinica:";
  cin >> numeroHistClin;
  cout << "Nombre del Paciente:";
  cin >> nombre;
  cout << "Direccion:";
  cin >> Direccion;
  cout << "Telefono:";
  cin >> Telefono;
  cout << "Edad:";
  cin >> edad;
  cout << endl;
 }
 void mostrarDatos() { // rutina que muestra los datos por pantalla.
  cout << "Historia Clínica No. " << numeroHistClin << endl;
  cout << "Nombre: " << nombre << endl;
  cout << "Direccion: " << Direccion << endl;
  cout << "Telefono: " << Telefono << endl;
  cout << "Edad: " << edad << endl;
 }
 ~Paciente() {  // Destructor que se ejecuta al terminar el programa.
  delete nombre;
  delete Direccion;
  delete Telefono;
 }
};

    // Note que el main se ha reducido y ya solo se crea la clase y se llaman
    // dos funciones de la clase "recopilarDatos" y "mostrarDatos".
main () {
 Paciente Registro1;
 Registro1.recopilarDatos();
 Registro1.mostrarDatos();

 return 0;
}
 


Ejercicio Resuelto D
Elaborar una clase llamada Codificador, que contenga una variable privada codigo y dos funciones públicas. La primera función deber ser el constructor de la clase donde almacene la variable privada codigo el número 328 y una segunda función denominada verCodigo(), la cual devuelva al programa principal el valor de la variable privada codigo.
Solución:
class Codificador {
    int codigo;
public:
    Codificador() {
        codigo = 328;
    }
    int verCodigo() {
        return codigo;
    }
};

Ejercicio Resuelto E
Elaborar una clase denominada Alumno, la cual tenga como variables privadas un apuntador a una cadena de caracteres denominado nombre, y una variable entera llamada nota. La clase debe contener en su parte pública tres funciones: la primera, la función Alumno(), la cual recibe como parámetro una cadena de caracteres y un entero con la nota, tendrá como tarea almacenar en la memoria dinámica la cadena y el entero recibidos en el constructor. La cadena debe quedar indicada por el apuntador nombre y la nota por el entero nota. La segunda función denominada verNombre(), debe retornar la dirección e la memoria dinámica donde está almacenada la cadena indicada por el apuntador nombre. Y la tercera llamada verNota() debe devolver un entero que refleje el contenido de la nota. El objeto debe liberar memoria al terminar.

class Alumno {
    char * nombre;
    int nota;
public:
    Alumno(char *pNombre, int pNota) {
        nombre = new char[50];
        strcpy(nombre,pNombre);
        nota = pNota;
    }
    verNombre() { return nombre; }
    verNota() { return nota; }
    ~Alumno() { delete nombre; }
};


Ejercicio Resuelto F
Elaborar una clase Coordenada, la cual contenga dos variables de tipo entero x y y. La clase debe contener dos funciones: la primera el constructor, el cual recibe dos parametors i y j. El valor almacenado en i se debe almacenar en la variable privada x y el valor almacenado en la variable j se debe pasar al a variable privada y. La clase debe contener la función verCoordenada(), la cual debe informar al programa principal los valores almacenados en x y y. la función no puede retorna ningún dato. Con el propósito de elaborar su tarea, la función verCoordenada() debe trabajar parámetros por referencia.

#include "iostream.h"

class Coordenada {
 int x,y;
public:
 Coordenada(int i, int j) {
  x = i;
  y = j;
 }
    // se pasan los parámetros por referencia para poder modificar
    // las
 void verCoordenada(int &i, int &j) {
  i = x;
  j = y;
 }
};

    // se coloca el main para mostrar como se usaría la clase
main() {
 Coordenada punto(2,3);
 int i,j;
 punto.verCoordenada(i,j);
 cout << i << ", " << j;
 return 0;
}


Ejercicio Resuelto G
Elaborar una clase denominada Codificador. La clase debe tener un su parte privada una variable dato de tipo entero, otro entero llamado codificado  que debe comenzar en 0 y debe tener una función privada verDatoReal() la cual tiene como tarea retornar dato si codificado está en cero y el valor 1000 - dato si codificado es igual a 1. En la parte pública deben existir cuatro funciones: el constructor, el cual requiere de un parámetro que inicializa la variable dato. La función asignarDato(), la cual recibe un parámetro de tipo entero, que almacena reemplazando el contenido de dato, también debe inicializar el codificado en 0. La tercera función se debe denominar procesar(), y tiene como tarea reemplazar a dato por 1000 - dato y a codificado por 1 - codificado. La cuarta función verDato() debe retornar el valor interno usando, utilizando la función definida en el bloque privado de la clase Codificador.

class Codificador {
    int dato, codificado;
    int verDatoReal() {
        if (codificado == 0)
            return dato;
        else
            return (1000 - dato);
    }
public:
    Codificador(int pdato) {
        dato = pdato;
        codificado = 0;
    }
    void asignarDato(int pdato) {
        dato = pdato
        codificado = 0;
    }
    void procesar() {
        dato = 1000 - dato;
        codificado = 1 - dato;
    }
    int verDato() {
        return verDatoReal();
    }
}


Ejemplo Resuelto H.
Elaborar una clase X, la cual tiene en su parte privada una variable x y en su parte pública dos funciones. El constructor de la clase, el cual almacena en la variale x, el valor del parámetro enviado al constructor. Tiene adicionalmente una función H(), la cual retorna el valor de la variable almacenada en la parte privada de la clase X. Con base en su clase anterior, diseñar una clase Y, que tiene en su parte privada una variable a de tipo X. La clase Y, el cual tiene como tarea inicializar la variable privada de la clase X y adicionalmente debe tener la función I(), la cual debe retornar el programa principal el valor de la variable almacenada en la parte privada de la clase X, a través de la función H() declarada en la parte pública de la clase X.

class X {
    int x;
public:
    X(int i) { x = i; }
    int H() { return x; }
};

class Y {
    X a;
public:
    Y (int z):a(z) { }
    int I() { return a.H(); }
};



 
Ejemplo Resuelto I
Elabore una clase Matriz, la cual almacene en su parte privada un aputnador a una matriz en la cual en cada celda se pueda almacenar un entero. El programa debe tener un constructor que asigne automáticamente memoria dinámica para almacenar la matriz. El orden de la matriz se indica en los parámetros del constructor. El constructor tiene dos parámetros de tipo entero. El primer parámetro indicará el número de filas de la matriz y el segundo parámetro el número de columnas de la matriz que se quiere trabajar. Adicionalmente en su parte pública debe exister una función denominada  llenar(), la cual recibe un parámetro. Esta función debe inicializar la matriz manejada dentro de la clase con el valor del parámetro. Debe existir una tercera función, que corresponde al destructor de la clase Matriz. En este destructor  se debe liberar toda la memoria asignada para la matriz. La clase debe tener una cuarta función la cual tiene como tarea retornar al programa pirncipal la dirección de la matriz.

class Matriz {
    int **raiz
    int filas, columnas;
public:
    Matriz (int pfilas, int pcolumnas);
    void llenar(int valor);
    ~Matriz();
}

Matriz::Matriz(int pfilas, int pcolumnas) {
    filas = pfilas;
    columnas = pcolumnas;
    raiz  = new int*[filas];
    for (int i=0; i<filas; i++)
        raiz[i] = new int[columnas];
}

void Matriz::llenar(int valor) {
    for ( int i=0; i<filas; i++)
        for (int j=0; j<columnas; j++)
            raiz[i][j] =   valor;
}

Matriz::~Matriz() {
    for (int i=0; i<filas; i++)
        delete raiz[i];
    delete raiz;
}


Ejemplo Resuelto J
Elaborar una clase Lado, que contenga en su parte privada un valor de tipo entero. Denominemos esta variable longitud. La función debe contener un constructor, el cual inicializa la variable longitud con el valor del parámetro enviado desde un programa principal o desde una función. La clase Lado, debe tener adicionalmente tener una función, que devuelva el valor de la variable longitud. Elaborar un programa principal que construya tres objetos de tipo Lado e inicialice su variable longitud. Después de construidos estos tres objetos, deben en las rutinas que usan la clase Lado, existir las instrucciones necesarias con el propósito de mirar si con los valores almacenados en cada una de las variables longitud de los tres objetos, se puede formar un triángulo. En caso de que se pueda formar se debe escribir "si" de lo contrario se debe escribir la palabra "no".

# include "iostream.h"

class Lado {
 int longitud;
public:
    Lado(int valor) { longitud = valor; }
 int verLongitud() { return longitud; }
};

int triangulo(int a1, int a2, int a3) {
 if ((a1 > a2+a3) || (a2 > a1+a3) || (a3 > a1+a2))
  return 0;
 else
  return 1;
}

main()  {
 Lado a(3), b(5), c(3);
 cout << "Se puede formar un triangulo?  : ";
 if (triangulo(a.verLongitud(), b.verLongitud(), c.verLongitud()))
  cout << "Si";
 else
  cout << "No";
 cout << endl << endl;
}


Ejercicio No. 5
Escriba el programa para que el Ejemplo Resuelto C (palabras homónimas) use clases.

 

[ Volver al indice de C++ ]