Está en la página 1de 16
UNIVERSIDAD DIEGO PORTALES facultad de ingeniería Escuela de Informática
UNIVERSIDAD DIEGO PORTALES
facultad de
ingeniería
Escuela de Informática

Computación II Programación Avanzada Autor: Maximiliano Vega http://max.poizon.cl

APUNTES C/C++ COMPUTACIÓN II / PROGRAMACIÓN AVANZADA

Maximiliano Vega Curaqueo.

1.-

Introducción a Objetos (POO)

La programación orientada a objetos (POO) permite la abstracción para la resolución de los problemas. Permite utilizar herencia, encapsulación, polimorfismo y abstracción tal como ya se dijo.

La gracia de poder programar con objetos, es el orden lógico que se hace, en el fondo es otro “estilo” de programación.

Los objetos se clasifican en clases.

Las clases permiten especificar los atributos y métodos (funciones) de los objetos, estás tienen diferentes tipos de atributos y métodos: public (públicos), prívate (privados) y protegidos (protected).

public permiten que todo objeto creado bajo esa clase exponga los atributos o métodos ante todo el programa.

private permiten que todo objeto creado bajo esa clase oculte los atributos y métodos del programa, solo pudiendo ser accedido por métodos y atributos de sí mismo.

protected permiten que todo objeto creado bajo esa clase oculte los atributos y métodos del programa, solo pudiendo ser accedido por métodos y atributos por sí mismo además de objetos de clases amigas.

Un ejemplo de una clase:

class lampara {

private:

int encendido;

};

public:

void encender()

{

}

void apagar()

{

}

int estado()

{

}

encendido = 1;

encendido = 0;

return encendido;

En el ejemplo anterior, la clase lámpara contiene el atributo privado “encendido” que es un entero y los métodos públicos:

Encender, que establece a encendido en 1. Apagar, que establece a encendido en 0. Estado, que retorna el número de encendido.

Si nosotros quisiéramos emplear este código, podríamos tener un programa así:

int main() {

lampara a;

cout << “Prendamos la lámpara” << endl;

a.encender();

if(a.estado()) { cout << “La lámpara está prendida” << endl; }

else { cout << “La lámpara está apagada” << endl; }

cout << “Apaguemos la lámpara” << endl;

a.apagar();

if(a.estado()) { cout << “La lámpara está prendida” << endl; }

else { cout << “La lámpara está apagada” << endl; }

return 0;

}

Una explicación breve de este código:

Creamos una lámpara y le asignamos la variable “a” Encendemos la lámpara llamando al método “encender” de “a, el cual asignara “1” a variable privada encendido. Verificamos con el método “estado” si la lámpara esta prendida o no, si es 1 el valor que retorna, entonces imprimirá que esta prendida, en caso contrario (else) que está apagada. Apagaremos la lámpara con el método “apagar” que asigna 0 a la variable privada encendido. Verificamos una vez más, esta vez imprimirá que está apagada porque el método “estado” retornara 0. Retornamos 0 para decirle a nuestro sistema operativo que nuestro programa ah terminado.

Este código imprime:

Prendamos la lámpara La lámpara está prendida Apaguemos la lámpara La lámpara está apagada

Ahora, si nosotros colocamos “cout << a.encendido << endl” para intentar imprimir la variable privada encendido el programa no nos habría permitido. (Por ser privado).

1.2.-

Constructores y destructores

Un constructor es un método que pertenece a una clase, el cual “se acciona” al crearse el objeto, en caso contrario, un destructor “se acciona” cuando eliminamos el objeto o cuando este deja de existir.

Retomando el ejemplo de la lámpara, con un constructor sería así:

class lampara {

private:

int encendido;

public:

lampara()

{

encendido = 0;

}

};

void encender()

{

}

void apagar()

{

}

int estado()

{

}

encendido = 1;

encendido = 0;

return encendido;

Como podemos apreciar, el constructor es un método con el mismo nombre de la clase, en este caso, lampara, y lo que hace es establecer la variable “encendido” en 0.

Eso quiere decir, que cada objeto que creemos de esta clase, inicialmente tendrá “encendido” en 0.

Ahora, con el mismo ejemplo, un destructor:

class lampara {

private:

int encendido;

public:

lampara()

{

encendido = 0;

}

~lampara()

{

cout << “Muero!” << endl;

}

};

void encender()

{

}

void apagar()

{

}

int estado()

{

}

encendido = 1;

encendido = 0;

return encendido;

Como apreciamos, el destructor se asocia con un “~” y el nombre de la clase. Una vez el objeto deje de existir en el programa, este imprimirá en consola “Muero!

2.- Char *

Asumiendo que de Computación I o Programación I ya vienen con el conocimiento de char, un “char *” se puede considerar como un arreglo “sin fin” de caracteres. En la realidad es un vector que apunta a un carácter, por lo que marca el inicio de una cadena de caracteres. Ahora, el problema de esto es que no sabemos en qué momento termina nuestro arreglo. Para refrescarles la memoria, los arreglos terminan con \0”, entonces nosotros podemos definir el final de nuestro “char *” estableciendo un \0” en su fin.

Entonces definiremos algunas utilidades de la librería cstring (en C++) y string.h (en C):

strcpy(char

*a, char

*b)

: Permite copiar “b” en “a”. Lo hace carácter por carácter.

strcat(char

*a, char

*b)

: Concatena “b” en “a”, es decir, une ambos arreglos.

strtok(char

*a, char

*b)

: Corta “a” en “b”, si “a” es nulo (NULL), devuelve los demás trozos de “a”. strtok(NULL, char *b)

strcmp(char

*a, char

*b)

: Retorna 0 si “a” y “b” no son comparables, por ende iguales. Retorna la diferencia en ASCII de el primer carácter que no concuerde entre los arreglos “a” y “b”.

strstr(char *a, char *b)

: Retorna la dirección en memoria donde se encuentra “b” en “a”. Si no lo encuentra, retorna 0.

Ejemplo:

int main() {

}

char* a; strcpy(a, ”Hola!”);

char* b; strcpy(b, ” Como estan?”);

char* c; strcpy(c, “Hola! Como estan?”);

strcat(a,b);

cout << a << endl;

if(strstr(a,b)) { cout << “Encontre “ << b << “en ” << a << endl; } else { cout << “No encontre “ << b << “en ” << a << endl; }

if(!strcmp(a,b)) { cout << “a y b son iguales” << endl; } else { cout << “a es diferente a b” << endl; }

cout

<< “La primera parte de a antes de encontrar una o es: ” << strtok(a, ”o”) << endl << “Despues de encontrar esa o es: “ << strtok(NULL, ”o”) << endl << “Y después de esa o: “ << strtok(NULL, ”o”) << endl << “Y después: “ << strtok(NULL, ”o”) << endl;

Explicación del código:

Creamos un vector de caracteres “a”. Copiamos “hola” en el vector “a”. Creamos un vector de caracteres “b”. Copiamos “Como estan?” en el vector b. Creamos un vector de caracteres “c”. Concatenamos “b” con “a”, ahora “a” será “Hola! Como estan?”. Imprimimos a, lo que imprimirá “Hola! Como estan?”.

Si encontramos “b” en “a” (En teoría, si retorna un número que no sea 0) entonces imprimimos:

“Encontre Como estan? en Hola! Como estan?” En el caso contrario imprimimos “No encontré” el valor de b “en “ el valor de a.

Si “a” y “b” no son comparables (No puedo comparar si son iguales) entonces imprimo:

“a y b son iguales” En el caso de ser comparables, es decir, diferentes… Imprimo “a es diferente a b”.

Imprimo “La primera parte de a antes de encontrar una o es:” Cortamos “a” en cada letra “o”, nuestro “a” era “Hola! Como estan?” Tenemos las siguientes partes:

“H” – “la! C” – “m” – “ estan?” Imprimimos el primer corte “H” [strtok(a, ”o”) ] Imprimimos el segundo corte “la! C” [strtok(NULL, ”o”)] Y seguimos sucesivamente. [strtok(NULL, ”o”)]

3.- String

String es una clase que está definida en la librería cstring y string.h Esta clase, permite almacenar arreglos de caracteres de forma simple. Contiene operadores de toda clase y métodos que permiten la utilización sencilla de arreglos de caracteres como si fuera cualquier otra variable. La clase string es demasiado amplia, pero haremos un pequeño resumen de su uso aquí antes de entrar en flujo de archivos.

Metodos:

size() y length()

max_size()

resize(size_t n, char c)

: Retorna el tamaño del arreglo.

: Retorna el tamaño máximo de caracteres que pueden almacenarse.

: Cambia el tamaño del string hasta “n”.

En caso de especificar el carácter “c” y especificar un tamaño n mayor

al del tamaño del arreglo, se agregara ese carácter por cada unidad

de tamaño adicional.

En caso contrario, “borra” los caracteres debido a un “n” menor al

tamaño de la frase contenida.

capacity()

: Retorna la capacidad máxima actual del string.

reserve(size_t n)

: Permite “solicitar” mayor capacidad al string, en “n” caracteres.

clear()

: Borra el contenido del string.

empty()

: Retorna 1 si el string está vacío, en caso contrario, 0.

append(Multiples parámetros)

: Permite “añadir” en el string palabras o caracteres, tiene multiples

push_back(char c)

assign(Multiples parámetros)

insert(Multiples parámetros)

erase(Multiples parámetros)

replace(Multiples parámetros)

formas de uso. (Explicadas especialmente más abajo).

: Añade el carácter “c” al final del string.

: Similar a “=”, permite asignar frases a string.

: Inserta caracteres dentro de un string, tiene multiples formas de uso.

(Explicadas especialmente más abajo).

: Permite eliminar desde cierta posición hasta otra, o desde una

posición en adelante los caracteres del string. (Explicadas

especialmente más abajo)

: Permite remplazar partes del string o caracteres del string por otras

partes o caracteres del string. (Explicadas especialmente más abajo)

copy(char *c,size_t c,size_t d) : Copia en el vector “c” la cantidad de caracteres “c” desde la posición

swap(string c)

find(Multiples parámetros)

rfind(Multiples parámetros)

compare(Multiples parámetros)

substr(size_t c, size_t a)

“d” y retorna el largo final de la copia.

: Intercambia el valor de “c” en el string que hace swap.

: Retorna la posición del primer carácter del string que se busca.

Permite definir el intervalo de búsqueda.

(Explicadas especialmente más abajo)

: Lo mismo que find pero este retorna la posición de la ultima

“coincidencia”.

: Permite comparar dos string, tal como strcmp con vectores char.

: Retorna un string desde la posición chasta el largo a.

Se recomienda visitar http://www.cplusplus.net para ejemplos para los metodos no tratados aquí.

find:

string.find(string a) Busca desde el inicio del string, “a” y retorna la posición string.find(string a, size_t pos) Busca desde el “pos” del string, “a” y retorna la posición

insert:

string.insert(size_t pos1, string s) Inserta “s” desde la posición “pos1”. string.insert(size_t pos1, string s, size_t pos2, size_t n) :

Inserta los primeros n caracteres desde la posición “pos2” de “s” en la posición pos1. string.insert(size_t pos1, string s, size_t n) Inserta “s” en la posición “pos1” los primeros n caracteres de “s”. string.insert(size_t pos1, size_t n, char c) Inserta el carácter “c” “n” veces en la posición “pos1”.

append:

string.append(string s) Añade al final del string, “s”. string.append(string s, size_t pos, size_t n) Añade los “n” caracteres desde “pos” de “s” en el string. string.append(string s, size_t n) Añade los “n” caracteres desde el inicio de “s” en el string. string.append(size_t n, char c) Añade “n” veces el character c al final del string.

replace:

string.replace(size_t pos1, size_t n1, string str) Remplaza el string desde la posicion “pos1” hasta “n1” con el string “str” string.replace(size_t pos1, size_t n1, string str, size_t pos2, size_t n2) Remplaza el string desde la posicion “pos1” hasta “n1” con el string “str” cortado desde “pos2” hasta “n2”. string.replace(size_t pos1, size_t n1, string s, size_t n2) Remplaza el string desde la posicion “pos1” hasta “n1” con los primeros “n2” caracteres del string “str”. string.replace(size_t pos1, size_t n1, size_t n2, char c) Remplaza el string desde la posicion “pos1” hasta “n1” con el carácter “c” repetido “n2” veces.

erase:

string.erase(size_t pos1, size_t n1) Elimina “n1” elementos desde pos1.

c_str:

string.c_str() Retorna un char* con el string dentro.

Operadores:

+ : Concatena strings. = : Asigna string.

Ejemplo:

int main() {

}

string a = Hola;

string b = Como estan?;

string c;

a

= a + b;

 

c

= a

+

+ b;

cout << a << c << endl;

if(a.find(b) >= 0) { cout << “Encontre “ << b << “en ” << a << endl; } else { cout << “No encontre “ << b << “en ” << a << endl; }

if(a == b) { cout << “a y b son iguales” << endl; } else { cout << “a es diferente a b” << endl; }

cout

<< “La primera parte de a antes de encontrar una o es: ” << a.substr(0, a.find(“o”)) << endl << “Despues de encontrar esa o es: “ << a.substr(a.find(“o”)+1, a.find(“o”, a.find(“o”)-1)) << endl << “Y después de esa o: “ << a.substr(a.find(“o”, a.find(“o”))+1 ,a.find(“o”, a.find(“o”, a.find(“o”))))

<< endl;

Explicación del código:

Creamos un string “a” con Hola” como texto. Creamos un string bcon Como estan?como texto. Creamos un string c. Concatenamos “b” con “a”, ahora “a” será “Hola! Como estan?”. Decimos que cahora es a” + “ “ + “b, es decir, Hola! Como estan? Como estan?. Imprimimos “a” y “c”, lo que imprimirá “Hola! Como estan? Como estan?.

Si encontramos “b” en “a” entonces imprimimos:

“Encontre Como estan? en Hola! Como estan?” En el caso contrario imprimimos “No encontré” el valor de b “en “ el valor de a.

Si “a” y “b” sin iguales entonces imprimo:

“a y b son iguales” En el caso contrario, es decir, diferentes… Imprimo “a es diferente a b”.

Imprimo “La primera parte de a antes de encontrar una o es:” Substr me dará un string desde la posición 0 hasta que la posición de la primera “o”, Entonces el juego es obtener con substr las frases entre las “o” pero sin la o (Por eso sumamos 1) Tenemos las siguientes partes:

“H” – “la! C” – “m” – “ estan?” Imprimimos el primer corte “H” [a.substr(0, a.find(“o”))] (Desde la posición 0 hasta la primera “o” ) Imprimimos el primer corte “la! C” [a.substr(a.find(“o”, a.find(“o”))+1 ,a.find(“o”, a.find(“o”, a.find(“o”))))] (Desde la posición de la primera “o” más 1 para que no se tome la “o”, hasta la segunda “o” menos 1 para que no tome la “o” ) Y así sucesivamente.

4.- Flujo de archivos

File Stream, como se llama en inglés, permite leer y escribir ficheros de texto plano. Se divide en tres clases, IFSTREAM, OFSTREAM y FSTREAM.

4.2- IFSTREAM

Input File Stream, Entrada de flujo de archivos, nos permite leer archivos.

Constructor:

ifstream(char* archivo, char* opciones)

Métodos:

ifstream.getline(char* linea, size_t tam)

ifstream.eof()

ifstream.open(char *a) ifstream.close() ifstream.is_open()

ifstream.good()

Operador:

ifstream >> string/char* s

: Abre “archivo” (Sustituyendo al método open) con las opciones descritas en “opciones”.

: Guarda la línea que se está leyendo en “linea”, hasta “tam” caracteres. (Get Line – Obtener Linea) : Retorna 1 si se está en el final del archivo, 0 en caso contrario. (End Of File Fin del Archivo) : Abre el archivo “a”. : Cierra el archivo abierto. : Retorna 1 si el archivo está abierto, 0 en caso contrario. : Retorna 1 si el archivo está abierto y listo para realizar operaciones, 0 en caso contrario.

: Guarda la linea actual en “s”.

En caso de utilizar string, getline se hace de la forma “getline(ifstream,string)”.

4.3- OFSTREAM

Output File Stream, Salida de flujo de archivos, nos permite escribir archivos.

Constructor:

ofstream(char* archivo, char * opciones) : Abre “archivo” (Sustituyendo al método open) con las opciones descritas en “opciones”.

Métodos:

ofstream.open(char* a) ofstream.close() ofstream.is_open()

: Abre el archivo “a”. : Cierra el archivo abierto. : Retorna 1 si el archivo está abierto, 0 en caso contrario. : Retorna 1 si el archivo está abierto y listo para realizar operaciones, 0 en caso contrario.

ofstream.good()

Operador:

ofstream << string/char*

: Escribe en el archivo abierto por ofstream.

Una opción bastante útil dentro de ofstream es ios::app que permite escribir siempre en la última línea del archivo. (Así no reescribe el archivo).

Archivo1.txt

Archivo2.txt

Linea 1

 

Meh 1

Linea 2

Meh 2

Linea 3

Meh 3

Linea 4

Meh 4

Linea 5

Meh 5

Linea 6

Meh 6

Linea 7

Meh 7

Linea 8

Meh 8

Linea 9

Meh 9

Linea 10

Meh 10

Linea 11

Meh 11

Linea 12

Meh 12

Linea 13

Meh 13

Linea 14

Meh 14

Linea 15

Meh 15

int main() {

string a,b;

ifstream Lector1(“Archivo1.txt”);

ifstream Lector2;

Lector2.open(“Archivo2.txt”);

ofstream Escritor(“Archivo3.txt”);

 

while(getline(Lector1,a) && getline(Lector2,b)) {

Escritor << a << “ “ << b << endl;

 

}

Lector1.close(); Lector2.close(); Escritor.close();

return 0;

}

Explicación del código:

Creamos dos string “a” y “b”. Creamos un ifstream Lector1para leer “Archivo1.txt”. Creamos un ifstream Lector2. Al ifstream Lector2le pedimos que abra “Archivo2.txt”. Creamos un ofstream Escritorpara escribir en “Archivo3.txt”.

Hacemos un ciclo que, mientras “Lector1” reciba líneas, que las guarde en “a” y además si “Lector2” recibe líneas, las guarde en “b”.

Mientras esto ocurra, pedimos el operador “<<” de “Escritor”, el cual funciona igual que cout. Entonces estamos escribiendo sobre el archivo abierto por “Escritor”, “a” luego “ “ luego “b” y luego un fin de línea, endl.

En el primer caso se escribiría “Linea 1 Meh 1” en Archivo3.txt

Luego, cerramos los flujos y retornamos 0 para decir que el programa ha terminado.

4.- Listas, Stacks (Pilas) y Colas

Las listas, stacks y colas se utilizan para enlazar, de alguna forma, objetos de la misma especie y realizar operaciones con ellos.

4.1 Listas.

Las listas permiten un orden lineal de los objetos, es decir, se mantiene una raíz que siempre se conoce y desde esta se avanza a los demás objetos enlazados.

s s s s s RAIZ i NODO i NODO i NODO i NODO i
s
s
s
s
s
RAIZ
i
NODO
i
NODO
i
NODO
i
NODO
i
g
g
g
g
g

Este esquema estaría ejemplificado con el siguiente código:

class nodo() {

public:

nodo *sig;

};

class lista() {

public:

nodo *raiz;

};

En una lista se puede añadir o quitar elementos en la posición que se desee, pero usualmente son agregados al principio de la lista, para evitar generar ciclos innecesarios (Como buscar el último elemento). Un método “agregar” (push) y “eliminar” (pop) podría ser:

class nodo() {

public:

int numero;

nodo *sig;

};

class lista() {

public:

nodo *raiz; bool agregar(nodo *Nuevo) { if(!raiz) { raiz = Nuevo; return TRUE; } else { Nuevo->sig = raiz; raiz = Nuevo; return TRUE; } return FALSE;

}

bool eliminar(int numero) { if (!raiz) { return FALSE; } elseif(raiz->numero == numero) { raiz = raiz->sig; return TRUE; } elseif(raiz->sig) { nodo *aux = raiz; nodo *aux2 = raiz->sig; while(aux2->numero != numero) { aux = aux2; aux2 = aux2->sig; } aux->sig = aux2->sig; delete(aux2); return TRUE;

}

else { return FALSE; }

};

}

4.2 Stacks.

Los stacks, o en español, pilas, se refiere a un grupo de objetos o elementos ordenados de tal forma que el método “añadir” de la pila añade en primera posición y el método eliminar de la pila elimina el elemento en la primera posición. (El último que entro es el primero en salir).

AÑADIR SIG NODO
AÑADIR
SIG
NODO
SIG NODO SIG NODO
SIG
NODO
SIG
NODO

ELIMINA

class nodo() {

public:

nodo *sig;

};

class stack() {

public:

nodo *raiz; bool agregar(nodo *Nuevo) { if(!raiz) { raiz = Nuevo; return TRUE; } else { Nuevo->sig = raiz; raiz = Nuevo; return TRUE; } return FALSE;

}

bool eliminar() { if(!raiz) { return FALSE; } nodo *aux = raiz; raiz = raiz->sig; delete(aux); return TRUE;

}

};

4.3 Colas.

Las colas, al igual que las pilas y listas, es un ordenamiento de objetos y elementos, la diferencia es que tal como si fuera una cola en algún banco para depositar, cuando se añaden objetos, se colocan al final de la lista y cuando se quitan objetos, se elimina el primer elemento de la lista. (El primero en entrar es el primero en salir).

ELIMINA SIG NODO SIG NODO AÑADIR SIG NODO
ELIMINA
SIG
NODO
SIG
NODO
AÑADIR
SIG
NODO

class nodo() {

public:

nodo *sig;

};

class cola() {

public:

nodo *raiz; bool agregar(nodo *Nuevo) { if(!raiz) { raiz = Nuevo; return TRUE; } nodo *aux = raiz; while(aux) { aux = aux->sig; } aux->sig = Nuevo; return TRUE;

}

bool eliminar() { if(!raiz) { return FALSE; } nodo *aux = raiz; raiz = raiz->sig; delete(aux); return TRUE;

}

};