You are on page 1of 212

UNIVERSIDAD CENTRAL DE VENEZUELA FACULTAD DE CIENCIAS ESCUELA DE COMPUTACIN

Materia: ESTRUCTURA DEL COMPUTADOR

Manual bsico de Programacin en C++

Seleccin: DZ

ndice
(RECOPILACION I) Diferencias entre C y C++ Programacin orientada a objeto POO ENCAPSULACIN, POLIMORFISMO, HERENCIA Representacin de datos en lenguaje C/C++ Primer programa en C++ Declaraciones en C++: (2) Como se declaran variables en C Como se declaran constantes en C Reglas de alcance de una variable signen, unsigned, short, long Tipo de datos1 (TDD) Calificadores de tipo signen, unsigned, short, long Operador de resolucin de alcance unario (POO) Homonimia de funciones Comentarios en C/C++ Secuencias de escape en C++ Estructuras condicionales en C Formas bsicas IF-ELSE-ELSE IF Sentencia CONTINUE, Estructura SWITCH Como hacer Ciclos en C++ Tipos de ciclos en C++ Flujo de entrada/salida de C++ Declaracin de archivo de cabecera y su relacin con las Funciones a usar en cdigo fuente Uso de las sentencias con printf y scanf en C++ Especificadores de formato Uso de los apuntadores en C 3 Operadores de Indireccin y Direccin & y * Instruccin esttica->consola: Ideal para DEV-C++ Cmo crear nuevos tipos de datos en C++ Directivas del Preprocesador Typedef , #include Arreglos unidimensionales (Vectores) Llamadas a funciones con arreglos Arreglos multidimensionales (Matrices) Registros Registros y funciones (2) (1)

(3)

(4) (5) (6) (8) (10)

(11) (12) (13) (15) (17) (19)

Arreglos de registros Definicin de tipos (Typedef) Archivos (22) Apertura de archivos Modo texto Modo binario Cierre de registros Escritura y lectura de registros: Un carcter Un nmero entero Una cadena de caracteres Con formato (CDT) Registros (material adicional) Otras funciones para archivos Deteccin de final de archivo Prototipos de funcin y verificacin de tipo de dato Operador de resolucin de alcance unario (RECOPILACION II) Resumen sobre las libreras de C++ Las clases estndar de C++ para entrada/salida Declaracin, apertura y cierre de canales para archivo Modo Descripcin Como crear clases en C/C++ Control de acceso a miembros (CDA) Archivos de cabecera Declaracin de las funciones Paso de parmetros a una funcin Funciones constructoras Funcin destructora Cuando son llamados los destructores y constructores? Asignacin por omisin en copia a nivel de miembro en C Funciones en lnea Verificacin de tipos en C++ Cmo poner en prctica un TDA con una clase? Un cdigo fuente en C++
Como leer registros Pase de parmetros por referencia Variable booleana en un condicional Nuevo tipo interesante de arreglo en c Impresin de arreglo

(21)

(28) (29)

Cmo llamar funciones: parmetros por valor y parmetros por referencia.

(31)

(32) (33) (34) (35) (36)

(37) (40)

Libreras9 de C++ Librera stdio.h

(41)

printf , scanf ,puts ,gets ,fopen ,fclose ,fprintf , fgets Librera tdlib.h atof , atoi , itoa , exit Librera conio.h

clrscr,clreol,gotoxy,textcolor,textbackground,wherex,wherey,getch,getche
9 Las funciones de las librerias de C++ dependen del compilador que se este usando lo recomendable es no usar funciones que otros compiladores no reconoceran si el programa es para otros. Por ejemplo el void detalle cumple la funcion de gotoxy()

Librera string.h strlen , strcpy , strcat , strcmp Funciones interesantes fflush(stdin),sizeof,cprintf,kbhit,random,randomize,system Conversin de tipos en C++ (CDT) Excepciones en C++ Operaciones con Objetos en C++ ASIGNACIN DE OBJETOS ARRAY DE OBJETOS Unidimensional Bidimensional DECLARACIN, INICIALIZACIN PASO DE OBJETOS A FUNCIONES: OBJETOS DEVUELTOS POR FUCIONES PUNTEROS A OBJETOS Funciones Constructoras y Destructoras CONSTRUCTORES CON PARAMETROS Sobrecarga de Funciones y Operadores Prioridad de operadores en C (ver simplificada) Funciones inline y Automticas2 Utilizacin de Estructuras como Clases2 this, new y delete2 Referencias2 Herencia2 Herencia mltiple2 Funciones Virtuales2 Funciones Amigas2 Tipo de dato referencia2 (44) (46) (47) (48)

(50) (51) (52) (53) (56) (62) (63) (64) (66) (70) (71) (73) (76) (77) (79)

Apuntadores en C, Por qu son Importantes los Apuntadores?, Operadores de Indireccin y Direccin, Advertencia sobre C, La Aritmtica de Apuntadores, Apuntadores a Funciones, Arreglos en C, Por qu Usar los Arreglos?, La Declaracin de un Arreglo, Breve resumen sobre los arrays, Arreglos y Apuntadores Apuntadores a Funciones Punteros a estructuras Punteros a objetos constantes Punteros a void (89) (83) (88)

Los operadores NEW Y DELETE

(90)

SOBRE ENUMERACIONES, ESTRUCTURAS Y UNIONES EN C++ ENUMERACIONES ESTRUCTURAS DE ALMACENAMIENTO UNIONES CADENAS EN C++ MAS SOBRE FUNCIONES EN C++ Definicin de funciones Argumentos por omisin en funciones Ms sobre funciones en lnea (inline) Sobrecarga de funciones Mas sobre el modificador <const> Paso de parmetros a funciones 1. Por valor 2. Por direccin 3. Por referencia Paso de arrays en C Tamao de un TDD (El operador: sizeof) La sentencia nula en C Prioridad y asociatividad de operadores en C (ver completa) (101) (98) (100) (95) (96) (97) (94) (92) (93) (91)

MS SOBRE ENTRADAS Y SALIDAS BSICAS EN C

Salida Uso de flujos para salida de caracteres. Entrada Manipuladores de C Palabras reservadas de C (ver completa) Laboratorio 4 #1 de C++ UCV 4 Laboratorio #2 de C++ UCV Sentencias de salto Sentencias break, continue, goto SOBRE ALGUNOS OPERADORES (?,::,) Los backward_warning.h o warning!! de C/C++ (Una cuestin para ignorar y ejecutar el programa) Estructuras de almacenamiento (EDA) Manejo de EDA y apuntadores Gestin dinnica de memoria Constantes de tipo enumeracin Diferencias entre POO y POC La librera para generar tiempo en C++ time.h Uso del system(cls) Creacin de un objeto en C++ (Cdigo fuente del void detalle versin final) Plantilla de men en C++ (Cdigo fuente del programa, una forma muy bsica P.O.O.) Recursividad en C++ Los ciclos infinitos de C++ Sentencias break, continue Instrucciones inmediatas if, else, for,.. Paso de punteros a objetos Por valor y por referencia. Lnea de comandos Ubicacin del programa en la unidad C: Entrada vs Salida Archivos

(102) (103)

(105) (106) (112) (120) (121) (122) (123) (125) (128) (129) (130) (136) (139) (140) (141) (145) (148)

(RECOPILACION III)

Material terico-practico adicional de programacin en C++ 7


Variables vs Apuntadores Objeto vs Clase (notas) Aprenda a programar con clases Definicin de una clase Prototipo de clases Objetos de clases Funciones miembro Tipos de funciones miembro Funciones en lnea y fuera de lnea La palabra reservada inline Archivos de cabecera y de clases Constructores Constructor por defecto Constructores sobrecargados Constructor de copia Inicializacin de miembros en constructores Destructores Clases compuestas Sobrecarga de funciones polimorfismo Errores de programacin frecuentes en POO Plantillas de funciones (templates) Visibilidad de una funcin Variables estticas y automticas Compilacin separada Parmetro const de una funcin Argumentos por omisin Detalles de programacin bsica I Resumen de la programacin con clases Errores de programacin frecuente en POO con clases Mas sobre el goto, ciclos. Conclusiones Programacin Bibliografa consultada Programacin adicional (149) (150)

(160)

(165) (166)

(171) (174) (176) (180) (184) (191) (193) (199) (200) (201,)

muchas sintaxis el TDD se coloca simplemente como <tipo>, <valor_devuelto>. Una funcin en cualquier lenguaje de programacin, tambin se puede llamar como un: tipo operador.
2 Estudiar

1En

Operaciones con Objetos, stos captulos corresponden ms a la programacin dinmica (abstracta) en C++, mientras que el Manual Bsico de Programacin en C++, (antes del apndice) de programacin en C++ va ms ligada a programacin estructurada. pseudoformal el * se suela cambiar por ^ por lo general y se coloca delante de la variable, Sintaxis: <nombre_apuntador>^.
4Se 3En

agregaron estos laboratorios, tal cual se publicaron el la pagina de la Facultad de Ciencias UCV contienen muy buena informacin.
7Para

los siguientes tpicos se recomienda revisar los contenidos de el libro Algoritmos, estructuras de datos y objetos L. Joyanes Aguilar, paj 141 para saber mas acerca las libreras, funciones y variables de C++ se pretendi abarcar los aspectos mas relevantes de los captulos 2,3,6, PARTE II de la obra.

*Fuentes usadas: (Total 200 paginas exactas de informacin y + de apa!) Charter BT (Insercin de algunos signos especiales), Verdana (texto teora) Courier New (cdigo fuente) Time New Roman (palabras reservadas)

Diferencias entre C y C++ Aunque C++ es un sper conjunto de C, existen algunas diferencias entre los dos. En primer lugar, en C cuando una funcin no toma parmetros, su prototipo tiene la palabra void. Sin embargo en C++ void no es necesario (opcional). Prototipo en C: Prototipo en C++: char f1(void); char f1();

Otra diferencia entre C y C++ es que en un programa de C++ todas las funciones deben estar en forma de prototipo, en C los prototipos se recomiendan, pero son opcionales. Tambin si una funcin de C++ es declarada para devolver un valor obligatoriamente la sentencia return debe devolver un valor, en C no es necesario que se devuelva. Otra diferencia es el lugar donde se declaran las variables locales. En C, deben ser declaradas solo al principio del bloque, mientras que en C++ las variables se pueden declarar en cualquier punto. Aunque es conveniente realizarlo siempre al comienzo de la funcin. La programacin orientada a objetos (POO), permite descomponer un problema en subgrupos relacionados (mtodo: divide y vencers). Cada subgrupo pasa a ser un objeto auto contenido que contiene sus propias instrucciones y datos que le relacionan con ese objeto. Todos los lenguajes POO comparten tres caractersticas: Encapsulacin, Polimorfismo y Herencia. ENCAPSULACIN: Es el mecanismo que agrupa el cdigo y los datos que maneja. Los mantienen protegidos frente a cualquier interferencia y mal uso. Cuando el cdigo y los datos estn enlazados de esta manera se ha creado un objeto. Ese cdigo y datos pueden ser privados para ese objeto o pblicos para otras partes del programa. POLIMORFISMO: Es la cualidad que permite que un nombre se utilice para dos o ms propsitos relacionados pero tcnicamente diferentes. El propsito es poder usar un nombre para especificar una clase general de acciones. Por ejemplo en C tenemos tres funciones distintas para devolver el valor absoluto. Sin embargo en C++ incorpora Polimorfismo y a cada funcin se puede llamar abs(). El Polimorfismo se puede aplicar tanto a funciones como a operadores. HERENCIA: Proceso mediante el cual un objeto puede adquirir las propiedades de otro objeto. La informacin se hace manejable gracias a la clasificacin jerrquica. OBJETO: Conjunto de variables y funciones pertenecientes a una clase encapsulados. A este encapsulamiento es al que se denomina objeto. Por tanto la clase es quien define las caractersticas y funcionamiento del objeto. Todo programa hecho en C puede correr en C++, pero no todos los programas hechos en C++ corren en C, para empezar abra que cambia su extensin de .cpp a .c

(1)

Representacin de datos en lenguaje C/C++ Estructura bsica de un lenguaje en C++: (shell)

(1) //Se hace la importacin de libreras (2) #include <stdio.h> // pueden invocarse mas de una (3) (4) //Declaracin de variables globales (5) int z=0; //variable (6) const float pi2 = 2*3.141592; //constante (7) int main () (8) { (9) int x=0,y=0; //variables locales a main (10) //bloque de instrucciones . . . (11) //creacin de constructores opcionales (12) y=funcion (x,y); (13) /*instruccin esttica->consola se usa con algunos (14) programas dev C++ por ejemplo*/ (15) return 0; //la funcin se puede comportar como una (cont.) (16)} // accin tambin en C++ (17) int funcion (int &x,int y) (18) { (19) int c=0; //variables local a funcin (20) c=y; //bloque de instrucciones (21) return c; (22) } (23) //una lnea vaca a veces es necesaria al final del cdigo (24) /*a veces los cuerpos de funciones hay que declararlas arriba (25) va del cuerpo del main() para que el programa las reconozca (26) (DEV C++ C++) */ Declaraciones en C: Las declaraciones de variables o funciones pueden ser colocadas antes de cualquier enunciado ejecutable, siempre y cuando las declaraciones antecedan el uso de lo que se est declarando. Como se declaran variables en C: Se declaran siguiendo el patrn (sintaxis): <tipo> <nombre>; Como se declaran constantes en C: Existen dos tipos de constantes: -Constantes simblicas: son las que permiten al programador ponerle un nombre a una constante y utilizarlo a todo lo largo del programa. Se declaran siguiendo el patrn (sintaxis): #define <identificador> <valor>; (2)

-Otra manera de declarar constantes en C es mediante la palabra reservada const . Este calificador permite especificar que un argumento pasado a una funcin no es modificable en dicha funcin o declarar variables constantes, en vez de declarar constantes simblicas en el preprocesador con #define). const <tipodedato><identificador> =<valor>; Es posible inicializar y declarar ms de una variable del mismo tipo en la misma sentencia: El calificador const se usa en la lista de parmetro de una funcin para especificar que un argumento pasado a la funcin no es modificable en dicha funcin. Tambin puede ser utilizado para declarar un apuntador constante. Creacin un apuntador constante a tipo. <tipodedato> *const <identificador>=<valor>; (Variable) Apuntador a la constante tipo. const <tipodedato> *<identificador>=<valor>; Apuntador constante a tipo constante: const <tipodedato> *const <identificador> = <valor>; Reglas de alcance de una variable El alcance de un identificador o variable es la porcin del programa en el cual dicho identificador puede ser referenciado. Cuando declaramos una variable local en un bloque, esta puede ser referenciada solamente en dicho bloque o en los bloques anidados dentro de dicho bloque. <tipo> <nombre1>=<valor>,<nombre2>=<valor>,<nombre3>=<valor>; Tipo de datos: Tipo char int float double Tamao 1 byte 2 bytes 4 bytes 8 bytes Rango de valores -128 a 127 -32768 a 32767 3'4 E-38 a 3'4 E+38 1'7 E-308 a 1'7 E+308

(3)

Calificadores de tipo Los calificadores de tipo tienen la misin de modificar el rango de valores de un determinado tipo de variable. Estos calificadores son cuatro: Signen: Le indica a la variable que va a llevar signo. Es el utilizado por defecto. signed char signed int Tamao 1 byte 2 bytes Rango de valores -128 a 127 -32768 a 32767

Unsigned: Le indica a la variable que no va a llevar signo (valor absoluto). Tamao 1 byte 2 bytes Rango de valores 0 a 255 0 a 65535

unsigned char unsigned int

Short: Rango de valores en formato corto (limitado). Es el utilizado por defecto. Tamao 1 byte 2 bytes Rango de valores -128 a 127 -32768 a 32767

short char short int

Long: Rango de valores en formato largo (ampliado). Tamao 4 bytes 10 bytes Rango de valores -2.147.483.648 a 2.147.483.647 -3'36 E-4932 a 1'18 E+4932

long char long int

Operador de resolucin de alcance unario Es posible declarar variables locales y globales con un mismo nombre. C++ dispone del operador de resolucin de alcance unario (::) para tener acceso a una variable global cuando est en alcance una variable local con el mismo nombre. No puede ser utilizado para tener acceso a una variable del mismo nombre en un bloque externo. Ejemplo: #include <iostream.h> float v; int main () { int v=7; //se crea una variable entera ::v=10.5 //Utiliza la variable global v cout<<variable local v = <<v<<\n; cout<<variable global v = <<::v<<\n; return 0; } (4)

Homonimia de funciones (Funciones con el mismo nombre) C++ permite que sean definidas varias funciones del mismo nombre (sobrecarga de funciones), siempre que estos nombres indiquen distintos conjuntos de parmetros. Esta capacidad se llama homonimia de funciones. La homonimia de la funcin se utiliza por lo comn para crear varias funciones del mismo nombre, que ejecuten tareas similares, sobre tipos de datos distintos. Las funciones homnimas deben tener distintas listas de parmetros. La homonimia ayuda a eliminar el uso de las macros #define de C.

/*Definimos dos funciones llamadas max(); una que regrese el mayor de dos enteros y otra que regrese el mayor de dos string.*/ #include <stdio.h> int max(int a,int b) { if(a>d) return a; else return b; } char *max(char *a, char *a) { if(strcmp(a,b)>0) return a; else return b; } int main() { printf(max(19,69) = %d\n, max(19,69)); printf(max(abc,def) = %s\n, max(abc,def)); return 0; } Comentarios en C/C++ No son tomados en cuenta por el compilador Comentario de una lnea empiezan con // en adelante Comentario de texto empiezan con /* y terminan con*/

(5)

Secuencias de escape: Ciertos caracteres no representados grficamente se pueden representar mediante lo que se conoce como secuencia de escape. A continuacin vemos una tabla de las ms significativas: \n \b \t \v \\ \f \' \" \o salto de lnea retroceso tabulacin horizontal tabulacin vertical contrabarra salto de pgina apstrofe comillas dobles fin de una cadena de caracteres

Estructuras condicionales en C: Estructura IF...ELSE Sintaxis: if (<condicin>) <sentencia>; // if sin llaves equivale a una sola sentencia //a ejecutar si se cumple la condicin

La sentencia solo se ejecuta si se cumple la condicin. En caso contrario el programa sigue su curso sin ejecutar la sentencia. Otro formato:
Estructura IF...ELSEIFELSE if (<condicin_1>) { <sentencia_1>;} else if (<condicin_2>) { <sentencia_2>;} else if (<condicin_3>) { <sentencia_3>;} else { <sentencia_n>; } /* Comentario en C observe que tambin un if puede tambin no llevar llaves en cuyo caso estara ejecutando una instruccin inmediata

*/
Sentencia CONTINUE Se utiliza dentro de un bucle. Cuando el programa llega a una sentencia CONTINUE no ejecuta las lneas de cdigo que hay a continuacin y salta a la siguiente iteracin del bucle. Existe otra sentencia, GOTO, que permite al programa saltar hacia un punto identificado con una etiqueta, pero el buen programador debe prescindir de su utilizacin. Es una sentencia muy mal vista en la programacin en C. (6)

Ejemplo: /* Uso de la sentencia CONTINUE */ #include <stdio.h> main() { int numero=1; while(numero<=100) { if (numero==25) { numero++; continue; } printf("%d\n",numero); numero++; } } Estructura SWITCH Esta estructura se suele utilizar en los mens, de manera que segn la opcin seleccionada se ejecuten una serie de sentencias. Su sintaxis es: switch (<variable>) { case <contenido_variable1>: <sentencias_1>; break; case <contenido_variable2>: <sentencias_n-1>; break; default: <sentencias_n>; break;

(7)

/* Uso de la sentencia condicional SWITCH. */ #include <stdio.h> /*ejemplo de como hacer un switch*/ main() { int dia; printf("Introduce el da: "); scanf("%d", &dia); switch(dia){ case 1: printf("Lunes"); break; case 2: printf("Martes"); break; case 3: printf("Mircoles"); break; case 4: printf("Jueves"); break; case 5: printf("Viernes"); break; case 6: printf("Sbado"); break; case 7: printf("Domingo"); break; default: printf(Da incorrecto); break; }

Cada case puede incluir una o ms sentencias sin necesidad de ir entre llaves, ya que se ejecutan todas hasta que se encuentra la sentencia BREAK. La variable evaluada slo puede ser de tipo entero o caracter. default ejecutar las sentencias que incluya, en caso de que la opcin escogida no exista. Como hacer Ciclos en C: Estructura DO...WHILE Su sintaxis es: Do {

<sentencia1>; <sentencia2>; }while (<condicin>);

(8)

Ejemplo: /* Uso de la sentencia DO...WHILE para hacer un men*/ #include <stdio.h> main() { char seleccion; do{ printf("1.- Comenzar\n"); printf("2.- Abrir\n"); printf("3.- Grabar\n"); printf("4.- Salir\n"); printf("Escoge una opcin: "); seleccion = getchar(); /*funcin que lee un caracter*/ switch(seleccion){ case '1':printf("Opcin 1"); break; case '2':printf("Opcin 2"); break; case '3':printf("Opcin 3"); } } }while(seleccion!='4');

Estructura FOR Su sintaxis es: for (<inicializacin>;<condicin>;<incremento>) { <sentencia1>; <sentencia2>; } El flujo del bucle FOR transcurre de la siguiente forma:

(9)

Estructura WHILE Su sintaxis es: while(<condicion>) { <Sentencia1>; <Sentencia2>; } Flujo de entrada/salida de C++ C++ ofrece una alternativa a las llamadas de funcin printf y scanf para manejar la entrada/salida de los tipos y cadenas de datos estndar. As. En lugar de printf usamos el flujo de entrada de salida cout y el operador <<(colocar en); y en lugar de scanf usamos el flujo de entrada estandar cin y el operador >>(obtener de) operadores de insercin y extraccin de flujo, a diferencia de printf y scanf, no requiere cadena de formato y de especificadores de conversin( especificadores de formato) para indicar los tipos de datos que son extrados o introducidos. Para utilizar entradas/salidas de flujo, se debe incluir el archivo de cabecera iostream.h. Uso de las sentencias printf y scanf Sentencia printf ( ) La rutina printf permite la aparicin de valores numricos, caracteres y cadenas de texto por pantalla. El prototipo de la sentencia printf es el siguiente: printf(<control>,<arg1>,<arg2>...); Sentencia scanf ( ) La rutina scanf permite entrar datos en la memoria del ordenador a travs del teclado. El prototipo de la sentencia scanf es el siguiente: scanf(<control>,<arg1>,<arg2>...); Suponiendo que arg1 fuera una variable mientras que arg2 fuera un especificador de formato se puede indicar al computador con que datos va a trabajar Tanto la funcin printf como la funcin scanf trabajan con especificadores de formato los cuales son:

(10)

%c %d %u %o %x %e %f %s %p

Un nico carcter Un entero con signo, en base decimal Un entero sin signo, en base decimal Un entero en base octal Un entero en base hexadecimal Un nmero real en coma flotante, con exponente Un nmero real en coma flotante, sin exponente Una cadena de caracteres Un puntero o direccin de memoria

El formato aunque no muy usado completo de los modificadores es el siguiente: % [signo] [longitud] [.precisin] [l/L] conversin Signo: indicamos si el valor se ajustar a la izquierda, en cuyo caso utilizaremos el signo menos, o a la derecha (por defecto). Longitud: especifica la longitud mxima del valor que aparece por pantalla. Si la longitud es menor que el nmero de dgitos del valor, ste aparecer ajustado a la izquierda. Precisin: indicamos el nmero mximo de decimales que tendr el valor. l/L: utilizamos l cuando se trata de una variable de tipo long y L cuando es de tipo double. Uso de los apuntadores en C: (Se recomienda consultar el apendice) .-Un Apuntador es una variable que contiene una direccin de memoria, la cual corresponder a un dato o a una variable que contiene el dato. Los apuntadores tambin deben de seguir las mismas reglas que se aplican a las dems variables, deben tener nombre nicos y deben de declararse antes de usarse Operadores de Indireccin y Direccin. Hay 2 operadores que se usan cuando trabajan con direcciones en un programa C; el Operador de Indireccin ( * ) y el de Direccin (&). Estos operadores son diferentes de los tratados anteriormente. El Operador de Direccin (&) regresa la direccin de una variable. Este operador est asociado con la variable a su derecha: &h; Esta lnea regresa la direccin de la variable h. El Operador de Indireccin (*) trabaja a la inversa del operador de Direccin. Tambin esta asociado con la variable a su derecha, toma la direccin y regresa el dato que contiene esa direccin. Por ejemplo, la siguiente lnea determina la direccin de la variable h y luego usa el operador de Indireccin para accesar la variable y darle un valor de 42. Ejemplo: *(&h)=42; (11)

La declaracin de un puntero de manera general es: Tipo *nombre de apuntador; Tipo : Especifica el tipo de objeto apuntado y puede ser cualquier tipo. Nombre de apuntador: Es el identificador del apuntador Instruccin esttica->consola: (ie->c) En los programas de C algunas veces despus de ejecutar el programa la consola se cierra muy rpido y no permite visualizar en un tiempo razonable el resultado del programa por consola, entonces es conveniente agregar al final de este una instruccin de modo que la consola dure un tiempo adecuado abierta esta es: system("PAUSE"); return EXIT_SUCCESS; Esta se coloca justo antes de la ltima llave del main. Programa estndar hecho en C++ #include <stdlib.h> //libreria de C #include <iostream> #include <stdio.h> //libreria de C #include <cstdlid> /*variables globales, estructuras, funciones, clases, acciones*/ using namespace std; // (ie->c) main(int argc, char *argc) // main() en C/C++ da igual { /*todo el bloque del programa*/ system("PAUSE"); // (ie->c) return EXIT_SUCCESS; //puede no ser necesaria aveces(ie->c) } /*se hace un enter despus de la ultima llave para indicar un separador al compilador de C++, en la mayora de los casos, si el programa se hace en lenguaje C++ el cuerpo de las funciones se declaran arriba del cuerpo del main() desde donde son llamadas*/ Cmo crear nuevos tipos de datos en C++ C++ proporciona la capacidad de crear nuevos tipos definidos por el usuario mediante el uso de la palabra reservada enum, la palabra reservada struct, la palabra reservada union y la palabra reservada class. Por ejemplo, las enumeraciones en C++ son declaradas mediante la palabra enum y se convierte en un tipo de dato nuevo. Luego, para declarar una variable del nuevo tipo de dato ya no es necesaria la palabra reservada enum, sino que se utiliza directamente el nombre del nuevo tipo de dato. Ejemplo: enum boolean {FALSE, TRUE};

struct Nombre {char primer [10];char segundo[10];};


(12)

Directivas del Preprocesador-> typedef La palabra reservada typedef proporciona un mecanismo para la creacin de sinnimos o alias para tipos de datos anteriormente definidos. Al crear un nuevo nombre utilizando typedef no se crea un nuevo tipo; typedef simplemente crea un nuevo nombre de tipo que puede ser utilizado como un seudnimo para un nombre de tipo ya existente, lo cual ayuda a autodocumentar el programa. Ejemplo: typedef int IntArray10 [10]; La directiva del preprocesador-> #include La directiva del preprocesador #include permite que se incluya una copia del archivo especificado. Las dos formas de la directiva son: #include <filename> #include filename La diferencia entre estas formas estriba en la localizacin donde el preprocesador buscar el archivo a incluirse. Si el nombre del archivo est encerrado entre comillas, el preprocesador buscar el archivo en el mismo directorio que el archivo que se est compilando (este mtodo se utiliza normalmente para incluir archivos de cabecera definidos por el programador). Si el nombre del archivo est encerrado entre corchetes angulares (< y >) la bsqueda se llevar a cabo en los directorios predesignados (por ejemplo cuando se incluyen los archivos de cabecera de la biblioteca estndar). Arreglos unidimensionales (Vectores) Un vector es un arreglo unidimensional, es decir, slo utiliza un ndice para referenciar a cada uno de los elementos. Su declaracin ser: <tipo> <nombre> [<tamao>]; //tamao es una variable por decir x El tipo puede ser cualquiera de los ya conocidos y el tamao indica el nmero de elementos del vector (se debe indicar entre corchetes [ ]). En el ejemplo se puede observar que la variable i es utilizada como ndice, el primer for sirve para rellenar el vector y el segundo para visualizarlo. Como se aprecia, las posiciones van de 0 a 9 (total 10 elementos). Ejemplo: /* Declaracin de un arreglo. */ #include <stdio.h> main() { int vector[10],i; for (i=0;i<10;i++) vector[i]=i; for (i=0;i<10;i++) printf(" %d", vector[i]); } (13)

Podemos inicializar (asignarle valores) un vector en el momento de declararlo(igual que en Java). Si lo hacemos as no es necesario indicar el tamao. Su sintaxis es: <tipo> <nombre> []={<valor_1>,<valor_2>,...} Ejemplos: int vector[]={1,2,3,4,5,6,7,8}; char vector[]="programador"; char vector[]={'p','r','o','g','r','a','m','a','d','o','r'}; Una particularidad con los vectores de tipo char (cadena de caracteres), es que deberemos indicar en que elemento se encuentra el fin de la cadena mediante el caracter nulo (\0). Esto no lo controla el compilador, y tendremos que ser nosotros los que insertemos este carcter al final de la cadena. Por tanto, en un vector de 10 elementos de tipo char podremos rellenar un mximo de 9, es decir, hasta vector[8]. Si slo rellenamos los 5 primeros, hasta vector[4], debemos asignar el caracter nulo a vector[5]. Es muy sencillo: vector[5]='\0'; Ahora veremos un ejemplo de como se rellena un vector de tipo char. /* Vector de tipo char. */ #include <stdio.h> main() { char cadena[20]; int i; for (i=0;i<19 && cadena[i-1]!=13;i++) cadena[i]=getche( ); if (i==19) cadena[i]='\0'; else cadena[i-1]='\0'; printf("\n%s",cadena); } Podemos ver que en el for se encuentran dos condiciones: 1.- Que no se hayan rellenado todos los elementos (i<19). 2.- Que el usuario no haya pulsado la tecla ENTER, cuyo cdigo ASCII es 13. Tambin podemos observar una nueva funcin llamada getche( ), que se encuentra en conio.h. Esta funcin permite la entrada de un caracter por teclado. Despus se encuentra un if, que comprueba si se ha rellenado todo el vector. Si es cierto, coloca el caracter nulo en el elemento 20 (cadena[19]). En caso contrario tenemos el else, que asigna el caracter nulo al elemento que almacen el caracter ENTER. (14)

En resumen: al declarar una cadena deberemos reservar una posicin ms que la longitud que queremos que tenga dicha cadena. Llamadas a funciones con arreglos Como ya se coment en el tema anterior, los arreglos nicamente pueden ser enviados a una funcin por referencia. Para ello deberemos enviar la direccin de memoria del primer elemento del arreglo. Por tanto, el argumento de la funcin deber ser un puntero. Ejemplo: /* Envo de un arreglo a una funcin. */ #include <stdio.h> void visualizar(int []); /* prototipo */ main() { int array[25],i; for (i=0;i<25;i++) { printf("Elemento n %d",i+1); scanf("%d",&array[i]); } visualizar(&array[0]); } void visualizar(int array[]) /* desarrollo */ { int i; for (i=0;i<25;i++) printf("%d",array[i]); } En el ejemplo se puede apreciar la forma de enviar un arreglo por referencia. La funcin se poda haber declarado de otra manera, aunque funciona exactamente igual: declaracin o prototipo void visualizar(int *); desarrollo de la funcin void visualizar(int *arreglo)

Arreglos multidimensionales (Matrices) Una matriz es un arreglo multidimensional. Se definen igual que los vectores excepto que se requiere un ndice por cada dimensin. (15)

Su sintaxis es la siguiente: <tipo> <nombre> [<tamao_1>][<tamao_2>],...,[<tamao_n>]; Una matriz bidimensional se podra representar grficamente como una tabla con filas y columnas. La matriz tridimensional se utiliza, por ejemplo, para trabajos grficos con objetos 3D. En el ejemplo puedes ver como se rellena y visualiza una matriz bidimensional. Se necesitan dos bucles para cada una de las operaciones. Un bucle controla las filas y otro las columnas. Ejemplo: /* Matriz bidimensional. */ #include <stdio.h> main() { int x, i, numeros[3][4]; /* rellenamos la matriz */ for (x=0;x<3;x++) for (i=0;i<4;i++) scanf("%d",&numeros[x][i]); /* visualizamos la matriz */ for (x=0;x<3;x++) for (i=0;i<4;i++) printf("%d",numeros[x][i]); } Si al declarar una matriz tambin queremos inicializarla, habr que tener en cuenta el orden en el que los valores son asignados a los elementos de la matriz. Veamos algunos ejemplos: int numeros[3][4]={1,2,3,4,5,6,7,8,9,10,11,12}; Quedaran asignados de la siguiente manera: numeros[0][0]=1 numeros[0][1]=2 numeros[0][2]=3 numeros[0][3]=4 numeros[1][0]=5 numeros[1][1]=6 numeros[1][2]=7 numeros[1][3]=8 numeros[2][0]=9 numeros[2][1]=10 numeros[2][2]=11 numeros[2][3]=12

(16)

Tambin se pueden inicializar cadenas de texto: char dias[7][10]={"lunes","martes", ,"viernes","sbado","domingo"}; Para referirnos a cada palabra bastara con el primer ndice: printf("%s",dias[i]); Registros Concepto de registro Un registro es un conjunto de una o ms variables, de distinto tipo, agrupadas bajo un mismo nombre para que su manejo sea ms sencillo. Su utilizacin ms habitual es para la programacin de bases de datos, ya que estn especialmente indicadas para el trabajo con registros o fichas. La sintaxis de su declaracin es la siguiente: struct <nombre_tipo_estructura> { <TDD> <nombre_variable1>; <TDD> <nombre_variable2>; <TDD> <nombre_variable3>; }; Donde tipo_estructura es el nombre del nuevo tipo de dato que hemos creado. Por ltimo, tipo_variable y nombre_variable son las variables que forman parte del registro. Para definir variables del tipo que acabamos de crear lo podemos hacer de varias maneras, aunque las dos ms utilizadas son stas: Una forma de definir el registro es: struct trabajador { char nombre[20]; char apellidos[40]; int edad; char puesto[10]; }; struct trabajador fijo, temporal;

(17)

Otra forma es: struct trabajador { char nombre[20]; char apellidos[40]; int edad; char puesto[10]; } fijo, temporal; En el primer caso declaramos el registro, y en el momento en que necesitamos las variables, las declaramos. En el segundo las declaramos al mismo tiempo que al registro. El problema del segundo mtodo es que no podremos declarar ms variables de este tipo a lo largo del programa. Para poder declarar una variable de tipo registro, el mismo tiene que estar declarado previamente. Se debe declarar antes de la funcin main. El manejo de los registros es muy sencillo, as como el acceso a los campos (o variables) de estos registros. La forma de acceder a estos campos es la siguiente: <variable>.<campo>; Donde variable es el nombre de la variable de tipo registro que hemos creado, y campo es el nombre de la variable que forma parte del registro. Lo veremos mejor con un ejemplo basado en el registro definido anteriormente: temporal.edad = 25; Lo que estamos haciendo es almacenar el valor 25 en el campo edad de la variable temporal de tipo trabajador. Otra caracterstica interesante de los registros es que permiten pasar el contenido de un registro a otro, siempre que sean del mismo tipo naturalmente: (Vase: Operaciones con Objetos en C++, paj. 47) fijo=temporal; Al igual que con los otros tipos de datos, tambin es posible inicializar variables de tipo registro en el momento de su declaracin: struct trabajador fijo={"Pedro","Hernndez Surez", 32, "gerente"}; Si uno de los campos del registro es un arreglo de nmeros, los valores de la inicializacin debern ir entre llaves: struct notas { char nombre[30]; int notas[5]; }; struct notas alumno={"Carlos Prez",{8,7,9,6,10}}; (18)

Registros y funciones Podemos enviar un registro a una funcin de las dos maneras conocidas:

1.- Por valor: su declaracin sera:


void visualizar(struct trabajador); Despus declararamos la variable fijo y su llamada sera: visualizar(fijo); Por ltimo, el desarrollo de la funcin sera: void visualizar(struct trabajador datos) Ejemplo: /* Paso de un registro por valor. */ #include <stdio.h> struct trabajador { char nombre[20]; char apellidos[40]; int edad; char puesto[10]; }; void visualizar(struct trabajador); main() { struct trabajador fijo; printf("Nombre: "); scanf("%s",fijo.nombre); printf("\nApellidos: "); scanf("%s",fijo.apellidos); printf("\nEdad: "); scanf("%d",&fijo.edad); printf("\nPuesto: "); scanf("%s",fijo.puesto); visualizar(fijo); } void visualizar(struct trabajador datos) { printf("Nombre: %s",datos.nombre); printf("\nApellidos: %s",datos.apellidos); printf("\nEdad: %d",datos.edad); printf("\nPuesto: %s",datos.puesto); }

(19)

2.- Por referencia: su declaracin sera: void visualizar(struct trabajador*); Despus declararemos la variable fijo y su llamada ser: visualizar (&fijo); Por ltimo, el desarrollo de la funcin ser: void visualizar(struct trabajador *datos) Fjense que en la funcin visualizar, el acceso a los campos de la variable datos se realiza mediante el operador ->, ya que lo tratamos con un puntero. En estos casos siempre utilizaremos el operador ->. Se consigue con el signo menos seguido de mayor que. Ejemplo: /* Paso de un registro por referencia. */ #include <stdio.h> struct trabajador { char nombre[20]; char apellidos[40]; int edad; char puesto[10]; }; void visualizar(struct trabajador *); main() { struct trabajador fijo; printf("Nombre: "); scanf("%s",fijo.nombre); printf("\nApellidos: "); scanf("%s",fijo.apellidos); printf("\nEdad: "); scanf("%d",&fijo.edad); printf("\nPuesto: "); scanf("%s",fijo.puesto); visualizar(&fijo); } void visualizar(struct trabajador *datos) { printf("Nombre: %s",datos->nombre); printf("\nApellidos: %s",datos->apellidos); printf("\nEdad: %d",datos->edad); printf("\nPuesto: %s",datos->puesto);} (20)

Arreglos de registros Es posible agrupar un conjunto de elementos de tipo registro en un arreglo. Esto se conoce como arreglo de registros: struct trabajador { char nombre[20]; char apellidos[40]; int edad; }; struct trabajador fijo[20]; As podremos almacenar los datos de 20 trabajadores. Ejemplos sobre como acceder a los campos y sus elementos: para ver el nombre del cuarto trabajador, fijo[3].nombre;. Para ver la tercera letra del nombre del cuarto trabajador, fijo[3].nombre[2];. Para inicializar la variable en el momento de declararla lo haremos de esta manera: struct trabajador fijo[20] = { {"Jos", "Herrero Martnez", 29 }, { "Luis", "Garca Snchez", 46 } }; Definicin de tipos El lenguaje 'C' dispone de una declaracin llamada typedef que permite la creacin de nuevos tipos de datos. Ejemplos: typedef int entero; entero*/ entero a, b = 3; /*acabamos de crear un tipo de dato llamado /*declaramos dos variables de este tipo*/

Su empleo con registros est especialmente indicado. Se puede hacer de varias formas: Una forma de hacerlo: struct trabajador { char nombre[20]; char apellidos[40]; int edad; }; typedef struct trabajador datos; datos fijo, temporal;

(21)

Otra forma: typedef struct { char nombre[20]; char apellidos[40]; int edad; }trabajador datos; datos fijo, temporal; Archivos Por ltimo veremos la forma de almacenar datos que podremos recuperar cuando deseemos. Estudiaremos los distintos modos en que podemos abrir un archivo, as como las funciones para leer y escribir en l. Apertura de archivos Antes de abrir un archivo necesitamos declarar un puntero de tipo FILE, con el que trabajaremos durante todo el proceso. Para abrir el archivo utilizaremos la funcin fopen(). Su sintaxis es: FILE *<nombre_del_puntero>; puntero = fopen (<nombre del archivo>, "<modo de apertura>" ); Donde puntero es la variable de tipo FILE, nombre del archivo es el nombre que daremos al archivo que queremos crear o abrir. Este nombre debe ir encerrado entre comillas. Tambin podemos especificar la ruta donde se encuentra o utilizar un arreglo que contenga el nombre del archivo (en este caso no se pondrn las comillas). Algunos ejemplos: puntero = fopen("DATOS.DAT","r"); puntero = fopen("C:\\TXT\\SALUDO.TXT","w"); Un archivo puede ser abierto en dos modos diferentes, en modo texto o en modo binario. A continuacin lo veremos con ms detalle. Modo texto w w+ a a+ r r+ crea un archivo de escritura. Si ya existe lo crea de nuevo. crea un archivo de lectura y escritura. Si ya existe lo crea de nuevo. abre o crea un archivo para aadir datos al final del mismo. abre o crea un archivo para leer y aadir datos al final del mismo. abre un archivo de lectura. abre un archivo de lectura y escritura. (22)

Modo binario wb w+b ab a+b rb r+b crea un archivo de escritura. Si ya existe lo crea de nuevo. crea un archivo de lectura y escritura. Si ya existe lo crea de nuevo. abre o crea un archivo para aadir datos al final del mismo. abre o crea un archivo para leer y aadir datos al final del mismo. abre un archivo de lectura. abre un archivo de lectura y escritura.

La funcin fopen devuelve, como ya hemos visto, un puntero de tipo FILE. Si al intentar abrir el archivo se produjese un error (por ejemplo si no existe y lo estamos abriendo en modo lectura), la funcin fopen devolvera NULL. Por esta razn es mejor controlar las posibles causas de error a la hora de programar. Un ejemplo: FILE *pf; pf=fopen("datos.txt","r"); if (pf == NULL) printf("Error al abrir el archivo"); La funcin freopen cierra el archivo apuntado por el puntero y reasigna este puntero a un archivo que ser abierto. Su sintaxis es: freopen(<nombre del archivo>,"<modo de apertura>",<nomb_puntero>); Donde nombre del archivo es el nombre del nuevo archivo que queremos abrir, luego el modo de apertura, y finalmente el puntero que va a ser reasignado. Cierre de registros Una vez que hemos acabado nuestro trabajo con un archivo es recomendable cerrarlo. Los archivos se cierran al finalizar el programa pero el nmero de estos que pueden estar abiertos es limitado. Para cerrar los archivos utilizaremos la funcin fclose();. Esta funcin cierra el archivo, cuyo puntero le indicamos como parmetro. Si el archivo se cierra con xito devuelve 0. fclose(<nomb_puntero>); Un ejemplo ilustrativo es: FILE *pf; pf = fopen("AGENDA.DAT","rb"); if ( pf == NULL ) printf ("Error al abrir el archivo"); else fclose(pf); (23)

Escritura y lectura de registros A continuacin veremos las funciones que se podrn utilizar dependiendo del dato que queramos escribir y/o leer en el archivo. Un carcter: fputc(<variable_caracter>,<puntero_archivo>); Escribimos un caracter en un archivo (abierto en modo escritura). Un ejemplo: FILE *pf; char letra='a'; if (!(pf=fopen("datos.txt","w"))) /* forma de controlar si hay un error */ { printf("Error al abrir el archivo"); exit(0); /* abandonamos el programa */ } else fputc(letra,pf); fclose(pf); La funcin fgetc(<puntero_archivo>), lee un caracter de un archivo (abierto en modo lectura). Deberemos guardarlo en una variable. Un ejemplo:

FILE *pf; char letra; if (!(pf=fopen("datos.txt","r"))) /* controlamos si se produce un error */ { printf("Error al abrir el archivo"); exit(0); /* abandonamos el programa */ } else { letra=fgetc(pf); printf("%c",letra); fclose(pf); }

(24)

Un nmero entero: putw(<variable_entera>,<puntero_archivo>); Escribe un nmero entero en formato binario en el archivo. Ejemplo:

FILE *pf; int num=3; if (!(pf=fopen("datos.txt","wb"))) /* controlamos si se produce un error */ { printf("Error al abrir el archivo"); exit(0); /* abandonamos el programa */ } else { fputw(num,pf); /* tambin podamos haber hecho: fputw(3,pf); */ fclose(pf); }

La funcin getw( puntero_archivo ), lee un nmero entero de un archivo, avanzando dos bytes despus de cada lectura. Un ejemplo: FILE *pf; int num; if (!(pf=fopen("datos.txt","rb"))) /* controlamos si se produce un error */ { printf("Error al abrir el archivo"); exit(0); /* abandonamos el programa */ } else { num=getw(pf); printf("%d",num); fclose(pf); }

(25)

Una cadena de caracteres: fputs(<variable_array>,<puntero_archivo>); Escribe una cadena de caracteres en el archivo. Ejemplo: FILE *pf; char cad="Me llamo Vicente"; if (!(pf=fopen("datos.txt","w"))) /* controlamos si se produce un error */ { printf("Error al abrir el archivo"); exit(0); /* abandonamos el programa */ } else { fputs(cad,pf); /* o tambin as: fputs("Me llamo Vicente",pf); */ fclose(pf); } La funcin fgets( variable_array, variable_entera, puntero_archivo ), lee una cadena de caracteres del archivo y la almacena en variable_array. La variable_entera indica la longitud mxima de caracteres que puede leer. Un ejemplo: FILE *pf; char cad[80]; if (!(pf=fopen("datos.txt","rb"))) /* controlamos si se produce un error */ { printf("Error al abrir el archivo"); exit(0); /* abandonamos el programa */ } else { fgets(cad,80,pf); printf("%s",cad); fclose(pf); }

(26)

Con formato: fprintf(<puntero_archivo>,<formato>,<argumentos>); Funciona igual que un printf pero guarda la salida en un archivo. Ejemplo: FILE *pf; char nombre[20]="Santiago"; int edad=34; if (!(pf=fopen("datos.txt","w"))) /* controlamos si se produce un error */ { printf("Error al abrir el archivo"); exit(0); /* abandonamos el programa */ } else { fprintf(pf,"%20s%2d\n",nombre,edad); fclose(pf); } La funcin fscanf(<puntero_archivo>,<formato>,<argumentos>), lee los argumentos del archivo. Al igual que con un scanf, deberemos indicar la direccin de memoria de los argumentos con el smbolo & ( ampersand ). Un ejemplo: FILE *pf; char nombre[20]; int edad; if (!(pf=fopen("datos.txt","rb"))) /* controlamos si se produce un error */ { printf("Error al abrir el archivo"); exit(0); /* abandonamos el programa */ } else { fscanf(pf,"%20s%2d\",nombre,&edad); printf("Nombre: %s Edad: %d",nombre,edad); fclose(pf); }

(27)

Registros fwrite( *buffer,<tamao>,<n de veces>,<puntero_archivo>); Se utiliza para escribir bloques de texto o de datos, registros, en un archivo. En esta funcin, *buffer ser la direccin de memoria de la cul se recogern los datos; tamao, el tamao en bytes que ocupan esos datos y n de veces, ser el nmero de elementos del tamao indicado que se escribirn. fread( *buffer,<tamao>,<n de veces>,<puntero_archivo>); Se utiliza para leer bloques de texto o de datos de un archivo. En esta funcin, *buffer es la direccin de memoria en la que se almacenan los datos; tamao, el tamao en bytes que ocupan esos datos y n de veces, ser el nmero de elementos del tamao indicado que se leern. Otras funciones para archivos: rewind( <puntero_archivo> ): Sita el puntero al principio del archivo. fseek(<puntero_archivo>,long <posicin>,int <origen>): Sita puntero en la posicion que le indiquemos. Como origen podremos poner: 0 = SEEK_SET, el principio del archivo 1 = SEEK_CUR, la posicin actual 2 = SEEK_END, el final del archivo rename(<nombre1>,<nombre2>): Su funcin es exactamente la misma que la que conocemos en MS-DOS. Cambia el nombre del archivo nombre1 por un nuevo nombre, nombre2. remove(<nombre>): Como la funcin del DOS del, podremos eliminar el archivo indicado en nombre. el

Deteccin de final de archivo La funcin feof(<puntero_archivo>), siempre deberemos controlar si hemos llegado al final de archivo cuando estemos leyendo, de lo contrario podran producirse errores de lectura no deseados. Para este fin disponemos de la funcin feof(). Esta funcin retorna 0 si no ha llegado al final, y un valor diferente de 0 si lo ha alcanzado. Pues con esto llegamos al final del tema. Espero que no haya sido muy pesado. No es necesario que te aprendas todas las funciones de memoria. Cntrate sobre todo en las funciones fputs(), fgets(), fprintf(), fwrite() y fread(). Con estas cinco se pueden gestionar los archivos perfectamente.

(28)

Prototipos de funcin y verificacin de tipo de dato Los prototipos de funcin le permiten al compilador verificar por tipo la exactitud de las llamadas de funcin. En C++ los prototipos de funcin son requeridos para todas las funciones. Sin embargo, una funcin definida en un archivo, antes de cualquier llamada a la misma, no requiere de un prototipo de funcin, ya que el encabezado de funcin acta como tal. Todos los parmetros de la funcin debern declararse entre los parntesis del prototipo y de la definicin de funcin. En caso que no existan parmetros, bastar con colocar parntesis vacos. Ejemplo: int potencia (int, int); Operador de resolucin de alcance unario Es posible declarar variables locales y globales con un mismo nombre. El operador de resolucin de alcance unario (::) permite tener acceso a una variable global cuando est en alcance una variable local con el mismo nombre. El operador de resolucin de alcance unario no puede ser utilizado para tener acceso a una variable con el mismo nombre en un bloque externo. Se puede tener acceso a una variable global de forma directa, sin usar el operador de resolucin de alcance unario, siempre que no exista una variable local en alcance con el mismo nombre. Cmo llamar funciones: parmetros por valor y parmetros por referencia. Cundo los argumentos se pasan en una llamada de una funcin por valor se efecta una copia del valor del argumento y este se pasa a la funcin llamada. Las modificaciones a la copia no afectarn el valor original de la variable del llamador. Cuando un argumento es pasado por referencia, el compilador pasa la direccin de memoria del valor del parmetro a la funcin. Cuando se modifica el valor del parmetro (la variable local), este valor queda almacenado en la misma direccin de memoria, por lo que al retornar a la funcin llamadora la direccin de memoria donde se almacen el parmetro contendr el valor modificado. Para declarar una variable parmetro como paso por referencia, el smbolo & debe preceder al nombre de la variable. Por ejemplo la funcin de intercambio, que intercambia los valores de dos variables: void intercambio ( int &a, int &b) { int aux = a; a = b; b = aux; } Los parmetros a y b son parmetros por referencia. Por consiguiente, cualquier cambio efectuado en el interior de la funcin se transmitir al exterior de la misma. Para llamar a la funcin intercambio () por referencia, simplemente se pasan las variables a intercambiar, por ejemplo:

(29)

Ejemplo: int i = 3, j = 50; intercambio (i, j); Tambin un parmetro por referencia es un seudnimo (alias) de su argumento correspondiente. Para indicar que un parmetro de funcin es pasado por referencia, solo hay que colocar un ampersand (&) despus del tipo del parmetro en el prototipo de funcin. Debemos usar apuntadores para pasar argumentos que pudieran ser modificados por la funcin llamada, y usar referencias a constantes para pasar argumentos extensos que no sern modificados. Las variables de referencia deben ser inicializadas en sus declaraciones, y no pueden ser reasignadas como seudnimos a otras variables. Cuando se regresa un apuntador o una referencia a una variable declarada en la funcin llamada, la variable deber ser declarada static dentro de dicha funcin. Las referencias pueden ser usadas como argumentos de funciones y regresar valores. Ejemplo: int ix; // ix es una variable en entera int &rx=ix; // rx es el alias de ix ix=1; // tambien rx ==1 rx=2; // tambien ix==2 Las referencias se pueden usar para proveer una funcin con un alias de un argumento real de llamada de funcin. Este permite cambiar el valor del argumento de llamada de funcin tal como se conoce de otros lenguajes de programacin de llamada por referencia: /*U se pasa por valor y S por referencia*/ void mira (int U, int &S) { U=42; S=42; } void mar() { int U,S; U=S=1; //inicializacion en una linea mirar(U,S); //en este punto S=42 y U=1; }

(30)

Resumen sobre las libreras de C Las clases estndar de C++ para entrada/salida Las primeras versiones de C++ desarrolladas en 1980 por Bjarne Stroustrup se basaban en el sistema de entrada y salida de su lenguaje padre C. Aunque todava se puede usar en C++ a travs de la librera <cstdio>, nos centraremos en cambio en el sistema de E/S basado en canales, estas son las clases de la librera <iostream>. Declaracin, apertura y cierre de canales para archivo Para que un programa pueda leer o escribir valores de un archivo de texto, debe construir un objeto ifstream o ofstream, respectivamente. ifstream canal_entrada; ofstream canal_salida; Estas instrucciones declaran los objetos canal_entrada y canal_salida como canales de archivo sin inicializar como conexiones potenciales entre el programa y los archivos-. Se convierten en conexiones reales cuando se enva un mensaje open(): canal_entrada.open(nombre_archivo_texto_entrada); canal_salida.open(nombre_archivo_texto_salida); Estos dos pasos declarar y abrir- se pueden combinar usando declaraciones de inicializacin: ifstream canal_entrada(nombre_archivo_texto_entrada); ofstream canal_salida(nombre_archivo_texto_salida); Por defecto la apertura de un ofstream hacia un archivo es destructiva, es decir, si el archivo existe, su contenido es destruido. Para evitar esto, se puede enviar un mensaje de open() con un segundo argumento de modo, que puede ser cualquiera de los siguientes:

Modo Descripcin
ios::in Es el modo por defecto de los objetos ifstream. Abre un archivo para lectura,

de forma no destructiva, colocndose para leer al principio del archivo. ios::trunc Abre un archivo y borra su contenido. ios::out Es el modo por defecto de los objetos ofstream. Abre un archivo para escritura, usando ios::trunc. ios::app Abre un archivo para escritura, pero de forma no destructiva, colocndose para escribir al final del archivo (es decir, para concatenar). ios::ate Abre un archivo existente colocndose para leer (en los objetos ifstream) o para escribir (en los objetos ofstream) al final del archivo.

(31)

ios::binary Abre un archivo sobre el que se har E/S en modo binario en lugar de en modo texto. Usando read() se leen bytes del archivo y se guardan en arreglos de char, y usando write() se escriben bytes desde arreglos de char en el archivo. Al finalizar el tratamiento con el archivo debe romperse la conexin entre el programa y el archivo envindole el mensaje close(): canal_entrada.close(); canal_salida.close(); Las clases ifstream, ofstream y fstream son subclases de la clase istream, ostream y iostream, respectivamente. Por lo tanto, todas las operaciones para E/S interactiva se pueden usar para E/S a travs de fichero. Por ejemplo, una vez que se haya declarado el objeto canal_entrada de tipo ifstream y se ha conectado a un archivo de texto, se puede leer un valor de l exactamente de la misma forma que hicimos para la E/S interactiva: canal_entrada >> variable; Como crear clases en C/C++

En C y en otros lenguajes de programacin procedurales, la programacin tiende a ser orientada a accin, en tanto que en la programacin C++ tiende a ser orientada al objeto. En C, la unidad de programacin es la funcin. En C++ es la clase a partir de la cual eventualmente los objetos son producidos (es decir, son creados). Los programadores en C++ se concentran en crear sus propios tipos de datos, conocidos como clases. Para ello, deben definir el formato general utilizando la palabra reservada class. Cada clase contiene datos junto con un conjunto de funciones que manipula dichos datos. Los componentes de datos de una clase se llaman miembros de datos. Los componentes de funcin de una clase se llaman funciones miembros. Al igual que un ejemplo de un tipo incorporado int se conoce como una variable, un ejemplo de un tipo definido por un usuario (es decir, una clase) se conoce como un objeto.

class <nombre_clase>

// miembros de datos public: //puede ser private o protected // funciones / objetos miembros // lista_objetos

(32)

Control de acceso a miembros

(CDA)

Se utilizan tres especificadores de acceso para controlar el acceso a los miembros de la clase, estos son: public, private y protected. El especificador public define miembros pblicos, que son aquellos a los que se puede acceder por cualquier funcin. A los miembros que siguen al especificador private slo se puede acceder por funciones miembro de la misma clase o por funciones y clases amigas. A los miembros que siguen al especificador protected se puede acceder por funciones miembro de la misma clase o de clases derivadas de la misma, as como amigas. Los especificadores public, private y protected pueden aparecer en cualquier orden. Si se omite el especificador de acceso, el acceso por defecto es privado.

class <nombre_clase> //datos y funciones privadas public: //datos y funciones pblicas } //lista_objetos

Una funcin amigo de una clase se define por fuera del alcance de dicha clase, pero an as tiene el derecho de acceso a los miembros private y protected de la clase. Se puede declarar una funcin o toda una clase como un friend de otra clase. Para declarar una funcin como friend de una clase, en la definicin de clase preceda el prototipo de funcin con la palabra reservada friend. Para declarar una clase B como amigo de la clase A entre los miembros de la clase A debe existir la siguiente declaracin: friend B; Esto significa que la amistad es concedida y no tomada, es decir, para que la clase B sea un amigo de la clase A, la clase A debe declarar que la clase B es su amigo. Tambin la amistad no es ni simtrica ni transitiva, es decir, si la clase A es un amigo de la clase B, y la clase B es un amigo de la clase C, no es correcto pensar que la clase B es un amigo de la clase A, que la clase C es un amigo de la clase B , ni que A es un amigo de la clase C. Archivos de cabecera Cada biblioteca estndar tiene su archivo de cabecera correspondiente, que contiene los prototipos de funcin de todas las funciones de dicha biblioteca, y las definiciones de varios tipos de datos y de constantes requeridas por dichas funciones. Por ejemplo la biblioteca estndar encargada de manipular la hora y fecha, se puede aadir a nuestro programa incluyendo el archivo de cabecera <time.h> El programador tambin puede crear archivos de cabecera para cada una de las clases que define en su programa. Para ello, el nombre de dicho archivo deber terminar en .h y podr ser incluido utilizando la directriz de preprocesador #include. Este archivo contendr los miembros de datos de la clase y los prototipos de las funciones pertenecientes a dicha clase. (33)

Declaracin de las funciones Al igual que las variables, las funciones tambin han de ser declaradas. Esto es lo que se conoce como prototipo de una funcin. Para que un programa en C sea compatible entre distintos compiladores es imprescindible escribir los prototipos de las funciones. Los prototipos de las funciones pueden escribirse antes de la funcin main o bien en otro archivo. En este ltimo caso se lo indicaremos al compilador mediante la directiva #include. En el ejemplo siguiente podremos ver la declaracin de una funcin (prototipo). Al no recibir ni retornar ningn valor, est declarada como void en ambos lados. Tambin vemos que existe una variable global llamada num. Esta variable es reconocible en todas las funciones del programa. Ya en la funcin main encontramos una variable local llamada num. Al ser una variable local, sta tendr preferencia sobre la global. Por tanto la funcin escribir los nmeros 10 y 5. Ejemplo: /* Declaracin de funciones. */ #include <stdio.h> void funcion(void); /* prototipo */ int num = 5; /* variable global */ main() { int num=10; /* variable local */ printf("%d\n",num); funcion(); /* llamada */ } void funcion(void) { printf("%d\n",num); } Paso de parmetros a una funcin Como ya hemos visto, las funciones pueden retornar un valor. Esto se hace mediante la instruccin return, que finaliza la ejecucin de la funcin, devolviendo o no un valor. En una misma funcin podemos tener ms de una instruccin return. La forma de retornar un valor es la siguiente: Sintaxis: return (<valor o expresin>); (34)

El valor devuelto por la funcin debe asignarse a una variable. De lo contrario, el valor se perder. En el ejemplo puedes ver lo que ocurre si no guardamos el valor en una variable. Fjate que a la hora de mostrar el resultado de la suma, en el printf, tambin podemos llamar a la funcin. Ejemplo: /* Paso de parmetros. */ #include <stdio.h> int suma(int,int); /* prototipo */ main() { int a = 10, b = 25, t; t = suma(a, b); /* guardamos el valor */ printf("%d=%d", suma(a, b), t); suma(a, b); /* el valor se pierde */ } int suma(int a, int b) { return (a + b); } Funciones constructoras Despus que los objetos son creados, sus miembros pueden ser inicializados mediante funciones constructor. Un constructor es una funcin miembro de clase con el mismo nombre que la clase. El programador proporciona el constructor que cada vez que se crea un objeto de dicha clase, es invocado automticamente. Los miembros de datos de una clase no pueden ser inicializados en la definicin de la clase. Ms bien, los miembros de datos deben ser inicializados en un constructor de la clase o sus valores definidos ms adelante despus que el objeto haya sido creado. Los constructores no pueden especificar tipos de regreso y valores de regreso. Los constructores pueden ser sujetos de homonimia, para permitir una variedad de maneras de inicializar objetos de una clase. Sintaxis: <nombre_clase> (<lista de parmetros>);

(35)

Funcin destructora Un destructor es una funcin miembro especial de una clase, su nombre est basado en la tilde (~) seguida por el nombre de la clase. Un destructor de una clase es llamado automticamente cuando un objeto de una clase se sale de alcance. De hecho el destructor mismo no destruye el objeto, ms bien ejecuta trabajos de terminacin, antes de que el sistema recupere el espacio de memoria del objeto con el fin de que pueda ser utilizado para almacenar nuevos objetos. Un destructor no recibe ningn parmetro, ni regresa ningn valor. Una clase slo puede tener un destructor la homonimia de destructores no est permitida. Sintaxis:

~ <nombre_clase> ();
Ejemplo: class Punto { int _x,_y; public: Punto() { _x = _y = 0; } } Punto(const int x,const int y) { _x = desde._x; _y = desde._y; } Punto(){/*Nada que hacer*/}

void setX(const int val); void setY(const int val); int getX(){return _x;} int getY(){return _y;} }; Cuando son llamados los destructores y constructores: Por lo general, son llamados de forma automtica. En general, las llamadas de destructor se efectan en orden inverso a las llamadas del constructor. Asignacin por omisin en copia a nivel de miembro: Operador de asignacin ( = ) es utilizado para asignar un objeto a otro objeto del mismo tipo. Funciones en lnea: Existen funciones en lnea que ayudan a reducir la carga por llamadas de funcin especial para pequeas funciones .El compilador puede ignorar el calificador inline y tpicamente as lo har para todo, a excepcin de las funciones ms pequeas. El calificador inline deber ser utilizado slo tratndose de funciones pequeas, de uso frecuente. Usar funciones inline puede reducir el tiempo de ejecucin, pero puede aumentar el tamao de programa. (36)

Ejemplo //Usamos la funcin inline para calcular el volumen de un //cubo. #include <iostream.h> inline float cubo(const float s){return s*s*s;} main() { cout<<Introduce la longitud del lado de un cubo: float lado; cin >>lado; cout <<El volumen del lado; cout<<volumen<<es<<cubo(lado)<<\n; return 0; } Verificacin de tipos en C++

La verificacin o comprobacin de tipos en C++ es ms rgida (estricta) que en C. Algunas consideraciones a tener en cuenta son: Usar funciones declaradas. Esta accin es ilegal en C++, y est permitida en C:

Fallo al devolver un valor de una funcin. Una funcin en C++ declarada con un tipo determinado de retomo, ha de devolver un valor de ese tipo. En C, est permitido no seguir la regla. Asignacin de punteros void. La asignacin de un tipo void* a un puntero de otro tipo se debe hacer con una conversacin explcita en C++. En C, se realiza implcitamente. Inicializacin de constantes de cadena. En C++ se debe proporcionar un espacio para el carcter de terminacin nulo cuando se inicializan constantes de cadena. En C, se permite la ausencia de ese carcter

int main() { //... printf(x) //C int printf(x) //C++ es ilegal, ya que printf no esta declarada return 0; }

Una solucin al problema que funciona tanto en C como en C++ es: char car [] ="Cazorla";

int main() { //...... char car[7] = Cazorla; // legal en C //error en C++ //...... return 0; }

Cmo poner en prctica un TDA con una clase? Las clases permiten que el programador modele objetos que tienen atributos (miembros de datos) y comportamientos u operadores (funciones miembros). Los tipos contienen miembros de datos y funciones miembro, y son definidos mediente la palabra reservada class. (37)

Ejemplo:

Class Punto //Declaracion de la clase punto { int _x,_y; //coordenadas del punto public: //Principio de la declaracin de la interfase. void setX(const int val); void setY(const int val); int getX(){return _x;} int getY(){return _y;} }; //fin class Punto apunto; //Definicion del objeto apunto. /*El objeto apunto puede usar estos metodos para establecer y para obtener informacin sobre s mismo.*/ apunto.setX(1); //inicializacion apunto.setY(1); /* x es necesaria a partir de aqu, de modo que la definimos aqu y la inicializamos con el valor de la coordenada _x de apunto. */ int x = apunto.getX(); void Punto::setX(const int val) //definimos el mtodo setX //mbito de la clase Punto { _x = val; } void Punto::setY (const int val) { _y = val; }

Comentario Comenzamos con la definicin de una clase, indicndola con la palabra reservada class. El cuerpo de la definicin de clase se delimita mediante llaves. La definicin de clase termina con un punto y coma. En el cuerpo de la definicin existen partes nuevas: la etiqueta public: y private: se conocen como especificadores de acceso. Cualquier miembro de datos o funcin miembro declarado despus del especificador de acceso de miembro) es accesible, siempre que el programa tenga acceso a un objeto de la clase. Cualquier miembro de datos o funcin miembro declarada despus del especificador de acceso de miembro private: (y hasta el siguiente especificador de acceso de miembro) slo es accesible a las funciones miembro de la clase. Estos especificadores pueden aparecer varias veces en una definicin de clase. Por defecto, los elementos de las clases son privados ( private: ). (38)

Por lo regular, los miembros de datos aparecen listados en la porcin private: de una clase, y normalmente, las funciones de miembro aparecen listadas en la porcin public:, aunque pueden darse en caso contrario. Los miembros de datos de una clase no pueden ser inicializados donde son declarados en el cuerpo de la clase. Debern ser inicializados por el constructor de la clase, o las funciones ser les asignar valores. La funcin con el mismo nombre que la clase, pero precedido por un carcter tilde () se llama el destructor de dicha clase. Cuando una funcin miembro se define por fuera de la definicin de clase, el nombre de funcin es antecedido por el nombre de la clase y por el operador de resolucin de alcance binario (::). Dicha funcin miembro queda dentro del alcance de la clase. El objeto apunto puede usar estos metodos para establecer y para obtener informacin sobre s mismo.

(39)

Un programa hecho en C++:


#include <cstdlib> #include <iostream> #include <stdlib.h> #include <stdio.h> using namespace std; int main(int argc, char *argv[]) { int algo=0; //se declara y valida una variable entera FILE *f; //se declara un apuntador a un archivo FILE char b[20]; //en C/C++ el string no existe f=fopen("archivo.txt","r"); //se habre un archivo while(!feof(f)){ //mientras no see fin de archivo lee fgets(b,20,f); //lee linea por lnea printf("%s\n",b); //imprime lo que hay en el archivo.txt } system("PAUSE"); // (ie->c) return 0; //ideal para convertir una funcion en accin algo=funcionentero(algo); //algo es pasado por referencia /* EL COMPILADOR DE C IGNORA ESTE BLOQUE-------------------------(1) //creacin de arreglos, relleno y escritura int *x=(int*)malloc(sizeof(int)*20); for (int h=1;h<21;h++) { x[h]=u; printf("%d",x[h]); //impresin vulgar u++; } algo=funcion(x); printf("la posicion del arreglo es %d\n",algo); imprime(x); */ //FIN DE UN BLOQUE COMENTADO----------------------------------(2) int resul=algo&0x01; //resul=((bit_de_paridad_de_algo)&(00000001)) if(resul) //resul vale (0 1) como un booleano implicito {printf("El numero es impar");} else {printf("El numero es par");} } //fin del main() int funcion(int x[]) //si es un arreglo el que se pasa por parametro { //no se le pone el apuntador & se pasa por valor int b=0; b=x[20]; return b; } void imprime(int x[]) { for(int f=1;f<21;f++) { printf("%d",x[f]); } } int funcionentero(int &algo){return algo;} //se pasa por referencia & por lo //que no modifica el valor de algo //en el main. Solo se pasa la //direccin de memoria donde esta //algo, las palabras coloreadas en //azul y violeta son palabras //reservadas de C/C++ y se les //conoce como tokens de C/C++

(40)

Apndice
En este captulo y para finalizar veremos los archivos de cabecera, donde estn declaradas las funciones que utilizaremos ms a menudo. Librera stdio.h (Librera estandar de C/C++)

printf Funcin: Escribe en la salida estndar con formato. Sintaxis: printf(<formato>,<arg1>, ...); scanf Funcin: Lee de la salida estndar con formato. Sintaxis: scanf(<formato>,<arg1>, ...); puts Funcin: Escribe una cadena y salto de lnea. Sintaxis: puts(<cadena>); gets Funcin: Lee y guarda una cadena introducida por teclado. Sintaxis: gets(<cadena>); fopen Funcin: Abre un fichero en el modo indicado. Sintaxis: pf=fopen(<fichero> , <modo de apertura>); fclose Funcin: Cierra un fichero cuyo puntero le indicamos. Sintaxis: fclose(<nombre_puntero>); fprintf Funcin: Escribe con formato en un fichero. Sintaxis: fprintf(<nombre_puntero> , <formato> , <arg1> , ...); fgets Funcin: Lee una cadena de un fichero. Sintaxis: fgets(<cadena> , <longitud> , <nombre_puntero>); Librera stdlib.h (Librera estandar de C/C++)

atof Funcin: Convierte una cadena de texto en un valor de tipo float. Sintaxis: float <nomb_variable> = atof(<cadena>); atoi Funcin: Convierte una cadena de texto en un valor de tipo entero. Sintaxis: int <nomb_variable>= atoi(<cadena>);

(41)

itoa Funcin: Convierte un valor numrico entero en una cadena de texto. La base generalmente ser 10, aunque se puede indicar otra distinta. Sintaxis: itoa(<nmero> , <cadena> , <base>); exit Funcin: Termina la ejecucin y abandona el programa. Sintaxis: exit(<variable_estado>); /* Normalmente el estado ser 0 */ Librera conio.h (Librera estandar de C/C++)

clrscr Funcin: Borra la pantalla. Sintaxis: clrscr( ); es lo mismo que system(cls) ; clreol Funcin: Borra desde la posicin del cursor hasta el final de la lnea. Sintaxis: clreol( ); gotoxy Funcin: Cambia la posicin del cursor a las coordenadas indicadas. Sintaxis: gotoxy(<columna> , <fila>); textcolor Funcin: Selecciona el color de texto (0 - 15). Sintaxis: textcolor(<variable_color>); textbackground Funcin: Selecciona el color de fondo (0 - 7). Sintaxis: textbackground(<variable_color>); wherex Funcin: Retorna la columna en la que se encuentra el cursor. Sintaxis: <variable_columna>=wherex( ); wherey Funcin: Retorna la fila en la que se encuentra el cursor. Sintaxis: <variable_fila>=wherey( ); getch Funcin: Lee y retorna un nico caracter introducido mediante el teclado por el usuario. No muestra el carcter por la pantalla. Sintaxis: char <nomb_variable> =getch(); getche Funcin: Lee y retorna un nico carcter introducido mediante el teclado por el usuario. Muestra el carcter por la pantalla. Sintaxis: char <nomb_variable> = getche(); (42)

Librera string.h

(Librera estndar de C++)

strlen Funcin: Calcula la longitud de una cadena. Sintaxis: int <nomb_variable>=strlen(<cadena>); strcpy Funcin: Copia el contenido de una cadena sobre otra. Sintaxis: strcpy(<cadena_a_sobre_escribir>,<cadena_original>); strcat Funcin: Concatena dos cadenas. Sintaxis: strcat(<cadena_1>,<cadena_2>,,<cadena_n>); strcmp Funcin: Compara el contenido de dos cadenas. Si cadena1 < cadena2 retorna un nmero negativo. Si cadena1 > cadena2, un nmero positivo, y si cadena1 es igual que cadena2 retorna 0 ( o NULL ). Sintaxis: int <nomb_variable>=strcmp(<cadena1>,<cadena2>); Funciones interesantes fflush(stdin) Funcin: Limpia el buffer de teclado. Sintaxis: fflush(stdin); Prototipo: stdio.h sizeof Funcin: Operador que retorna el tamao en bytes de una variable. Sintaxis: int <nomb_variable_2>= sizeof (nomb_variable_1|TDD); cprintf Funcin: Funciona como el printf pero escribe en el color que hayamos activado con la funcin textcolor sobre el color activado con textbackground. Sintaxis: cprintf(<formato> , <arg1> , ...); Prototipo: conio.h kbhit Funcin: Espera la pulsacin de una tecla para continuar la ejecucin. Sintaxis: while (!kbhit( )) /* Mientras no pulsemos una tecla... */ Prototipo: conio.h random Funcin: Retorna un valor aleatorio entre 0 y numero_limite-1. Sintaxis: int <nomb_variable>=random(<numero_limite>); /* Tambin necesitamos la funcin randomize */ Prototipo: stdlib.h

(43)

randomize Funcin: Inicializa el generador de nmeros aleatorios. Deberemos llamarlo al inicio de la funcin en que utilicemos el random. Tambin deberemos utilizar el include time.h, ya que randomize hace una llamada a la funcin time, incluida en este ltimo archivo. Sintaxis: randomize( ); Prototipo: stdio.h system Funcin: Ejecuta el comando indicado. Esto incluye tanto los comandos del sistema operativo, como cualquier programa que nosotros le indiquemos. Al acabar la ejecucin del comando, volver a la lnea de cdigo situada a continuacin de la sentencia system. Sintaxis: system (<comando>); /* p.ej: system("arj a programa"); */ Prototipo: stdlib.h Conversin de tipos en C++ (CDT) Entindase CDT en C como el cambio de contexto de un tipo de dato a otro contexto. Contexto es la manera en que el computador maneja el dato y opera con l. En C para realizar por lo general alguna CDT es necesario tener: Funcin principal Funcion(es) auxiliares Apuntador Expecificador de formato A simple vista C++ es bastante particular en la CDT y es un poco ms complejo que Java (porque Java es ms estandarizado), aunque se adquieren mucha flexibilidad en la programacin. A medida que se le conoce, se puede ir programando de una manera ms elegante en su cdigo fuente. La conversiones explcitas se fuerzan mediante moldes (casts). La conversin forzosa de tipos de C tiene el formato clsico: SINTAXIS: (<TDD>)<expresin>;

C++ ha modificado la notacin anterior por una notacin funcional como alternativa sintctica: SINTAXIS: <TDD>(<expresin>);

Las notaciones siguientes son equivalentes: float(x); (float)x; //notacin de casteo en C++ //notacin de casteo en C (44)

Ejemplo: Leer un registro y guardar la primera lnea tipo carcter en entero. int main()//accin principal { FILE *archivo; //archivo ciudades.txt int x=0,y=0,a=0,z=0,m=0; int matriz[10][10]; // declaracin de una matriz declarada 10x10 [0..9][0..9] char arreglo[100]; //arreglo de caracteres de 0 a 99 char n[4]; //arreglo de caracteres archivo=fopen("ciudades.txt","r"); //Abre el archivo en modo Lectura printf("\nIntroduzca un numero natural: "); scanf("%d",&x);//lee la opcin de ciudad if(x==1) { //Opcin 1 archivo=fopen("ciudades.txt","r");//Abre el archivo en modo Lectura while(z<y) { fgets(arreglo,100,archivo); /*toma la lnea del archivo con 100 caracteres, lo almacena en ARREGLO*/ if(z==(y-1)) { printf("%s\n\n",arreglo); /*muestra la informacin de la ciudad seleccionada*/ } z++; } main(); //recursin para mostrar el men principal } if(x==2) { archivo=fopen("ciudades.txt","r"); //Abre el archivo en modo Leer /*Un archivo se puede abrir varias veces en C*/ fscanf(archivo,"%s",&n); /*Toma la primera linea del archivo y lo almacena en n*/ printf("\nEl numero de ciudades es: %s\n\n",n); //Muestra el entero a=atoi(n); /*Transforma el Valor de N a un entero y lo almacena en "a"*/ printf(%d,a); //imprime el entero } return 0; }

(45)

Excepciones en C Es un mecanismo de gestin de errores incorporado. Permite gestionar y responder a los errores en tiempo de ejecucin. Las excepciones estn construidas a partir de tres palabras clave: try, catch y throw. Cualquier sentencia que provoque una excepcin debe haber sido ejecutada desde un bloque try o desde una funcin que este dentro del bloque try. Cualquier excepcin debe ser capturada por una sentencia cath que sigue a la sentencia try, causante de la excepcin. SINTAXIS:

try { } <cuerpo>;

catch(<tipo_1 arg>) { }

<bloque_1> catch;

catch(<tipo_2 arg>) { } catch(<tipo_n arg>) { } <bloque_2> catch;

<bloque_n> catch;

(46)

EJEMPLO:

#include <iostream.h> #include <stdio.h> #include <conio.h> void main() { try{ cout<<"Dentro del bloque try\n"; throw 10; cout<<"Esto se ejecuta si no hay problemas"; } catch(int i){ cout<<"Capturado el error "<< i; cout<<"\n"; } cout << "fin"; getch();

Operaciones con Objetos en C++ ASIGNACIN DE OBJETOS: Se puede asignar un objeto a otro a condicin de que ambos objetos sean del mismo tipo (misma clase). Cuando un objeto se asigna a otro se hace una copia a nivel de bits de todos los miembros, es decir se copian los contenidos de todos los datos. Los objetos continan siendo independientes.

Sintaxis: <objeto_destino>=<objeto_origen>;

(47)

EJEMPLO:

#include <iostream.h> #include <stdio.h> #include <conio.h> class miclase{ int a,b; public: void obtener(int i, int j){a=i;b=j;} void mostrar(){cout << a << " "<< b << "\n";} }; void main() { miclase o1,o2; o1.obtener(10,4); o2=o1; o1.show(); o2.show(); getch(); }

ARRAY DE OBJETOS: Los objetos son variables y tienen las mismas capacidades y atributos que cualquier tipo de variables, por tanto es posible disponer objetos en un array. La sintaxis es exactamente igual a la utilizada para declarar y acceder al array. Tambin disponemos de arrays bidimensionales. DECLARACIN:

<nombre_clase> <nombre_objeto>[<n elementos>]; <nombre_clase> <nombre_objeto>[<n elementos>]= {<elemento_1>,<elemento_2>,,<elemento_n>};

INICIALIZACIN: <nombre_objeto>[<ndice>].funcin(<valores>);

(48)

EJEMPLO: Unidimensional.

#include <iostream.h> #include <stdio.h> #include <conio.h> class ejemplo{ int a; public: void pasar(int x){a=x;} int mostrar() {return a;} }; void main() { ejemplo ob[4]; int indice; clrscr(); for(indice=0;indice<4;indice++) ob[indice].pasar(indice); for(indice=0;indice<4;indice++) { cout << ob[indice].mostrar(); cout << "\n"; } getch(); }

(49)

EJEMPLO: Bidimensional.
#include <iostream.h> #include <stdio.h> #include <conio.h> class bidi{ int a,b; public: bidi(int n, int m){a=n;b=m;} int pasa_a(){return a;} int pasa_b(){return b;} }; void main() { clrscr(); int fil,col; bidi objeto[3][2]={ bidi(1,2),bidi(3,4), bidi(5,6),bidi(7,8), bidi(9,10),bidi(11,12)}; for(fil=0;fil<3;fil++) { for(col=0;col<2;col++) { cout << objeto[fil][col].pasa_a(); cout << " "; cout << objeto[fil][col].pasa_b(); cout << "\n"; } } getch(); } PASO DE OBJETOS A FUNCIONES: Los objetos se pueden pasar a funciones como argumentos de la misma manera que se pasan otros tipos de datos. Hay que declarar el parmetro como un tipo de clase y despus usar un objeto de esa clase como argumento cuando se llama a la funcin. Cuando se pasa un objeto a una funcin se hace una copia de ese objeto. Cuando se crea una copia de un objeto porque se usa como argumento para una funcin, no se llama a la funcin constructora. Sin embargo, cuando la copia se destruye (al salir de mbito), se llama a la funcin destructora.

(50)

PROTOTIPO DE FUNCIN:

<TDD_devuelto> <nombre_funcion>(<nombre_clase> <nombre_objeto>) { <cuerpo>; }


LLAMADA A LA FUNCIN:

<nombre_funcion>(<objeto>); EJEMPLO:
#include <iostream.h> #include <stdio.h> #include <conio.h> class objetos{ int i; public: objetos(int n){i=n;} int devol(){return i;} }; int sqr(objetos o) { return o.devol()*o.devol(); } void main() { objetos a(10), b(2); cout << sqr(a); cout << sqr(b); getch(); }

OBJETOS DEVUELTOS POR FUCIONES: Al igual que se pueden pasar objetos, las funciones pueden devolver objetos. Primero hay que declarar la funcin para que devuelva un tipo de clase. Segundo hay que devolver un objeto de ese tipo usando la sentencia return. Cuando un objeto es devuelto por una funcin, se crea automticamente un objeto temporal que guarda el valor devuelto. Este es el objeto que realmente devuelve la funcin. Despus el objeto se destruye, esto puede causar efectos laterales inesperados.

(51)

EJEMPLO:
#include <iostream.h> #include <stdio.h> #include <conio.h> #include <string.h> class ejemplo{ char cadena[80]; public: void muestra(){cout<<cadena<<"\n";} void copia(char *cad){strcpy(cadena,cad);} }; ejemplo entrada() { char cadena[80]; ejemplo str; cout<<"Introducir cadena: "; cin>>cadena; str.copia(cadena); return str; } void main() { ejemplo ob; ob=entrada(); ob.muestra(); getch(); }

PUNTEROS A OBJETOS: Hasta ahora se ha accedido a miembros de un objeto usando el operador punto. Es posible acceder a un miembro de un objeto a travs de un puntero a ese objeto. Cuando sea este el caso, se emplea el operador de flecha (->) en vez del operador punto. Para obtener la direccin de un objeto, se precede al objeto con el operador &. Se trabaja de igual forma que los punteros a otros tipos.

(52)

EJEMPLO:
#include <iostream.h> #include <stdio.h> #include <conio.h> class miclase{ int a; public: miclase(int x); int get(); }; miclase::miclase(int x) { a=x; } int miclase::get() { return a; } void main() { clrscr(); miclase obj(200); miclase *p; p=&obj; cout << "El valor del Objeto es " << obj.get(); cout << "El valor del Puntero es " << p->get(); getch(); }

Funciones Constructoras y Destructoras En los programas hay partes que requieren inicializacin. Esta necesidad de inicializacin es incluso ms comn cuando se est trabajando con objetos. Para tratar esta situacin, C++ permite incluir una funcin constructora. A estas funciones se las llama automticamente cada vez que se crea un objeto de esa clase. La funcin constructora debe tener el mismo nombre que la clase de la que es parte, no tienen tipo devuelto, es ilegal que un constructor tenga un tipo devuelto. Pero si es posible pasarle valores a modo de parmetros. Prototipo de la funcin: <nombre_funcin>(<parmetros>); Desarrollo de la funcin: <nombre_clase>::<nombre_funcin>(<parmetros>){cuerpo;}

(53)

EJEMPLO:
#include <iostream.h> #include <stdio.h> #include <conio.h> class miclase{ int a; public: miclase(); void show(); }; miclase::miclase() { a=100; } void miclase::show() { cout << a; } void main() { clrscr(); miclase obj; obj.show(); getch(); } El complemento de un constructor es la funcin destructora. A esta funcin se la llama automticamente cuando se destruye el objeto. El nombre de las funciones destructoras debe ser el mismo que el de la clase a la que pertenece precedido del carcter ~ (alt+126). Los objetos de destruyen cuando se salen de mbito cuando son locales y al salir del programa si son globales. Las funciones destructoras no devuelven tipo y tampoco pueden recibir parmetros. Tcnicamente un constructor y un destructor se utilizan para inicializar y destruir los objetos, pero tambin se pueden utilizar para realizar cualquier otra operacin. Sin embargo esto se considera un estilo de programacin pobre.

PROTOTIPO DE LA FUNCIN DESTRUCTOR:


~<nombre_funcin>(<parmetros>);

(54)

DESARROLLO DE LA FUNCION:
<nombre_clase>::<nombre_funcin>() { <cuerpo>; }

EJEMPLO: Mismo programa de antes aadiendo una funcin destructora.

#include <iostream.h> #include <stdio.h> #include <conio.h> class miclase{ int a; public: miclase(); ~miclase(); void show(); }; miclase::miclase() { a=100; } miclase::~miclase() { cout << "Destruyendo...\n"; getch(); } void miclase::show() { cout << a; } void main() { clrscr(); miclase obj; obj.show(); getch(); }

(55)

CONSTRUCTORES CON PARAMETROS: Es posible pasar argumentos a una funcin constructora. Para permitir esto, simplemente aada los parmetros a la declaracin y definicin de la funcin constructora. Despus, cuando declare un objeto, especifique los parmetros como argumentos.

EJEMPLO:
#include <iostream.h> #include <stdio.h> #include <conio.h> class miclase{ int a; public: miclase(int x); void mostrar(); }; miclase::miclase(int x) { cout << "Constructor"; a=x; } void miclase::miclase() { cout <<"El valor de a es: "; cout << a; } void main() { miclase objeto(4); ob.show(); getch(); }

Sobrecarga de Funciones y Operadores

En C++ dos o ms funciones pueden compartir el mismo nombre en tanto en cuanto difiera el tipo de sus argumentos o el nmero de sus argumentos o ambos. Cuando comparten el mismo nombre y realizan operaciones distintas se dice que estn sobrecargadas. Para conseguir la sobrecarga simplemente hay que declarar y definir todas las versiones requeridas. Tambin es posible y es muy comn sobrecargar las funciones constructoras. Hay 3 razones por las que sobrecargar las funciones constructoras. Primero ganar flexibilidad, permitir arrays y construir copias de constructores (56)

EJEMPLO:
#include <iostream.h> #include <conio.h> #include <stdio.h> int abs(int numero); long abs(long numero); double abs(double numero); void main() { clrscr(); cout <<"Valor absoluto de -10 "<< abs(-10) <<"\n"; cout <<"Valor absoluto de -10L "<< abs(-10L) <<"\n"; cout <<"Valor absoluto de -10.01 "<< abs(-10.01) <<"\n"; getch(); } int abs(int numero) { return numero<0 ? -numero:numero; } long abs(long numero) { return numero<0 ? -numero:numero; } double abs(double numero) { return numero<0 ? -numero:numero; } /*EJEMPLO otro programa*/ #include <iostream.h> #include <stdio.h> #include <conio.h> void fecha(char *fecha); void fecha(int anno, int mes, int dia); void main() { clrscr(); fecha("23/8/98"); fecha(98,8,23); getch(); } void fecha(char *fecha) { cout<<"Fecha: "<<fecha<<"\n"; } void fecha(int anno,int mes,int dia) { cout<<"Fecha: "<<dia<<"/"<<mes<<"/"<<anno; } (57)

ARGUMENTOS IMPLICITOS: Otra caracterstica relacionada con la sobrecarga es la utilizacin de argumentos implcitos que permite dar un valor a un parmetro cuando no se especifica el argumento correspondiente en la llamada a la funcin.

PROTOTIPO: <TDD_devuelto>(<var_1>=<valor>,<var_2>=<valor>,<var_n>=<valor>);

EJEMPLO:
#include<iostream.h> #include<stdio.h> #include<conio.h> void funcion(int a=0, int b=0) { cout<<"a: "<< a <<" b: "<< b <<"\n"; } void main() { clrscr(); funcion(); funcion(10); funcion(20,30); getch(); } Es muy similar a la sobrecarga de funciones, un operador siempre se sobrecarga con relacin a una clase. Cuando se sobrecarga un operador no pierde su contenido original, gana un contenido relacionado con la clase. Para sobrecargar un operador se crea una funcin operadora que normalmente ser una funcin amiga a la clase.

PROTOTIPO: <TDD_devuelto> <nombre_clase>::<operador> <operador>(<parmetros>)


{ } <cuerpo>;

(58)

Se pueden realizar cualquier actividad al sobrecargar los operadores pero es mejor que las acciones de un operador sobrecargado se ajusten al uso normal de ese operador. La sobrecarga tiene dos restricciones, no puede cambiar la precedencia del operador y que el numero de operadores no puede modificarse. Tambin hay operadores que no pueden sobrecargarse.

OPERADORES

. :: ?? .*

Existen 3 tipos de sobrecarga de operadores. Operadores binarios, operadores lgicos-relacionales y operadores unarios. Cada uno de ellos debe tratarse de una manera especfica para cada uno de ellos. BINARIOS: La funcin solo tendr un parmetro. Este parmetro contendr al objeto que este en el lado derecho del operador. El objeto del lado izquierdo es el que genera la llamada a la funcin operadora y se pasa implcitamente a travs de this.

(59)

EJEMPLO:
#include <iostream.h> #include <stdio.h> #include <conio.h> class opera{ int x, y; public: opera() {x=0;y=0;} opera(int i, int j) {x=i; y=j;} void obtenxy(int &i,int &j) {i=x; j=y;} opera operator+(opera obj); }; opera opera::operator+(opera obj) { opera temp; temp.x=x+obj.x; temp.y=y+obj.y; return temp; } void main() { opera obj1(10,10), obj2(5,3),obj3; int x,y; obj3=obj1+obj2; obj3.obtenxy(x,y); cout << "Suma de obj1 mas obj2\n "; cout << "Valor de x: "<< x << " Valor de y: " << y; getch(); }

LGICOS Y RELACIONALES: Cuando se sobrecargan dichos operadores no se desear que las funciones operadoras devuelvan un objeto, en lugar de ello, devolvern un entero que indique verdadero o falso. Esto permite que los operadores se integren en expresiones lgicas y relacionales ms extensas que admitan otros tipos de datos.

(60)

EJEMPLO:
#include <iostream.h> #include <stdio.h> #include <conio.h> class opera{ int x,y; public: opera() {x=0;y=0;} opera(int i,int j) {x=i; y=j;} void obtenerxy(int &i, int &j) {i=x; j=y;} int operator==(opera obj); }; int opera::operator==(opera obj) { if(x==obj.x && y==obj.y) return 1; else return 0; } void main() { clrscr(); opera obj1(10,10), obj2(5,3); if(obj1==obj2) cout << "Objeto 1 y Objeto 2 son iguales"; else cout << " Objeto 1 y objeto 2 son diferentes"; getch(); }

UNARIOS: El miembro no tiene parmetro. Es el operando el que genera la llamada a la funcin operadora. Los operadores unarios pueden preceder o seguir a su operando, con lo que hay que tener en cuenta como se realiza la llamada.

(61)

EJEMPLO:
#include <iostream.h> #include <stdio.h> #include <conio.h> class opera{ int x, y; public: opera() {x=0;y=0;} opera(int i, int j) {x=i;y=j;} void obtenxy(int &i, int &j) {i=x; j=y;} opera operator++(); }; opera opera::operator++() { x++; y++; } void main() { clrscr(); opera objeto(10,7); int x,y; objeto++; objeto.obtenxy(x,y); cout<< "Valor de x: " << x <<" getch(); } Prioridad de operadores: () -(unario),/\,\/ div,mod,*,/ +,>=,<=,<,> =, o,y --> (Parntesis) (negacin, y , o ) (divisin en N, multiplicacin y divisin) (suma, resta) (Relaciones de orden) (Relacin) (operadores lgicos) (Asignacin) _ +

Valor de y: "<< y << "\n";

(62)

Funciones InLine y Automticas La ventaja de las funciones insertadas es que se pueden ejecutar ms rpidamente que las funciones normales. La llamada y vuelta de una funcin normal tardan tiempo y si tienen parmetros incluso ms. Para declarar este tipo de funciones simplemente hay que preceder la definicin de la funcin con el especificador inline. Sintaxis:

inline <TDD_devuelto> <nombre_funcin> ( <parmetros> ){<cuerpo>;}


Las llamadas a las funciones insertadas se realizan de la misma manera que cualquier funcin. Uno de los requisitos es que se tiene que definir antes de llamarla, es decir definir y desarrollar antes de la funcin main. Si el compilador no es capaz de cumplir la peticin, la funcin se compila como una funcin normal y la solicitud inline se ignora. Las restricciones son cuatro, no puede contener variables de tipo static, una sentencia de bucle, un switch o un goto. EJEMPLO: En este programa utilizamos una funcin inline pasando valores. No usa clases ni objetos.

#include <iostream.h> #include <stdio.h> #include <conio.h> inline int valor(int x) { return !(X%2);} void main() { int a; cout <<"Introducir valor: "; cin >> a; if (valor(a)) cout << "Es par "; else cout << "Es impar"; } La caracterstica principal de las funciones automticas es que su definicin es lo suficientemente corta y puede incluirse dentro de la declaracin de la clase. La palabra inline no es necesaria. Las restricciones que se aplican a las funciones inline se aplican tambin para este tipo. El uso ms comn de las funciones automticas es para funciones constructoras. Sintaxis <valor_devuelto><nombre_funcin> (<parmetros>){<cuerpo>;}

(63)

EJEMPLO: Mismo programa anterior pero sin utilizar inline.

#include <iostream.h> #include <stdio.h> #include <conio.h> class ejemplo{ public: int valor(int x) { return !(X%2);} }; void main() { int a; cout <<"Introducir valor: "; cin >> a; if (valor(a)) cout << "Es par "; else cout << "Es impar"; }

Utilizacin de Estructuras como Clases En C++, la definicin de una estructura se ha ampliado para que pueda tambin incluir funciones miembro, incluyendo funciones constructoras y destructoras como una clase. De hecho, la nica diferencia entre una estructura y una clase es que, por omisin, los miembros de una clase son privados y los miembros de una estructura son pblicos. struct <nombre>{ /*variables y funciones publicas; */ private: /*es un MDA*/ /*variables y funciones privadas;*/ }; Aunque las estructuras tienen las mismas capacidades que las clases, se reserva el uso de struct para objetos que no tienen funciones miembro. Una de las razones de la existencia de las estructuras es mantener compatibilidad con los programas hechos C.

(64)

EJEMPLO: #include <iostream.h> #include <stdio.h> #include <string.h> #include <conio.h> struct tipo{ tipo(double b, char *n); void mostrar(); private: double balance; char nombre[40]; }; tipo::tipo(double b, char *n) { balance=b; strcpy(nombre,n); } void tipo::mostrar() { cout << "Nombre: " << nombre; cout << ": $" << balance; if (balance<0.0) cout << "****"; cout << "\n"; } void main() { clrscr(); tipo acc1(100.12,"Ricardo"); tipo acc2(-12.34,"Antonio"); acc1.mostrar(); getch(); clrscr(); acc2.mostrar(); getch(); } Como ejemplo a lo anterior crearemos el primer programa utilizando objetos y clases para ver la teora llevada a la prctica. Seguiremos utilizando las mismas sentencias que usbamos en C, ms adelante los programas tomarn la estructura exclusiva de C++.

(65)

EJEMPLO: #include <stdio.h> #include <conio.h> class miclase{ int a; public: void pasar_a(int num); int mostrar_a(); }; void miclase::pasar_a(int num) { a=num; } int miclase::mostrar_a() { return a; } void main() { miclase obj1, obj2; clrscr(); obj1.pasar_a(10); obj2.pasar_a(99); printf("%d\n",obj1.mostrar_a()); printf("%d\n",obj2.mostrar_a()); getch(); }

This, New y Delete This es un puntero que se pasa automticamente a cualquier miembro cuando se invoca. Es un puntero al objeto que genera la llamada, por tanto la funcin recibe automticamente un puntero al objeto. A este puntero se referencia como this y solo se pasa a los miembros punteros this. Sintaxis:

<objeto.funcion>(); // a la funcin recibe automticamente el puntero this.

(66)

EJEMPLO: El primero sin puntero this. El segundo utilizando el puntero this. // #include <iostream.h> #include <stdio.h> #include <conio.h> #include <string.h> class stock{ char item[20]; double coste; public: stock(char *i,double c) { strcpy(item,i); coste=c; } void muestra(); }; void stock::muestra() { cout<<item << "\n"; cout<<"PVP: " << coste; } void main() { clrscr(); stock obj("tuerca",5.94); obj.muestra(); getch(); } // 2.#include <iostream.h> #include <stdio.h> #include <conio.h> #include <string.h> class stock{ char item[20]; double coste; public: stock(char *i,double c) { strcpy(this->item,i); this->coste=c; } void muestra(); }; 1.-

(67)

void stock::muestra() /*Esta es la continuacin el cdigo*/ { cout<<this->item << "\n"; cout<<"PVP: " << this->coste; } void main() { clrscr(); stock obj("tuerca",5.94); obj.muestra(); getch(); } Hasta ahora si se necesitaba asignar memoria dinmica, se haca con malloc y para liberar se utilizaba free. En C++ se puede asignar memoria utilizando new y liberarse mediante delete. Estos operadores no se pueden combinar unas con otras, es decir debe llamarse a delete solo con un puntero obtenido mediante new. Los objetos tambin se les puede pasar un valor inicial con la sentencia new. SINTAXIS:

<nombre_puntero> =new <tipo>; delete <nombre_puntero>; <nombre_puntero>=new <TDD>(<valor_inicial>);


Tambin se pueden crear arrays asignados dinmicamente, estos arrays pueden utilizar la sentencia new. La sintaxis general es: DECLARACION DEL ARRAY: SINTAXIS:

<nombre_puntero>=new <TDD>[<tamao>]; /*sin inicializar*/


EJEMPLO:

#include<iostream.h> #include<stdio.h> #include<conio.h> #include<stdlib.h> class cosas{ int i,j; public: void obten(int a,int b){i=a;j=b;} int muestra(){return i*j;} };

(68)

Ejemplo: void main() { clrscr(); int *p_var; p_var=new int; //p_var=new int(9); se asigna un valor inicial. cosas *p; p=new cosas; if(!p || !p_var) { cout<<"Error de asignacion\n"; exit(1); } *p_var=1000; p->obten(4,5); cout<<"El entero en p_var es: " <<*p_var; cout<<"\nTotal: " <<p->muestra(); getch();

EJEMPLO: Array asignado dinmicamente. #include<iostream.h> #include<stdio.h> #include<conio.h> #include<stdlib.h> void main(void) { int *p; int i; p=new int[5]; clrscr(); if(!p) { cout<<"Error de asignacion\n"; exit(1); } for(i=0;i<5;i++) p[i]=i+1; for(i=0;i<5;i++) { cout<<"Este es el entero en p["<<i<<"]:"; cout<<p[i]<<"\n"; } delete[] p; getch(); }

(69)

Referencias C++ consta de una particularidad relacionada con los punteros, denominada referencia. Una referencia es un puntero implcito que se comporta como una variable normal siendo un puntero. Existen tres modos de utilizar una referencia. Se puede pasar a una funcin, ser devuelta de una funcin y crearse como una referencia independiente. Lo que apunta una referencia no puede ser modificado. El caso de las referencias independientes es muy poco comn y casi nunca se utilizan, en este manual no se hace referencia a ellas. En el ejemplo siguiente se compara un programa que utiliza un puntero normal y otro programa que realiza las mismas operaciones utilizando una referencia que se pasa a una funcin. EJEMPLO:

//Utilizando punteros normal. #include <iostream.h> #include <stdio.h> #include <conio.h> void f(int *n); void main() { int i=0; f(&i); cout<<"valor i:" << i; getch(); } void f(int *n) { *n=100; } //Utilizando referencias. #include <iostream.h> #include <stdio.h> #include <conio.h> void f(int &n); void main() { int i=0; f(i); cout<<"valor i:"<< i; getch(); } void f(int &n) { n=100; } (70)

En el caso de las referencias devueltas por una funcin se puede poner el nombre de la funcin en el lado izquierdo de la expresin. Es como asignar un valor a una variable. Hay que tener en cuenta el mbito de la variable que se comporta como una referencia. EJEMPLO: #include <iostream.h> #include <stdio.h> #include <conio.h> int &f(); int x; void main() { clrscr(); f()=100; cout<<"Valor de x: " <<x; getch(); } int &f() { return x; } Herencia Para empezar, es necesario definir dos trminos normalmente usados al tratar la herencia. Cuando una clase hereda otra, la clase que se hereda se llama clase base. La clase que hereda se llama clase derivada. La clase base define todas las cualidades que sern comunes a cualquier clase derivada. Otro punto importante es el acceso a la clase base. El acceso a la clase base pude tomar 3 valores, public, private y protected. Si el acceso es public, todos los atributos de la clase base son pblicos para la derivada. Si el acceso es private, los datos son privados para la clase base la derivada no tiene acceso. Si el acceso es protected, datos privados para la base y derivada tiene acceso, el resto sin acceso. La clase derivada se le conoce tambien como clase hija y a la clase base se le conoce tambien como clase madre.

(71)

EJEMPLO: para comprobar los distintos tipos de acceso. #include <iostream.h> #include <stdio.h> #include <conio.h> class miclase{ int a; protected: int b; public: int c; miclase(int n,int m){a=n;b=m;} int obten_a(){return a;} int obten_b(){return b;} }; void main() { miclase objeto(10,20); clrscr(); objeto.c=30; // objeto.b=30; error,sin acceso. // objeto.a=30; error,sin acceso. cout<<objeto.obten_a() <<"\n"; cout<<objeto.obten_b() <<"\n"; cout<<objeto.c; getch(); } FORMATO DE la clase hija (sintaxis): class <nombre_de_clase_hija>:<MDA> <nombre_de_clase_madre>{ <cuerpo>; }; EJEMPLO: Herencia pblica. #include <iostream.h> #include <stdio.h> #include <conio.h> class base{ int x; public: void obten_x(int a){x=a;} void muestra_x(){cout<< x;} }; class derivada:public base{ int y; public: void obten_y(int b){y=b;} void muestra_y(){cout<<y;} }; (72)

Herencia Simple Clase Madre: Conjunto de objetos

Clase Hija: Prototipos de objetos heredados


(Encapsulamiento)

void main() /*este cdigo es la continuacin de otro*/ { derivada obj; /*obj es una variable de tipo derivada*/ clrscr(); /*se limpia la pantalla*/ obj.obten_x(10); /*se llama al mtodo obten_x heredado en derivada*/ obj.obten_y(20); /*se llama al mtodo obten_y propio de derivada*/ obj.muestra_x();/*se llama al mtodo muestra_x heredado en derivada*/ cout<<"\n"; /*imprime una salida*/ obj.muestra_y(); /*se llama al mtodo muestra_y propio de derivada*/ getch(); /*se lee un carcter*/ } EJEMPLO: Herencia con acceso privado. #include <iostream.h> #include <stdio.h> #include <conio.h> class base{ int x; public: void obten_x(int a){x=a;} void muestra_x(){cout<<x <<"\n";} }; class derivada:private base{ int y; public: void obten_xy(int a,int b){obten_x(a);y=b;} void muestra_xy(){muestra_x();cout<<y<<"\n";} }; void main() { clrscr(); derivada ob; ob.obten_xy(10,20); ob.muestra_xy(); // ob.obten_x(10); error,sin acceso. // ob.muestra_x(); error,sin acceso. getch(); } HERENCIA MULTIPLE: Existen dos mtodos en los que una clase derivada puede heredar ms de una clase base. El primero, en el que una clase derivada puede ser usada como la clase base de otra clase derivada, crendose una jerarqua de clases. El segundo, es que una clase derivada puede heredar directamente ms de una clase base. En esta situacin se combinan dos o ms clases base para facilitar la creacin de la clase derivada.

(73)

SINTAXIS: Para construir la derivada mediante varias clases base.

class <nom_derivada>:<MDA> <nomb_base1>,<nomb_base2>,<nomb_baseN<{ <cuerpo>; /*<nomb_base_n> = <nombre_clase_base_n>*/ }; SINTAXIS: Para crear herencia mltiple de modo jerrquico. class <nomb_derivada_1>:<MDA> <nomb_clase_base_1> <cuerpo>; }; class <nomb_derivada_2>:<MDA> < nomb_derivada_1> <cuerpo>; }; {

class <nomb_derivada_N>:<MDA> < nomb_derivada_(N-1)>{ <cuerpo>; }; EJEMPLO: Herencia de tipo jerrquica. #include <iostream.h> #include <stdio.h> #include <conio.h> class base_a{ int a; public: base_a(int x){a=x;} int ver_a(){return a;} }; class deriva_b:public base_a { int b; public: deriva_b(int x, int y):base_a(x){b=y;} int ver_b(){return b;} };

(74)

class deriva_c:public deriva_b


{ int c; public: deriva_c(int x,int y,int z):deriva_b(x,y){c=z;} void ver_todo() { cout<<ver_a()<<" "<<ver_b()<<" "<<c; } }; void main() { clrscr(); deriva_c ob(1,2,3); ob.ver_todo(); cout<<"\n"; cout<<ob.ver_a()<<" "<<ob.ver_b(); getch(); } El caso de los constructores es un poco especial. Se ejecutan en orden descendente, es decir primero se realiza el constructor de la clase base y luego el de las derivadas. En las destructoras ocurre en orden inverso, primero el de las derivadas y luego el de la base. EJEMPLO: Mltiple heredando varias clases base.

#include <iostream.h> #include <stdio.h> #include <conio.h> class B1{ int a; public: B1(int x){a=x;} int obten_a(){return a;} }; class B2{ int b; public: B2(int x){b=x;} int obten_b(){return b;} }; class C1:public B1,public B2{ int c;

(75)

public: C1(int x,int y,int z):B1(z),B2(y) { c=x; } void muestra() { cout<<obten_a()<<" "<<obten_b()<<" "; cout<<c<<"\n"; } }; void main() { clrscr(); C1 objeto(1,2,3); objeto.muestra(); getch(); } Funciones Virtuales Una funcin virtual es miembro de una clase que se declara dentro de una clase base y se redefine en una clase derivada. Para crear una funcin virtual hay que preceder a la declaracin de la funcin la palabra clave virtual. Debe tener el mismo tipo y numero de parametros y devolver el mismo tipo. Cada redefinicin de la funcin virtual en una clase derivada expresa el funcionamiento especifico de la misma con respecto a esa clase derivada. Cuando se redefine una funcin virtual en una clase derivada NO es necesaria la palabra virtual. EJEMPLO:

#include<iostream.h> #include<stdio.h> #include<conio.h> class base{ public: int i; base(int x){i=x;} virtual void func(){cout<<i<<"\n";} }; class derivada1:public base{ public: derivada1(int x):base(x){}; void func(){ cout <<i*i<<"\n";} };

(76)

class derivada2:public base{ public: derivada2(int x):base(x){}; void func(){cout<<i+i;} }; void main() { base obj1(10); derivada1 obj2(10); derivada2 obj3(10); obj1.func(); obj2.func(); obj3.func(); getch(); } Funciones Amigas Habr momentos en los que se quiera que una funcin tenga acceso a los miembros privados de una clase sin que esa funcin sea realmente un miembro de esa clase. De cara a esto estn las funciones amigas. Son tiles para la sobrecarga de operadores y la creacin de ciertos tipos de funciones E/S. El prototipo de esta funciones viene precedido por la palabra clave friend, cuando se desarrolla la funcin no es necesario incluir friend. Una funcin amiga no es miembro y no se puede calificar mediante un nombre de objeto. Estas funciones no se heredan y pueden ser amigas de ms de una clase.

PROTOTIPO: (sintaxis)
friend <TDD_devuelto> <nombre_funcin> (<parmetros>);

DESARROLLO:
<TDD_devuelto> < nombre_funcin> (<parmetros>) { }

<cuerpo>;

(77)

EJEMPLO:

#include <iostream.h> #include <stdio.h> #include <conio.h> class miclase{ int n,d; public: miclase(int i, int j){n=i;d=j;} friend int factor(miclase ob); }; int factor(miclase ob) { if (!(ob.n%ob.d)) return 1; else return 0; } void main() { miclase obj1(10,2), obj2(3,2); if(factor(obj1)) cout << "es factor"; else cout << "no es factor"; getch(); }

(78)

Tipo de Dato Referencia Tambien llamado apuntador, o pointer. Una referencia no es ms que un tipo de dato elemental que representa una direccin de memoria en donde por lo general se encuentra un dato, sea elemental o estructurado. Los apuntadores son la base para la creacin de la mayora de las estructuras dinmicas, como listas, rboles y grafos. La cantidad de memoria que ocupa cada variable tipo referencia es una palabra. Apuntadores en C (tambien se les conoce como punteros) Un Apuntador es una variable que contiene una direccin de memoria, la cual corresponder a un dato o a una variable que contiene el dato. Los apuntadores tambin deben de seguir las mismas reglas que se aplican a las dems variables, deben tener nombre nicos y deben de declararse antes de usarse. Cada variable que se utiliza en una aplicacin ocupa una o varias posiciones de memoria. Estas posiciones de memoria se acceden por medio de una direccin:

En la figura el texto Hello sta guardado en memoria, comenzando en la direccin 1000. Cada carcter ocupa un espacio de direccin nico en memoria. Los apuntadores proporcionan un mtodo para conservar y llegar a estas direcciones en memoria. Los apuntadores facilitan el manejo de datos, debido a que conservan la direccin de otra variable o ubicacin de datos. Por qu son Importantes los Apuntadores? Los apuntadores dan flexibilidad a los programas en C++ y permiten que estos crezcan dinmicamente. Utilizando un apuntador hacia un bloque de memoria que se asigna al momento de ejecucin, un programa puede ser ms flexible que uno que asigna toda su memoria de una sola vez. Tambin, un apuntador es ms fcil de guardar que una estructura grande o un objeto de una clase. Debido a que un apuntador slo guarda una direccin, puede fcilmente pasarse a una funcin. Uno de las desventajas que pueden presentar los apuntadores es que un apuntador sin control o no inicializado puede provocar fallas en el sistema, adems de que su uso incorrecto puede generar fallas muy complejas de hallar. Operadores de Indireccin y Direccin: Hay 2 operadores que se usan cuando trabajan con direcciones en un programa C; el Operador de Indireccin ( * ) y el de Direccin ( & ). Estos operadores son diferentes de los tratados anteriormente.

(79)

El Operador de Direccin ( & ) regresa la direccin de una variable. Este operador est asociado con la variable a su derecha: &h; Esta lnea regresa la direccin de la variable h. El Operador de Indireccin ( * ) trabaja a la inversa del operador de Direccin. Tambin esta asociado con la variable a su derecha, toma la direccin y regresa el dato que contiene esa direccin. Por ejemplo, la siguiente lnea determina la direccin de la variable h y luego usa el operador de Indireccin para acceder a la variable y darle un valor de 42: *(&h)=42; int n; // es un tipo de dato entero

int *p; // p es un puntero a un entero /*Una vez declarado un puntero, se puede fijar la direccin o posicin de memoria del tipo al que apunta.*/ p = &n; //p se fija a la direccin de a Una vez que se ha declarado un puntero, p el objeto al que apunta se escribe *p y se puede tratar como cualquier otra variable de tipo <NombreTipo>. int *p, *q, o; // dos punteros a integer, y una variable integer *P = 101; // *p apunta 101 *q= n + *p; // *q apunta a n mas el contenido de lo que apunta p C++ trata los punteros a tipos diferentes como TDD diferentes, int *ip; double *dp; Los punteros ip y dp son incompatibles, de modo que es un error escribir: dp = ip; Se pueden, sin embargo, realizar asignaciones entre contenidos, ya que se realizara una conversin explcita de tipos: *dp =ip. Existe un puntero especial (nulo) que se suele utilizar con frecuencia en programas C++. El puntero NULL tiene un valor cero, que lo diferencia de todas las direcciones vlidas. El conocimiento nos permite comprobar si un puntero p es el puntero NULL evaluando la expresin (p==0). Los punteros NULL se utilizan slo como seales de que ha sucedido algo. En otras palabras, si p es un puntero NULL, es incorrecto referenciar *p.

(80)

SINTAXIS La declaracin de un puntero de manera general es: <tipo> *<nombre_de_apuntador>(<variable>);

<tipo>: Especifica el tipo de objeto apuntado y puede ser cualquier tipo. <nombre de apuntador>: Es el identificador del apuntador. El espacio de memoria requerido para un apuntador, es el nmero de bytes necesarios para especificar una direccin de memoria, debiendo apuntar siempre al tipo de dato correcto. Advertencia sobre C: En el lenguaje C como cualquier otro lenguaje que manipula objetos cada uno de ellos debe tener como mnimo un apuntador asignado, si un objeto queda sin un apuntador para l, queda aislado en algn lugar de la memoria ocupando un espacio, motivo por el cual algunos lenguajes emplean un Recolector de Basura de modo que cada cierto tiempo elimina los objeto que quedan aislados (sin apuntador) generalmente por descuido del programador, excepto C, donde se tiene libre acceso a todas las direcciones memoria. Por esto en Java se restringe el acceso a la memoria del computador por motivos de seguridad, pero se puede acceder a su valor y se verifica siempre el espacio de memoria asignado al programa que se construye a fin de que por algn descuido del programador, el programa no termine modificando espacios en memoria asignados a otros datos reservados relacionados con cdigos de otros programas. Por esta razn, Java es ms lento que C en la compilacin. Si un programa en lenguaje C sobrescribe su espacio de memoria asignado a l, podra causar daos en otros programas al alterar sus cdigos fuentes que estn almacenados, e incluso asta del S.O. Si un apuntador en C apunta a una direccin donde se encuentra un dato del sistema operativo y lo modifica esto pondra causar daos graves al S.O. aunque algunos se beneficien de ello. Considere el siguiente programa y observe a las variables de direccin e Indireccin trabajar:

(81)

La Aritmtica de Apuntadores. Generalidades: Las operaciones ms comunes son la asignacin y las relacionales. Por lo general slo interesa comparaciones de = y !=; raramente necesitaremos comparar una direccin con otra con los operadores > y <. Algunos lenguajes soportan aritmtica de punteros, en donde podemos incrementar o decrementar una direccin de memoria. En el caso de la asignacin, es importante que ambas asignaciones apunten a elementos del mismo tipo, pues de lo contrario se podran acceder e interpretar datos de manera errnea. Dos apuntadores son iguales si almacenan la misma direccin de memoria. En C solamente se pueden realizar operaciones de incremento y decremento, y estos es de acuerdo a la longitud de su tipo de base. Por ejemplo supngase que una mquina particular utiliza direccionamiento de byte, un entero requiere 4 bytes y el valor de la variable pi (declarada as: int *pi) es 100, es decir, se apunta al entero *pi en la localidad 100. Entonces el valor de pi-1 es 96, el de pi+1 es 104 y el de pi+2 es 108. El valor de *(pi-1) es el de los contenidos de los 4 bytes 96,97,98, y 99 , el de *(pi+1) es el del contenido de los byte 104, 105,106 y 107, y el de *(pi+2) es el entero que esta en los bytes 108,109,110 y 111. De manera parecida, si el valor de la variable pc (declarada as: char *pc; ) es igual a 100, y un carcter tiene un byte de longitud, pc-1 refiere a la localidad 99, pc+1 a la 101 y pc+2 a la 102. Dado que los punteros son nmeros (direcciones), pueden ser manipulados por los operadores aritmticos. Las operaciones que estn permitidas sobre punteros son: suma, resta y comparacin. As, si las sentencias siguientes se ejecutan en secuencia: char *p; // p, contiene la direccin de un carcter char a[l0]; // array de diez caracteres p = &a[0]; // p, apunta al primer elemento del array p++; // p, apunta al segundo elemento del array p++; // p, apunta al tercer elemento del array p--; // p, apunta al segundo elemento del array

(82)

Un elemento de comparacin de punteros, es el siguiente programa: #include <iostream.h> main (void) { int *ptr1, *ptr2; int a[2] = {l0,l0}; ptrl = a; cout << ptr1 es << ptr1 << *ptr1 es << *ptr1 << endl; cout << ptr2 es << ptr2 << *ptr2 es << *ptr2 << endl; //comparar dos punteros if (*ptrl == *ptr2) cout << ptr1 es igual a *ptr2 \n; else cout << *ptrl no es igual a *ptr2 \n; } Apuntadores a Funciones Un rea en la cual desempean un papel prominente los apuntadores es el lenguaje C es la transmisin de parmetros a funciones. Por lo comn, los parmetros se transmiten por valor a una funcin en C, es decir, se copian los valores transmitidos en los parmetros de la funcin llamada en el momento en que se invoca. Si cambia el valor de un parmetro dentro de la funcin, no cambia su valor en el programa que la llama. Por ejemplo considrese el siguiente fragmento y funcin de programa (el nmero de lnea es solo una gua en el ejemplo):

(83)

La lnea 2 imprime el nmero 5 y despus llama a funct. El valor de "x", que es 5, se copia en "y" y comienza la ejecucin de funct. Despus, la lnea 9 imprime el nmero 6 y regresa funct. Sin embargo, cuando la lnea 8 incrementa el valor de "y", el valor de "x" permanece invariable. As, la lnea 4 imprime el nmero 5, "x" y "y" refieren a 2 variables diferentes. Si deseamos usar funct para modificar el valor de "x", debemos de transmitir la direccin de "x" de la siguiente manera:

La lnea 2 imprime nuevamente el nmero 5, y la lnea 3 llama a funct. Ahora, sin embargo, el valor transferido no es el valor entero de "x" sino el valor apuntador "&x". Este es la direccin de "x". El parmetro de funct no es ms y de tipo int, sino py de tipo int * . (Es conveniente nombrar a las variables apuntadores comenzando con la letra p para recordar tanto que se trata de un apuntador) la lnea 8 ahora aumenta al entero en la localidad py; py, sin embargo, no cambia y conserva su valor inicial "&x". As, py apunta al entero "x" de tal manera que cuando *py, aumenta x. La lnea 9 imprime 6 y cuando regresa funct, la lnea 4 imprime tambin 6. Los apuntadores son el mecanismo usado en el lenguaje C para permitir a una funcin llamada modificar las variables de la funcin que llama. Arreglos en C Arreglos. Es una serie de datos del mismo tipo, tambin conocidos como vectores o rangos. Una arreglo esta constituido por varias posiciones de memoria de igual tamao consecutivas que tienen el mismo tipo de variable y se accesan usando el mismo nombre seguido de un subndice entre corchetes. La cantidad total de espacio que se usa por un arreglo depende de 2 cosas: El nmero de elementos en el arreglo y El tamao del arreglo.

(84)

Por qu Usar los Arreglos? Por que son uno de los factores esenciales de los programas de computadora. Permiten que se haga referencia a entradas individuales en una tabla de elementos de datos usando el mismo cdigo y variando el ndice del elemento. La Declaracin de un Arreglo: es igual a como se hara con una variable, a excepcin de que tambin se especifica la cantidad de elementos en el arreglo encerrado entre corchetes de la siguiente manera: <tipo> <nombre_del_arreglo>[<tamao_indice>]; Cuando se declara un arreglo, sus valores se pueden inicializar de la siguiente manera: int lista[9]= {0,4,78,5,32,9,77,1,23}; /*Tiene valores en [08]*/

No trate de engaar al Compilador inicializando mas valores en el arreglo de los que puede, ya que este no lo obedecer, sin embargo, si inicializa solo una parte del arreglo, las restantes posiciones se inicializan con ceros. Si desea imprimir un valor de un arreglo, la lnea luce as: printf ("%d", lista[1]); /*Imprime el nmero: 4*/

Una Caracterstica importante de los arreglos en C es que no se pueden modificar los limites superior e inferior (y por tanto el rango) durante el programa. El lmite inferior se fija siempre en 0 y el superior lo fija el programador, es decir:

Se han visto hasta ahora, arreglos llamados Unidimensionales, pero existen tambin los llamados Bidimensionales(o matrices), y se declaran as:
<tipo> <nombre_arreglo_bidimensional>[<tamao_fila>][<tamao_columna>];

Estos tambin son comnmente conocidos como Matrices, El tamao en la declaracin de la matriz estipula Rengln-Columna y se representaran as:

(85)

Estos tambin se pueden inicializar: int lista_nueva[2][2]={{14, 34},{23, 67}}; Y se acceden de la misma manera que un unidimensional. Ejemplo: printf ("%d", lista_nueva[1][0]); Y de esta forma se pueden construir arreglos Multidimensionales por ejemplo: int grande[3][4][7]; incluso int mas_grande [5][7][8][2][3][2]; pero se debe de tener cuidado al manejar estos arreglos por que son complejos de manipular a la larga. A pesar de ser Bidimensionales, en la memoria siguen siendo representados como espacios secuenciales lineales. Toda la memoria del computador, no es mas que una arreglo megagigante donde se guardan todos los datos, por muy complejo que parezca su almacenamiento. Breve resumen sobre los arreglos: La Definicin de arrays Los arrays se inicializan con este formato: int a[3] = {5, 10, 15}; char cad[5] = {a, b , c, d, e}; int tabla [2][3] = {{l,2,3} {3,4,5}}; Las tres siguientes definiciones son equivalentes: char saludo [5] = hola; char saludo [] = hola; char saludo [5] = {h, o, l, a} 1. Los arrays se pueden pasar como argumentos a funciones. 2. Las funciones no pueden devolver arrays. 3. No est permitida la asignacin entre arrays. Para asignar un array a otro, se debe escribir el cdigo para realizar las asignaciones elemento a elemento.

(86)

Arreglos y Apuntadores. A los arrays se accede a travs de los ndices: int lista [5]; lista [3] = 5; Las versiones con apuntadores en los arreglos son ms rpidas que la indexacin comn. La declaracin: int arr[10]; /*Se declara un arrays en C con diez elementos sin inicializar*/ int *pa,*ptr; /*se crean dos punteros a enteros*/

ptr = arr; /*fija puntero al primer elemento del array*/ ptr =+3; /* ptr = ptr + 3, suma 3 a ptr; ptr apunta al 4to elemento de arr*/ *ptr = 5; /*completa el 4to elemento de arr con valor 5.*/ /*El apuntador pa toma la direccin de memoria donde esta almacenado pa=&a[0]; /*y as establecemos que:*/ /*pa apunta al valor almacenado en a[0]*/ *pa=a[0]; /*y*/ /*pa+1 apunta al valor almacenado en a[1]*/ *(pa+1)=a[1]; /*y as sucesivamente*/ De esta manera se pude manejar mas eficientemente los valores y direcciones de un arreglo Bi o Unidimensional. El nombre de un array se puede utilizar tambin como si fuera un puntero al primer elemento del array. double a [10]; double *p = a; // p y a se refieren al mismo array. a[0]*/

(87)

M 0 1 2 3 4

O 5 6 7 8

Y 9

A este elemento se puede acceder por: a[0] accede a M , *p ;o bien p[0] a[5] accede a O, *(p + 5); o bien p[5] a[9] accede a Y, *(p + 9); o bien p[9] Si el nombre apunta al primer elemento del array, entonces nombre + 1 apunta al segundo elemento. El contenido de lo que se almacena en esa posicin se obtiene por la expresin:*(<nombre_del_apuntador> + 1). Aunque las funciones no pueden modificar sus argumentos, si un array se utiliza como un argumento de una funcin, la funcin puede modificar el contenido del array. Punteros a estructuras Los punteros a estructuras son similares y funcionan de igual forma que los punteros a cualquier otro tipo de dato. struct familia { char marido[100]; char esposa[100]; char hijo[100]; } familia Mackoy; //Mackoy estructura de tipo familia struct familia *p; //p, un puntero a familia p = &Mackoy; //p, contiene direccin de mackoy strcpy (p->marido,Luis Mackoy); //inicializacin strcpy (p ->esposa, Vilma Gonzalez); //inicializacin strcpy (p ->hijo, Luisito Mackoy); //inicializacin Punteros a objetos constantes Cuando se pasa un puntero a un objeto grande, pero se trata de que la funcin no modifique el objeto (por ejemplo, el caso de que slo se desea visualizar el contenido de un array), se declara el argumento correspondiente de la funcin como puntero a un objeto constante. La declaracin: const <NombreTDD> *v establece v como un puntero a un objeto que no puede ser modificado. Un ejemplo puede ser: void <nombre_funcin>(const <ObjetoGrande> *v);

(88)

Punteros a void El tipo de dato void representa un valor nulo. En C++, sin embargo, el tipo de puntero void se suele considerar como un puntero a cualquier tipo de dato. La idea fundamental que subyace en el puntero void en C++ es la de un tipo que se puede utilizar adecuadamente para acceder a cualquier tipo de objeto, ya que es ms o menos independiente del tipo. Un ejemplo ilustrativo de la diferencia de comportamiento en C y C++ es el siguiente segmento de programa: int main() { void *vptr; int *iptr; vptr = iptr; iptr = vptr; //Incorrecto en C++, correcto en C iptr = (int *) vprr; //Correcto en C++ }

Punteros y cadenas Las cadenas en C++ se implementan como arrays de caracteres, como constantes de cadena y como punteros a caracteres. Constantes de cadena Su declaracin es similar a: char *cadena = Mi profesor; o bien su sentencia equivalente: char varcadena[ ] = Mi profesor; Si desea evitar que la cadena se modifique, aada const a la declaracin: const char *varcadena = M profesor; Los puntos a cadena se declaran: char s[1]; o bien: char *s; Punteros a cadenas Los punteros a cadenas no son cadenas. Los punteros que localizan el primer elemento de una cadena almacenada. char *varCadena; const char *cadenafija;

(89)

Consideraciones prcticas Todos los arrays en C++ se implementan mediante punteros: char cadenal[l6] = Concepto Objeto; char *cadena2 = cadenal; Las declaraciones siguientes son equivalentes y se refieren al carcter C: cadenal[0] = a; char car = a; cadena1[0] = car; Los operadores NEW Y DELETE C++ define un mtodo para realizar asignacin dinmica de memoria, diferente del utilizado en mediante los operadores new y delete. El operador new sustituye a la funcin malloc tradicional en C, y el operador delete sustituye a la funcin free tradicional, tambin en C. new, asigna memoria, y devuelve un puntero al new Nombre Tipo y un ejemplo de su aplicacin es: int *ptrl; double *ptr2; ptrl = new int; // memoria asignada para el objeto ptrl ptr2 = new double; // memoria ampliada para el objeto ptr2 *ptrl = 5; *ptr2 = 6.55; Dado que new devuelve un puntero, se puede utilizar ese puntero para inicializar el puntero de una sola definicin, tal como: int *p = new int; Si new no puede ocupar la cantidad de memoria solicitada devuelve un valor NULL. El operador delete libera la memoria asignada mediante new. delete prt1; Un pequeo programa que muestra el uso combinado de new y delete es: include <iostream.h> void main (void) { char *c; c = new char[512]; cin >> c; cout << c <<endl; delete [] c; }

(90)

Los operadores new y delete se pueden utilizar para asignar memoria a arrays, clases y otro tipo de datos. int *i; i = new int[2][35]; //crear el array de 2 x 35 dimensiones //asignar el array delete i; //destruir el array Sintaxis de new y delete new <nombre-tipo> new int new char[l00]; new <nombre-tipo> <nicializador> new int (99) new char(C); new <nombre-tipo> new (char*); delete <expresin> delete p; delete[] <expresin> delete []p; ENUMERACIONES En C++, un nombre de una enumeracin, estructura o unin es un nombre de un tipo. Por consiguiente, la palabra reservada struct, union, o enum no son necesarias cuando se declara una variable. El tipo de dato enumerado designa un grupo de constantes enteros con nombres. La palabra reservada enum se utiliza para declarar un tipo de dato enumerado o enumeracin. La sintaxis es: enum <nombre>{<valor_1>,<valor_2>,<valor_3>,,<valor_n>}; Donde <nombre> es el nombre de la variable declarada enumerada, <valor> es una lista de tipos n-numerados, a los que se asigna valores cuando se declara la variable enumerada y puede tener un valor de inicializacin. Se puede utilizar el nombre de una enumeracin para declarar una variable de ese tipo (variable de enumeracin). Ej: <nombre> <ver>; Considrese la siguiente sentencia: enum color [Rojo, Azul, Verde, Amarillo]; Una variable de tipo enumeracin color es: color pantalla = Rojo; //Estilo de C++ ESTRUCTURAS Una estructura (o registro) es un tipo de dato compuesto que contiene una coleccin de elementos de tipos de datos diferentes combinados en una nica construccin del lenguaje. Cada elemento de la coleccin se llama miembro y puede ser una variable de un tipo de dato diferente. Una estructura representa un nuevo tipo de dato en C++.

(91)

La sintaxis de una estructura es: struct <nombre>{<miembro_1>;<miembro_2>;;<miembro_n>}; La sintaxis para la composicin de un miembro especifico, podra ser: <miembro_n> = <TDD> <campo_n> Un ejemplo y una variable tipo estructura se muestran en las siguientes sentencias: struct cuadro { int i; float f; }; struct cuadro nombre; /*Estilo C cuadro es una variable del TDD cuadro*/ cuadro nombre; //Estilo C++ UNIONES Una unin es una variable que puede almacenar objetos de tipos y tamaos diferentes. Una unin puede almacenar tipos de datos diferentes, slo puede almacenar uno cada vez, en oposicin a una estructura que almacena simultneamente una coleccin de tipos de datos. La sintaxis de una unin es: union <nombre>{<miembro_1>,<miembro_2>,,<miembro_n>}; Un ejemplo de una unin es: union alfa { int x; char o; }; Una declaracin de una variable estructura es: alfa w; El modo de acceder a los miembros de la estructura es mediante el operador punto . Ejemplo: u.x = 145; u.c = z;

(92)

C++ admite un tipo especial de unin llamada unin annima, que declara un conjunto de miembros que comparten la misma direccin de memoria. La unin annima no tiene asignado un nombre y, en consecuencia, se accede a los elementos de la unin directamente. La sintaxis de una unin annima es: union { } Las variables de la unin annima comparten la misma posicin de memoria y espacio de datos. int main() { union {

int nuevolD; int contador;

} x = 25; y = 245.245; //el valor en y sobrescribe el valor de x z = 9.41415; //el valor en z sobrescribe el valor de z

int x; float y; double z;

CADENAS EN C++ Una cadena es una serie de caracteres almacenados en bytes consecutivos de memoria. Una cadena se puede almacenar en un array de caracteres (char) que tenan en un carcter nulo (cero): char perro[5] = { `m`,`o`,`r`,`g`,`a`,`n`}; // no es una cadena char gato[5] = { f,e,l,i,n,o,\0,}; // es una cadena Lectura de una cadena del teclado #include <iostream.h> main () { char cad [80]; cout << introduzca una cadena:; // lectura del teclado cm cad; cin >> cad; cout << Su cadena es:; cout << cad; return 0; }

(93)

Esta lectura del teclado lee una cadena hasta que se encuentra el primer carcter blanco. As, cuando se lee Hola que tal la primera cadena, en cad slo se almacena Hola. Para resolver el problema, utilizar la funcin gets () que lee una cadena completa leda del teclado. El programa anterior quedara as: #include <iostream.h> #include <stdio.h> main() { char cad[80]; cout Introduzca una cadena:; gets (cad); cout Su cadena es:; cout << cad; return 0; }

Definicin de funciones La definicin de una funcin es el cuerpo de la funcin que se ha declarado con anterioridad. double Media (double x, double y) // Devuelve la media de x e y { return (x + y)/2.0 } char LeerCaracter() //Devuelve un carcter de la entrada estndar { char c; cin >> c; return c; } Argumentos por omisin Los parmetros formales de una funcin pueden tomar valores por omisin, o argumentos cuyos valores se inicializan en la lista de argumentos formales de la funcin. int Potencia (int n, int k = 2); Potencia(256); //256 elevado al cuadrado Los parmetros por omisin no necesitan especificarse cuando se llama a la funcin. Los parmetros con valores por omisin deben estar al final de la lista de parmetros: void void void void fund (int i =3, int j); // no correcto func2 (int i, int j=0, int k = 0); // correcto func3 (int i = 2, int j, int k = 0); // no correcto ImprimirValores (int cuenta,double cantidad= 0.0);

(94)

Llamadas a la funcin ImprimirValores: ImprimirValores (n,a); ImprimirValores (n); //equivalente a ImprimirValores (n, 0.0) Otras declaraciones y llamadas a funciones son: double double double double double fl(int f2(int f3(int f4(int f5(int n, int n, int n = 2, n, int n = 2, m, int p=0); m= 1, int p = 0); int m= 1, int p =0); m = 1, int p); int m, int p = 0); // correcto // correcto // correcto // no correcto // no correcto

Funciones en lnea (inline) Si una declaracin de funcin est precedida por la palabra reservada inline, el compilador sustituye cada llamada a la funcin con el cdigo que implementa la funcin. Ejemplo: inline int max(int a, int b) { if (a > b) return a; return b; } main () { int x = 5, y = 4; int z = Max(x,y); } Los parmetros con valores por omisin deben entrar al final de la lista de parmetros: Las funciones f1, f2 y f3 son vlidas, mientras que las funciones f4 y f5 no son vlidas. Las funciones en lnea (inline) evitan los tiempos suplementarios de las llamadas mltiples a funciones. Las funciones declaradas en lnea deben ser simples con slo unas pocas sentencias de programa; slo se pueden llamar un nmero limitado de veces y no son recursivas. Ejemplo: inline int abs(int i); inline int min(int v1, int v2); int mcd(int vl, int v2); Las funciones en lnea deben ser definidas antes de ser llamadas.

(95)

#include <iostream.h> int incrementar (int I); inline incrementar (int i) { i ++; return i; } main (void) { int i = 0; while (i < 5) { i = incrementar (i); cout i es: i endl; } } Sobrecarga de funciones En C++, dos o ms funciones distintas pueden tener el mismo nombre. Esta propiedad se denomina sobrecarga. Un ejemplo es el siguiente: int max (int, int); double max (double, double); o bien este otro: void sumar (char i); void sumar (float j); Las funciones sobrecargadas se diferencian en el nmero y tipo de argumentos, o en el tipo que devuelven las funciones, y sus cuerpos son diferentes en cada una de ellas.

(96)

Ejemplo: #include <iostream.h> void suma (char); void suma (float); main (void) { int i = 65; float j = 6.5; char c = a; suma ( i ); suma ( j ) ; suma ( c ) ; } void suma (char i) { cout << Suma interior(char) <<endl; } void suma ( float j ) { cout << Suma interior (float) << endl; } El modificador <const> Constantes: En C++, los identificadores de variables/constantes se pueden declarar constantes, significando que su valor no se puede modificar. Esta declaracin se realiza con la palabra reservada const. const const const const double PI= 3.11416; char BLANCO = ; double PI_EG = -I; double DOBLE_I = 2 * PI ;

El modificador de tipos const se utiliza en C++ para proporcionar proteccin de slo lectura para variables y parmetros de funciones. Cuando se hace preceder un tipo de argumento con el modificador const para indicar que este argumento no se puede cambiar, el argumento al que se aplica no se puede asignar un valor ni cambiar. void copia (const char *fuente, char *destino); void funciondemo (const int I);

(97)

Paso de parmetros a funciones En C++ existen tres formas de pasar parmetros a funciones: 1. Por valor La funcin llamada recibe una copia del parmetro y este parmetro no se puede modificar dentro de la funcin void intercambio (int x, int y) { int aux = y; y = x; x = aux; } //..... intercambio (i , j ); // las variables i, j, no se intercambian 2. Por direccin. Se pasa un puntero al parmetro. Este mtodo permite simular en C/C++ la llamada por referencia, utilizando tipos punteros en los parmetros formales en la declaracin de prototipos. Este mtodo permite modificar los argumentos de una funcin. void intercambio (int *x,int *y) { int aux = *y; *y = *x *x = aux; } // ... intercambio (&i, &j); // i , j se intercambian sus valores 3. Por referencia. Se pueden pasar tipos referencia como argumentos de funciones, lo que permite modificar los argumentos de una funcin. void intercambio(int &x, int &y) { int aux = y; y = x; x = aux; } //..... intercambio (i,j); // i , j intercambian sus valores Si se necesita modificar un argumento de una funcin en su interior, el argumento debe ser un tipo de referencia en la declaracin de la funcin. Paso de arrays Los arrays se pasan por referencia. La direccin del primer elemento del array se pasa a la funcin; los elementos individuales se pasan por valor. Los arrays se pueden pasar indirectamente por su valor si el array se define como un miembro de una estructura. (98)

Ejemplo 1: Paso del array completo. #include <iostream.h> void func1 (int x[]); //prototipo de funcin void main( ) { int a[3] = {l,2,3}; func1 (a) ; // sentencias func1 (&a[0]) ; // equivalentes } void func(int x[]) { int i; for (i = 0; 1 < 3; i + 1) cout << 1 << x[i]<< \n; } Ejemplo 2: Pasa de a un elemento de un array. #include <iostream.h> const int n + 3; void func2(int x); void main( ) { int a[n] = {l,2,3}; func2 (a[2]); } void func2(int x) { cout << x << \n; }

(99)

Tamao de un TDD (El operador: sizeof) El operador (funsin) sizeof proporciona el tamao en bytes de un tipo de dato o variable sizeof toma el argumento correspondiente (tipo escalar, array, record, etc.). La sintaxis del operador es: sizeof (<nombre variable>); /*si se quiere saber el tamao en byte de una variable*/ sizeof (<tipo de dato>); /*si se quiere saber el tamao de un tipo de dato elemental*/

Ejemplos: int m , n[12]; sizeof(m); // sizeof(n); // sizeof (15); // sizeof (int); // bits). */ retorna retorna retorna retorna 4, en maquinas de 32 bits 48, 4 byte x 12 posiciones 4 un entero 15 el tamao en memoria de un int (generalmente 32

La sentencia nula: La sentencia nula se representa por un punto y coma, y no hace ninguna accin: char cad[80]=Cazorla; int i; for (i = 0; cad[i] != \0; i++);

(100)

Prioridad y asociatividad de operadores en C (versin completa)


Cuando se realizan expresiones en las que se mezclan operadores diferentes es preciso establecer una precedencia (prioridad) de los operadores y la direccin (o secuencia) de evaluacin (orden de evaluacin: izquierda-derecha, derecha-izquierda), denominada asociatividad. La Tabla B.11 muestra la precedencia y asociatividad de operadores.

Ejemplo: a * b/c+d equivale a: (a * b ) / ( c + d ) Sobrecarga de operadores


La mayora de los operadores de C++ pueden ser sobrecargados o redefinidos para trabajar con nuevos tipos de datos.

Precedencia y asociatividad de operadores :: ( ) [ ] . -> ++ -& (direccin) ~ (tipo) - + sizeof (tipo) new delete * (indireccion) .* ->* */% + << >> < <= > >= = = = & ^ | && || = += - = *= /= %= >>= <<= &= |= ^= , (operador coma) Izquierda-Derecha Derecha-Izquierda Izquierda-Derecha Izquierda-Derecha Izquierda-Derecha Izquierda-Derecha Izquierda-Derecha Izquierda-Derecha Izquierda-Derecha Izquierda-Derecha Izquierda-Derecha Izquierda-Derecha Izquierda-Derecha Derecha-Izquierda Izquierda-Derecha

Operadores que se pueden sobrecargar + - * / % ^ & | ~ ! = < > >> << >>= <<= != == ( ) -> , []

(101)

ENTRADAS Y SALIDAS BSICAS Al contrario que muchos lenguajes, C++ no tiene facilidades incorporadas para manejar entrada o salida. En su lugar, se manejan por rutinas de bibliotecas. Las clases que C++ utiliza para entrada y salida se conocen como flujos. Un flujo (stream) es una secuencia de caracteres junto con una coleccin de rutinas para insertar caracteres en flujos (a pantalla) y extraer caracteres de un flujo (de teclado). Salida
El flujo cout es el flujo de salida estndar que corresponde a stdout en C. Este flujo se deriva de la clase ostream construida en iostream.

CPU

cout

pantalla

Entrada binaria

Salida de caracteres

Uso de flujos para salida de caracteres. Si se desea visualizar el valor del objeto int llamado i, se escribe la sentencia: cout << i; El siguiente programa visualiza en pantalla una frase: #include <iostream.h> int main() { cout << Hola Mundo\n; } Las salidas en C++ se pueden conectar en cascada, con una facilidad de escritura mayor que en C. #include <isostrean.h>. int main() { int i; i = 1099; cout << El valor de i es << i << \n; } Otro programa que muestra la conexin en cascada es: #include <iostream.h> int main(){ int x = 45; double y = 496.125; char *c = "y es multiplicada por x="; cout << c << y * x << "\n; } (102)

Entrada La entrada se maneja por la clase istream. Existe un objeto predefinido istream, llamado cin, que se refiere al dispositivo de entrada estndar (el teclado). El operador que se utiliza para obtener un valor del teclado es el operador de extraccin >>. Por ejemplo, si i era un objeto int, se escribir: cin >> i; que obtiene un nmero del teclado y lo almacena en la variable i. Un programa simple que lee un dato entero y lo visualiza en pantalla es: #include <iostream.h> int main() { int i; cin >> i; cout << i; } Al igual que en el caso de cout, se pueden introducir datos en cascada: #include <iostream.h> int main() { char c[60]; int x,y; cin >> c >> x >> y; cout << c << << x << << y << \n; } Manipuladores Un mtodo fcil de cambiar la anchura del flujo y otras variables de formato es utilizar un operador especial denominado manipulador. Un manipulador acepta una referencia de flujo como un argumento y devuelve una referencia al mismo flujo. El siguiente programa muestra el uso de manipuladores especficamente para conversiones de nmero (dec, oct, y hex): #include <iostream.h> int main () { int i = 36; cout << dec << i << oct << i << << hex << i << \n; }

La salida de este programa es: 36 44 24

(103)

Otro manipulador tpico es endl, que representa al carcter de nueva lnea (salto de lnea), es equivalente a \n . El programa anterior se puede escribir tambin as: #include <iostream.h> int main () { int i = 36; cout << dec << i << oct << i << hex << i << endl; }

(104)

Palabras reservadas de C++ Las palabras reservadas o claves no se deben utilizar como identificadores, debido a su significado estricto en C++; tampoco se deben redefinir. La Tabla enumera las palabras reservadas de C++ segn el ARM(Siglas del libro de BJARNE STROUSTRUP en el que se definen las reglas de sintaxis del lenguaje C++ estndar). Palabras reservadas de C++
asm* auto break case catch* char class* const continue default delete* do double else enurn extern float for friend* goto if inline* int long new* operator* private* protected* public* register return short signed sizeof static struct switch template* this* throw* try typedef union unsigned virtual* void volatile while

*Estas palabras no existen en ANSI C.

Los diferentes compiladores comerciales de C++ pueden incluir, adems, nuevas palabras reservadas. Estos son los casos de Borland, Microsoft y Sysmantec. Tabla. Palabras reservadas de Turbo/Borland C++
asm auto break case catch _cdecl _cdecl char class const continue _cs default delete do _double _ds else enum _es export extern far far float for friend goto huge if inline int interrup _loadds long _near near new operator pascal pascal private protected public register return _saveregs _seg short signed sizeof _ss static struct switch template this typedef union unsigned virtual void volatile while signed sizeof static _stcall struct switch thread _try typedef union unsigned void volatile while

Tabla. Palabras reservadas de Microsoft Visual C/C++ 1.5/2.0


asm else int auto enum _interrupt based _except _leave break _export _loadds case extern long _cdecl _far maked char _fastcall _near const _finally _pascal continue float register _declspec for return default _fortran _saveregs dllexport goto _self dllimport _huge _segment do if _segname double _inline short El comit ANSI ha aadido nuevas palabras reservadas (Tabla B.4).

Tabla. Nuevas palabras reservadas de ANSI C++


bool cons_cast dynamic_cast false mutable namespace reinterpretcast static_cast true typeid using wchart

(105)

Objetivos:

Laboratorio #1 de C

> Entender la sintaxis de C (tipos de datos bsicos, condicionales, iteradores, funciones y mtodos, palabras claves, instrucciones de preprocesador) y hacer uso de ella para desarrollar programas. > Compilar un programa en C/C++ por medio del compilador de GNU gcc/g++ (Linux). > Usar la librera stdio.h para procesar flujos de entrada y salida. > Usar tipos de datos estructurados como arreglos, matrices, cadenas, y tipos de datos definidos por el usuario. > Aprender a usar Punteros. 1) Sintaxis de C La sintaxis de C ha sido muy popular incluso en los tiempos modernos, existen lenguajes que han heredado esta sintaxis (como Java), ya que es fcil de usar y permite desarrollar aplicaciones grandes. A) Tipos de datos bsicos: C posee los mismos tipos de datos primitivos que Java, estos son int, float, char, bool*, double. Los int pueden recibir valores constantes como nmeros: int x = 123; Tambin puede recibir valores octales o hexadecimales Octal: int x = 0235; // asigna el valor 157 en octal (se antecede con un 0). Hexadecimal: int x = 0xAA; /* asigna el valor 170 en hex (se antecede con un 0x)*/ Los float pueden recibir valores constantes como: float x = 0.587; /* para asignar valores de punto flotante se debe usar . (punto)*/ Tambin se puede lograr con notacin exponencial float x = 2E4; // esto equivale a 2 x 10^4 Los char reciben constantes entre comillas simples: char x = 'a'; Tambin pudieran recibir nmeros enteros, ya que los char son enteros de 1 byte. El valor que va a tener este char va a ser el caracter cuyo cdigo ASCII corresponda con el nmero dado. Ejemplo: char x = 48; // x va a tener el valor '0'. * Igual al boolean de java, solo es usado en C++. C usa enteros como booleanos, si se evala una condicin que da como resultado 0 se tomara como un false, en cualquier otro caso es true. (106)

B) Condicionales e iteradores: Los condicionales e iteradores son exactamente iguales a los de Java, tenemos: if if - else switch(expresin) case value: while do while(condicin) for C) Palabras claves: Java. Las palabras claves, son exactamente las mismas que se pueden usar en

break: Usada para salir de un bloque iterativo (for, while, etc). continue: Usada para ignorar todas las instrucciones en el bloque que se encuentran despus de esta instruccin. D) Instrucciones de Preprocesador: Las instrucciones de preprocesador son aquellas usadas para indicar instrucciones al compilador. Algunas de estas instrucciones son: #include: Se encarga de incluir una librera en el cdigo actual Ejemplo: #include stdio.h; #define NOMBRE VALOR: Se encarga de definir una constante cuyo nombre es el indicado en NOMBRE con el valor indicado en VALOR Ejemplo: #define PI 3.14; #ifdef - #else - #endif: Se encarga de verificar si la constante se encuentra definida, funciona como un if, en el caso de que la constante exista se compilan las instrucciones que estn entre esta etiqueta y la etiqueta #endif. Ejemplo: #ifdef PI int cualquiera; #else int cualquiera2; #endif Tambin existe una variante de #ifdef llamada #ifndef, que funciona de manera inversa a la antes mencionada.

(107)

E) Funciones y Mtodos En C las funciones son exactamente iguales a las de Java. Para definir un mtodo: void accin(int <parametro1>) { /*hace algo*/ } Para definir una funcin: int sumar(int uno, int dos) { return uno + dos; } Ejercicio: ***Desarrollar una funcin factorial (recursiva) en C.***

2) Compilar un programa con gcc/g++ Para compilar un cdigo fuente de C, usamos por medio de la consola los comandos gcc g++. La instruccin bsica para compilar es: gcc -o Factorial Factorial.c En el caso de que queramos compilarlo con g++, cambiamos el gcc por un g++ y funcionar de la misma manera. -lbiblioteca Liga con las bibliotecas objeto. Esta opcin deber seguir los argumentos de los archivos fuente. Las bibliotecas objeto son guardadas y pueden estar estandarizadas, un tercero o usuario las crea. Probablemente la biblioteca ms comnmente usada es la biblioteca matemtica (math.h). Esta biblioteca deber ligarse explcitamente si se desea usar las funciones matemticas (y por supuesto no olvidar el archivo cabecera #include <math.h>, en el programa que llama a las funciones) por ejemplo: gcc Factorial.c -o Factorial -lm Muchas otras bibliotecas son ligadas de esta forma. -Ldirectorio Agrega directorios a la lista de directorios que contienen las rutinas de la biblioteca de objetos. El ligador siempre busca las bibliotecas estndares y del sistema en /lib y /usr/lib. Si se quieren ligar bibliotecas personales o instaladas por usted, se tendr que especificar donde estn guardados los archivos. Por ejemplo: gcc Factorial.c -L/home/minombr/mislibs milib.h -Itrayectoria Agrega una trayectoria o ruta a la lista de directorios en los cuales se buscarn los archivos cabecera #include con nombres relativos (es decir, los que no empiezan con diagonal /). El procesador por default, primero busca los archivos #include en el directorio que contiene el archivo fuente, y despus en los directorios nombrados con la opcin -I si hubiera, y finalmente, en /usr/include. (108)

-g3 Compila el cdigo, de tal manera que el ejecutable va a tener la suficiente informacin como para poder ser depurado. Por ejemplo: gcc Factorial.c -o Factorial -g3 3. Uso de la librera stdio.h salida. Una de las facultades de C, es la facilidad para manejar los flujos de entrada y

C posee dos funciones bsicas pero poderosas para imprimir en un flujo de salida y para leer de un flujo de entrada. Para imprimir: fprintf()

Parmetros: Flujo al cual va a imprimir (puede ser la salida estndar (consola) o a un archivo). Recibe una cadena la cual puede tener expresiones que pueden ser sustituidas. Puede recibir las diferentes variables para cumplir el formato dado en la cadena inicial. Ejemplo: fprintf (STDOUT, Vamos a imprimir un entero: %d\n,15); Para leer: fscanf()

Parmetros: Flujo del cual se va a leer (puede ser la entrada estndar (consola) o a un archivo). Recibe una cadena la cual puede tener expresiones que se van a leer. Puede recibir las diferentes variables para cumplir el formato dado en la cadena inicial. Ejemplo: int variable = 0; fscanf(STDIN,%d,&variable);

Los Parmetros que se pueden pasar en la cadena de formato pueden ser: %d para entero %f para flotantes %c para caracteres %s para cadenas %lf para doubles %llf para long long (109)

Ambas funciones devuelven un entero, el cual indica en el caso de fprintf el nmero de caracteres impresos, y en el caso de fscanf el nmero de parmetros que fueron ledos. 4. Tipos de datos estructurados Como cualquier otro lenguaje, C ofrece distintos tipos de datos estructurados como lo son arreglos, y tipos de datos definidos por el usuario. A) Arreglos: Los Arreglos se definen de la siguiente manera: int arreglo[<tamao>]; Los arreglos pueden ser definidos con cualquier tipo de dato. Incluso los definidos por el usuario. NOTA: vale la pena acotar que cuando se crean los arreglos, los valores contenidos en el mismo no se encuentran inicializados, normalmente ningn tipo de dato en C va a tener un valor de inicializado por defecto. Las Matrices se definen de la siguiente manera: float matrix[<N_FILAS>][<N_COL>]; Para definir cadenas, usamos arreglos de caracteres, a diferencia de Java, C no posee ningn objeto string. Solo arreglos de caracteres. char cadena[<TAMAO>]; Para definir nuestros propios tipos de datos, usamos la sentencia struct. struct Persona { int cedula; char nombre[20]; }; Esta sentencia solo va a crear una persona, para que se pueda usar como tipo de dato tenemos que usar la sentencia typedef antes del struct. typedef struct { int cedula; char nombre[20]; } Persona; Persona pepe;

(110)

5. Definir Apuntadores En C a diferencia de Java nosotros podemos usar directamente los apuntadores que hacen referencias a los tipos de datos. Se pueden crear apuntador para cada tipo de dato, incluso los definidos por el programador. Para definir un apuntador de Persona, se puede hacer de la siguiente manera: Persona persona1; Persona ptr*; ptr = &persona1; Para acceder a las propiedades de persona por medio del apuntador puede usarse el operador de dereferenciacin (->) int cedula = ptr->cedula;

(111)

Laboratorio #2 de C Archivos en C, Listas simples y C++ bsico 1. Manejo de archivos en C / C++. C ve cada archivo simplemente como un flujo secuencial de bytes. Cada archivo termina con una marca de fin de archivo o con un nmero de bytes especifico almacenado dentro de una estructura de datos administrada y mantenida por el sistema. Al abrir un archivo se devuelve un apuntador a la estructura FILE la cual contiene la informacin necesaria para procesar el archivo. 1.1 Creacin de un archivo de acceso secuencial. Para referenciar un archivo se crea un apuntador a la estructura FILE la cual posteriormente se asocia a un archivo. FILE *puntero; archivo*/ /* Se crear una variable puntero la cual es un apuntador a un

1.2 Apertura de un archivo. Una vez declarado un puntero a archivo utilizaremos la funcin fopen(). Para abrir el archivo y asociarlo al puntero. Su sintaxis es: puntero = fopen ( nombre del archivo, "modo de apertura" ); Donde puntero es la variable de tipo FILE, nombre del archivo es el nombre que daremos al archivo que queremos crear o abrir. Este nombre debe ir encerrado entre comillas. Tambin podemos especificar la ruta donde se encuentra o utilizar un arreglo que contenga el nombre del archivo (en este caso no se pondrn las comillas). Algunos ejemplos: puntero = fopen("DATOS.DAT","r"); puntero = fopen("C:\\TXT\\SALUDO.TXT","w"); Un archivo puede ser abierto en dos modos diferentes, en modo texto o en modo binario. A continuacin lo veremos con ms detalle.

Modo texto
w crea un archivo de escritura. Si ya existe lo crea de nuevo. w+ crea un archivo de lectura y escritura. Si ya existe lo crea de nuevo. a abre o crea un archivo para aadir datos al final del mismo. a+ abre o crea un archivo para leer y aadir datos al final del mismo. r abre un archivo de lectura. r+ abre un archivo de lectura y escritura. (112)

Modo binario
wb crea un archivo de escritura. Si ya existe lo crea de nuevo. w+b crea un archivo de lectura y escritura. Si ya existe lo crea de nuevo. ab abre o crea un archivo para aadir datos al final del mismo. a+b abre o crea un archivo para leer y aadir datos al final del mismo. rb abre un archivo de lectura. r+b abre un archivo de lectura y escritura. La funcin fopen devuelve, como ya hemos visto, un puntero de tipo FILE. Si al intentar abrir el archivo se produjese un error (por ejemplo si no existe y lo estamos abriendo en modo lectura), la funcin fopen devolvera NULL. Por esta razn es mejor controlar las posibles causas de error a la hora de programar. Un ejemplo: FILE *pf; pf=fopen("datos.txt","r"); if (pf == NULL) printf("Error al abrir el archivo"); 1.3 Cierre de un archivo Una vez que hemos acabado nuestro trabajo con un archivo es recomendable cerrarlo. Los archivos se cierran al finalizar el programa pero el nmero de estos que pueden estar abiertos es limitado. Para cerrar los archivos utilizaremos la funcin fclose( );. Esta funcin cierra el archivo, cuyo puntero le indicamos como parmetro. Si el archivo se cierra con xito devuelve 0. fclose(puntero); Un ejemplo ilustrativo es: FILE *pf; pf = fopen("AGENDA.DAT","rb"); if ( pf == NULL ) printf ("Error al abrir el archivo"); else fclose(pf); 1.4 Lectura desde un archivo

Existen muchas maneras de lectura desde un archivo aqu se mencionaran las mas bsicas y de fcil uso la primera de estas es fgetc (). Para leer un carcter int fgetc (FILE *stream); char c; c = fgetc (<puntero>); /* Obtiene el prximo carcter de un stream.*/ (113)

Esta Funcin retorna el prximo carcter de un stream el cual esta siendo referenciado por puntero el cual es un apuntador a un archivo abierto. Ejemplo contador del nmero de lneas de un archivo c = fgetc (pFile); if (c == '\n') i++; } while (c != EOF); Leer una Estructura: int fread (void *buffer, size_t size, size_t count, FILE *stream); Lee un Bloque de datos desde un stream. Lee un numero count de intems cada uno de un tamao size en bytes desde un stream y los almacena en un buffer. El puntero al stream se incrementa segn el numero de bytes ledos, el total debe ser (size x count); Parmetros buffer Apuntador a la estructura de destino con un tamao mnimo de (size *count) byte. size Tamao en bytes para cada intems a ser ledo. count Numero de intems a ser ledos, cada uno con tamao size en bytes. stream Apuntador a un archivo abierto. Valor devuelto. error. El nmero total de intems ledos, si el nmero es diferente a count ocurre un do {

1.5 Escritura en un archivo. Escribir un carcter int fputc (int character, FILE *stream); Escribe un carcter en un stream, lo escribe en la posicin actual del stream y el apuntador se mueve al siguiente carcter.

(114)

Parmetros

carcter
Carcter a ser escrito, si es un entero se escribe como entero sin signo.

stream
Apuntador a un archivo abierto. Escribir estructuras size_t fwrite(const void *buffer,size_t size,size_t count,FILE *stream ); Escribir un bloque de datos en un stream. Escribe un numero count de intems, cada uno de tamao size en bytes, desde la memoria apuntada por buffer, en la posicin actual del stream. Parmetros.

buffer Apuntador a la data a ser escrito. size Tamao de cada uno de los intems a ser escritos. count Nmero de intems a ser escritos, cada uno de tamao size en bytes. stream Apuntador a archivo abierto con permiso de escritura.
NOTA: Tambin se pueden usar las funciones fscanf y fprintf dadas en el laboratorio anterior. 2. Sintaxis C++ La sintaxis de C++ hereda todas las de C, pero tambin incluye soporte de clases, tipos de datos (bool), etc. A continuacin veremos como declarar Clases en C++

(115)

2.1 Clases Las Clases en C++ se declaran de la siguiente forma: class <NombreDeLaClase> [: public <ClasePadre>] { private: // <-- modificador de acceso tipo_dato <atributo1>; tipo_dato <atributo2>; public: int <metodo1>(int <param>); // mtodo no inline void <metodo2>() { // mtodo inline //algun cuerpo ... }static void <metodo3>() { // mtodo esttico // algo... } };

Como pudimos ver en el ejemplo, la declaracin de los atributos de la clase va a ser como el de cualquier estructura en C. Para los mtodos existen 3 tipos de declaraciones: los inline, los normales y los estticos. Inline: son aquellos mtodos que funcionan como macros, es decir, la llamada a el mtodo va a ser sustituida por el cdigo que se encuentra dentro de ese mtodo (esta sustitucin va a estar dada en el cdigo ejecutable). Static: los mtodos estticos (o de clase) son aquellos que sern invocados sin tener que crear un objeto (instancia de la clase). Estas normalmente no alteraran el estado de la clase. Estas pueden ser invocadas usando: Clase.metodo(); . Normales: los mtodos normales son aquellos que son declarados en la clase, pero son definidos fuera de ella. Estos se comportaran de la manera que se espera, cuando se invoca a un mtodo normal, se crea un nuevo ambiente de ejecucin para este mtodo, una vez que finalice es eliminado. Para poder definir un mtodo normal fuera de la clase se debe usar el operador de referenciacin ::. Por ejemplo asumiendo que se declaro la clase NombreDeLaClase, para definir el metodo1, se hace de la siguiente manera:

int <NombreDeLaClase>::<metodo1>(int <param>) { // hacer algo return 0; }

(116)

Modificadores de Acceso (MDA) Los modificadores de acceso permiten aplicar el concepto de ocultamiento de informacin del paradigma de la programacin orientada a objetos. Estos aparecen en orden decreciente de visibilidad. Este puede ser asociado con un atributo o funcin anteponiendo las palabras reservadas public, protected, private, seguidos del smbolo :. Por defecto las clases tienen un modificador de acceso private, por eso cuando se desee declarar mtodos pblicos en la clase, estos deben ser precedidos por la sentencia public:. Herencia Por poder hacer uso de la herencia en C++, cuando se declara la clase se debe especificar cual es su clase padre con: : (public|protected|private) ClasePadre En la herencia tambin se pueden aplicar los modificadores de acceso, pero sigue un lineamiento un poco distinto. Si el modificador es public, todos los mtodos del padre que sean public o protected se mantendrn con ese mismo modificador de acceso en la clase hija. Si el modificador es protected, todos los mtodos del padre que sean public o protected, sern declarados como protected en la clase hija. Si el modificador es private, todos los mtodos del padre que sean public o protected, sern declarados como private en la clase hija. 3. Listas simples. Una lista es una coleccin finita de elementos del mismo tipo, ordenados de acuerdo a su posicin en la lista, para el estudios de listas en C++ se implementara de manera dinmica (crece segn sea necesario). El TDA (Tipo de Dato Abstracto) listas implementa varias operaciones las cuales en la practica podemos modificar a conveniencia. Entre los mtodos se pueden tener: agregar(nuevoElemento) obtener(indice) eliminar(indice) tamao() entre otros... Las Listas pueden ser definidas como un TDA o como una Clase, la diferencia principal es que, si se define como clase, todos los mtodos van a estar contenidos en la clase o estos van a modificar el estado interno del objeto de la clase. Ejemplo de implementacin con clases: Lista *l = new Lista(); l->agregar(nuevoElemento);

(117)

Los mtodos invocados pertenecen al objeto y modifican el estado del objeto. Ejemplo de implementacin con TDA: Lista l; agregar(l,nuevoElemento); En cada invocacin de mtodo debe ser agregada la lista para que sta pueda ser modificada. Cualquiera de los dos enfoques es vlido. 3.1 Asignacin dinmica de memoria. NOTA: El Operador sizeof (variable), es una funcin que proporciona el lenguaje C para determinar el tamao en bytes de una variable. Estas funciones permiten obtener espacios de memoria en tiempo de ejecucin para almacenar nuevos nodos y liberar la misma cuando no sea necesario. void *malloc ( size_t siz e ); La funcin malloc tiene como parmetro el nmero de bytes necesarios para la asignacin de memoria dinmica, retorna un apuntador a un bloque de memoria con el tamao solicitado. Como el tipo de dato devuelto es void * , se le puede asignar a cualquier apuntador, comnmente la funcin malloc se utiliza junto a la funcin sizeof la cual retorna el numero de bytes necesarios para una variable. Nombretipo *ptrNuevo; ptrNuevo = malloc (sizeof(nombretipo)); void free (void *memblock) La Funcin free libera un bloque de memoria previamente reservado. Free (ptrNuevo); 3.1 Asignacin de memoria dinmica con POO Para la programacin orientada a objetos se utiliza el operador new(), este operador crea un objeto del tamao indicado, llamada constructor para el objeto y retorna un apuntador del tipo correcto. prtNuevo = new nombretipo; Para la liberacin de memoria de manera dinmica se utiliza el operador delete(). delete PrtNuevo

(118)

Actividad nro 1. Utilice clases para la Implementacin: Dado el archivo info.txt el cual contiene la informacin de productos se desea que usted plantea una estructura de datos para almacenar la informacin de dicho producto y luego implemente la clase lista con las operaciones InsertarOrdenado() y EliminarOrdenado() , para dicha estructura. Una vez creada estas funciones desde la accin principal se va a ir leyendo la informacin desde el archivo para cada producto y se va a insertar en una lista de productos la cual debe estar ordenada por cdigo de producto. Una vez generada la lista se debe dar las opciones de: Eliminar un producto, Mostrar estado de la lista, Salir de la aplicacin, la aplicacin debe funcionar hasta que se elija salir, para eliminar un producto se debe solicitar el cdigo del mismo y la lista debe quedar ordenada. Formato del archivo info.txt Cada lnea contiene la informacin de un producto, primero el cdigo el cual es un entero de 3, luego la descripcin, la cual es una cadena de caracteres de mximo 20 letras, y el precio entero, entre cada valor hay un espacio en blanco. <cdigo> <espacio> <descripcin> <espacio> <precio> 10 cdrom 85000 15 floppy 30000 2 monitor 350000

(119)

Sentencias de salto: Sentencias break, continue, goto La instruccin break interrumpe la ejecucin del bucle donde se ha incluido, haciendo al programa salir de l aunque la expresin_de_control correspondiente a ese bucle sea verdadera La sentencia continue hace que el programa comience el siguiente ciclo del bucle donde se halla, aunque no haya llegado al final de las sentencia compuesta o bloque. La sentencia goto <etiqueta>(es el salto incondicional en ensamblador), hace saltar al programa a la sentencia donde se haya escrito la etiqueta correspondiente. Por ejemplo: Sintaxis: sentencias if(condicin) goto salto; sentencia_1; sentencia_2;

} salto: sentencia_3; sentencia_4;

La palabra bucle es sinnimo de ciclo. Para ms informacin sobre break y continue consulte la pgina 140 de ciclos infinitos de C++. Obsrvese que la etiqueta termina con el carcter (:). La sentencia goto no es una sentencia muy prestigiada en el mundo de los programadores de C++, pues disminuye la claridad y legibilidad del cdigo. Fue introducida en el lenguaje por motivos de compactibilidad con antiguos hbitos de programacin, y siempre puede ser sustituida por otras expresiones ms claras y estructuradas.

(120)

SOBRE ALGUNOS OPERADORES: Operador coma(,) Los operandos de este operador son expresiones, y tiene la forma general: expresin = expresin_1, expresin_2; Es este caso, expresin_1 se evala primero, y luego se evala expresin_2. El resultado global es el valor de la segunda expresin, es decir de expresin_2.Este es el operador de menos precedencia de todos los operadores de C++. Operadores new y delete Hasta ahora slo se ha visto dos posibles tipo de duracin de las variables: static, las cuales existen durante toda la ejecucin del programa, y automatic, que existen desde que son declaradas hasta que finaliza el bloque donde han sido declaradas. Con los operadores new y delete el programador tiene entera libertad para decidir crear o destruir variables cuando las necesite. Una variable creada con el operador new dentro de cualquier bloque, perdura hasta que es explcitamente borrada con el operador delete. Puede traspasar la frontera de su bloque y ser manipulada por instrucciones de otros bloques. Estos operadores sern descritos mas ampliamente en el apartado dedicado a la reserva dinmica de memoria. Operador de resolucin de visibilidad (::) Este operador permite acceder a una variable global cuando sta se encuentra oculta por otra variable local del mismo nombre. Considrese el siguiente ejemplo: int a=2; void main(void){ int a = 10; cout << a << endl; cout << ::a << endl; }

//muestra por pantalla 10 //muestra por pantalla 10

OPERADOR CONDICIONAL (el ?:) Tambin conocido como operador opcional. Este operador permite controlar el flujo de ejecucin del programa. El operador condicional es un procesador con tres operandos (ternario) que tiene la siguiente forma general: expresin_1 ? expresin_2 : expresin_3; (121)

Explicacin: Se evala la expresin_1. Si el resultado de dicha evaluacin es trae (!=0), se ejecuta la expresin_2; si el resultado es false(=0), se ejecuta expresin_3.

Los backward_warning.h o warning de C A veces el programa C/C++ suele enviarnos estas clase de mensajes o capciones lo que muchas veces nos alarma, lo que indican esta clase de mensaje warning es que no estamos usando alguna variable, por lo que si nos aparece recomiendo encarecidamente que se ordene compilar y ejecutar el programa en contra de todo lo que se piense. Los warning no son errores como tales.

(122)

Estructuras de almacenamiento: Manejos de arreglos apuntadores Una estructura es una forma de agrupar un conjunto de datos de distinto tipo bajo un mismo nombre o identificador. Por ejemplo, supngase que se desea disear una estructura que guarde los datos correspondientes a un alumno de primero. Esta estructura, a la que se llamar alumno, deber guardar el nombre, la direccin, el nmero de matrcula, el telfono, y las notas en las 10 asignaturas. Cada uno de estos datos se denomina miembro de la estructura. El modelo o patrn de esta estructura puede crearse del siguiente modo: Programa: struct alumno { char nombre[31]; char direccion[21]; unsigned long no_matricula; unsigned long telefono; float notas[10]; }; El cdigo anterior crea el TDD alumno (plantilla registro de nombre alumno), pero an no hay ninguna variable declarada con este nuevo tipo. De hecho este bloque se declara fuera del main, adems la necesidad de incluir un carcter (;) despus de cerrar las llaves. Este tipo de declaracin ahorra complejidad en memoria ya que ni siquiera sus campos ocupan espacio en memoria, a menos que se empiecen a crear nodos o listas. Luego para declarar dos variables de tipo alumno se debe utilizar la sentencia: Programa: alumno alumno1, alumno2; donde tanto alumno1, como alumno2 son una estructura, la cual hereda la forma de la plantilla alumno, que podr almacenar un nombre de hasta 30 caracteres c/u, una direccin de hasta 20 caracteres c/u, el nmero de matrcula, el nmero de telfono y las notas de las 10 asignaturas. Tambin podran haberse definido alumno1 y alumno2 al mismo tiempo que se defina la estructura de tipo alumno. Para ello bastara haber hecho: Programa: struct alumno { char nombre[31]; char direccin[21]; unsigned long no_matricula; unsigned long telefono; float notas[10]; }alumno1, alumno2; (123)

Para acceder a los miembros de una estructura se utiliza el operador punto(.), precedido por el nombre de la estructura y seguido del nombre del miembro. Por ejemplo, para dar valor al telfono del alumno alumno1 el valor 943903456, se escribir: alumno1.telefono = 943903456; y para guardar la direccin de este mismo alumno, se escribir: strcpy(alumno1.direccin, C/ Penny Lane 1,2-A); La estructura asta ahora esta disponible para dos elementos alumno1 y alumno2. El tipo de estructura creado se puede utilizar para definir ms variables o estructuras de tipo alumno, as como vectores de estructuras de este tipo. Por ejemplo: struct alumno { char nombre[31]; char direccin[21]; unsigned long no_matricula; unsigned long telefono; float notas[10]; }; void main() { * * * alumno *nuevo_alumno, *clase[300]; //apuntadores a una estructura(2) // alumno nuevo_alumno,clase[300]; //estructura, vector de estructuras } En este caso, nuevo_alumno es una estructura de tipo alumno, y clase[300] es un vector de estructuras con espacio para almacenar los datos de 300 alumnos. El nmero de matrcula del alumno 264 podr ser accedido como clase[264].no_matricula ( clase[264]->no_matricula (2)). Los miembros de las estructuras pueden ser variables de cualquier tipo, incluyendo vectores y matrices, e incluso otras estructuras previamente definidas. Las estructuras se diferencian de los arrays (vectores y matrices) en varios aspectos. Por una parte, los arrays contienen informacin mltiple pero homognea, mientras que los miembros de las estructuras ser de naturaleza muy diferente. Adems, las estructuras permiten ciertas operaciones globales que no se pueden realizar con arrays. Por ejemplo, la sentencia siguiente: clase[298] = nuevo_alumno; (124)

Hace que se copien todos los miembros de la estructura nuevo_alumno en los miembros correspondientes de la estructura clase[298]. Estas operaciones globales no son posibles con arrays. Se pueden definir tambin punteros a estructuras: alumnos *pt; pt = &nuevo_alumno; Ahora, el puntero pt apunta a la estructura nuevo_alumno y esto permite una nueva forma de acceder a sus miembros utilizando el operador flecha(->), constituido por los signos (-) y (>). As, para acceder al telfono del alumno nuevo_alumno, se puede utilizar cualquiera de las siguientes sentencias: Pt->telefono; (*pt).telefono; donde el parntesis es necesario por la mayor prioridad de operador (.) respecto a (*). Las estructuras admiten los mismos modos auto, estern y static que los arrays y las variables escalares. Las reglas de inicializacin a cero por defecto de los modos extern y static se mantienen. Por lo dems, una estructura puede inicializarse en el momento de la declaracin de modo anlogo a como se inicializan los vectores y matrices. Por ejemplo, una forma de declarar e inicializar a la vez la estructura alumno_nuevo podra ser la siguiente: struct alumno { char nombre[31]; char direccion[21]; unsigned long telefono; float notas[10]; } alumno_nuevo = {Mike Smith, Sam Martn 87,2 A, 62419, 421794}; donde, como no se proporciona valor para las notas, estas se inicializan en cero (por defecto). Las estructuras constituyen uno de los aspectos ms potentes del lenguaje C++. En esta seccin se ha tratado slo de hacer una breve presentacin de sus posibilidades.

(125)

Gestin dinnica de memoria Segn lo visto hasta ahora, la reserva o asignacin de memoria para vectores y matrices se hace de forma automtica con la declaracin de dichas variables, asignando suficiente memoria para resolver el problema de tamao mximo, dejando el resto sin usar para problemas ms pequeos. As, si en la funcin encargada de realizar un producto de matrices, stas se dimensionan para un tamao mximo (100, 100), con dicha funcin se podr calcular cualquier producto de un tamao igual o inferior, pero aun en el caso de que el producto sea por ejemplo de tamao (3,3), la memoria reservada corresponder al tamao mximo (100,100). Es muy til el poder reservar ms o menos memoria en tiempo de ejecucin, segn el tamao del caso concreto que se vaya a resolver. A esto se llama reserva o gestin dinmica de memoria. Existe en C++ un operador que reserva la cantidad de memoria deseada en tiempo de ejecucin. Se trata del operador new, del que ya hablamos en los temas anteriores. Este operador utiliza la siguiente forma: Sintaxis: <TDD> *vector; //vector es el nombre de un apuntador Vector = new <TDD> [variable]; //variable es una variable entera El operador new se utiliza para para crear variables de cualquier tipo, ya sean las estndar por el usuario. La mayor ventaja de esta gestin de memoria es que se puede definir el tamao del vector por medio de una variable que toma el valor adecuado en cada ejecucin. Existen tambin un operador llamado delete que deja libre la memoria reservada por new y que ya no se va a utilizar. Recordemos que cuando la reserva es dinmica la variable creada perdura hasta que sea explcitamente borrada por este operador. La memoria no se libera por defecto en C/C++ a excepcin de lenguajes como Java. El prototipo de este operador es el siguiente: delete[] vector; A continuacin se presenta a modo de ejemplo un programa que reserva memoria de modo dinmico para un vector de caracteres:

(126)

#include <iostream.h> #include <string.h> void main() { char Nombre[50]; cout <<Introduzca su nombre:; cin >> Nombre; char *CopiaNombre = new char[strlen(Nombre)+1]; // Se copia el nombre en la variable copianombre strcpy(CopiaNombre, Nombre); delete[] CopiaNombre; } El siguiente ejemplo reserva memoria dinmicamente para una matriz de doubles: #include <iostream.h> void main() { int nfil, ncol, i, j; double **mat; //se pide al usuario el tamao de la matriz cout << Introduzca numero de filas y columnas: cin >> nfil >> ncol; // se reserva memoria para el vector de punteros mat = new double*[nfil]; //se reserva memoria para cada fila for (i=0; i<nfil; i++) mat[i] = new double[ncol]; //se inicializa toda la matriz for (i=0; i<nfil; i++) for (j=0; j<ncol; j++) mat[i][j]=i+j; //se imprime la matriz for (i=0; i<nfil; i++) { for (j=0; j<ncol; j++) cout << mat[i][j]<< \t; cout << \n; } //se libera la memoria for (i=0; i<nfil; i++) { //se borran las filas de la matriz delete []mat[i]; //se borra el vector de punteros delete []mat; } }

Constantes de tipo Enumeracin En C++ existe una clase especial de constantes llamadas constantes enumeracin. Estas constantes se utilizan para definir los posibles valores de ciertos identificadores o variables que slo deben poder tomar unos pocos valores. Por ejemplo se puede pensar en una variable llamada dia_de_la_semana que slo pueda tomar los 7 valores siguientes: lunes, martes, mircoles, jueves, viernes, sbado y domingo. Es muy fcil imaginar otros tipos de variables anlogas, una de las cuales podra se una variable booleana con solo dos valores: SI y NO, o TRUE y FALSE, u ON y OFF. El uso de este tipo de variables hace ms claros y legibles los programas, a la par que disminuye la probabilidad de introducir errores. En realidad, las constantes enumeracin son los posibles valores de ciertas variables definidas como de ese tipo concreto. Considrese como ejemplo la siguiente declaracin: enum dia {lunes, martes, mircoles, jueves, viernes, sabado, domingo}; Esta declaracin crea un nuevo tipo de variable el tipo de variable da- que slo puede tomar uno de los 7 valores encerrados entre las llaves. enum dia dia1, dia2;

Y estas variables se les pueden asignar valores de la forma dia1 = martes; o aparecer en diversos tipos de expresiones y de sentencias. A cada enumerador se le asigna un valor entero. Por omisin, estos valores parten de cero con un incremento unitario. Adems, el programador puede controlar la asociacin de esos valores como aparece a continuacin, enum dia {lunes=1, martes, mircoles, jueves, viernes, sabado, domingo}; asocia un valor 1 a lunes, 2 a martes, 3 a mircoles, etc., mientras que la declaracin, enum dia {lunes=1, martes, mircoles, jueves=7, viernes, sabado, domingo}; asocia un valor 1 a lunes, 2 a martes, 3 a mircoles, un 7 a jueves, un 8 a viernes, un 9 a sbado y un 10 a domingo. Esta asociacin no conlleva que las variables tipo enum se comporten como enteros, son un nuevo tipo de variables que necesitan un cast para que su valor entero pueda se asignado. Se puede tambin hacer la definicin de tipo enum y la declaracin de las variables en una nica sentencia, en la forma: enum palo = {oros, copas, espadas, bastos} carta1, carta2, carta3; donde carta1, carta2, carta3 son variables que slo pueden tomar los valores oros, copas, espadas y bastos (equivales respectivamente a 0, 1, 2 y 3). (128)

Diferencias entre POO y POC En el lenguaje de computacin: POO significa programacin orientada a objetos, mientras que POC se conoce como programacin orientada a clases. Un programa puede implementarse tanto con POO como con POC, la diferencia radica en que si se programa orientado a objetos cada uno de ellos junto con el programa controlador o void, aparecen como dispersos y sin relacin aparente entre s, pueden haber algunas variables comunes varios objetos a los cuales hay que pasrsela por parmetro cada vez que estos son llamados por el main, adems de ellos cada objeto dentro del programa puede llamar a otro cuando desee, esto lo determina el programador, pero no hay un forma para que el programa por si solo haga estas divisiones, este tipo de dificultades se corrigen con la POC. Aunque una clase tiene una mayor jerarqua que un objeto ya que un objeto (accin o funcin), es una instancia de una clase. La librera para generar tiempo en C++ time.h Implementacin: #include <stdio.h> //libreria de c++ para prototipos de entrada salida #include<iostream> //libreria de c++ para propositos de entrada salida #include <stdlib.h> //libreriadec++paraprototiposde conversion de numeros de textos #include <time.h> //libreria de c++ para prototipos para manipular fechas y horas #include <cstring> //funcion que genera el tiempo int generar_tiempo() { //comienza la accion tiempo retorna un entero int valor=0; //entero con valor cero srand( (unsigned)time( NULL ) ); /*hace la comparacion con respecto al reloj de la computadora*/ valor= (1 + rand() % 10 ) ; //saca un numero entero entre 1 y 10 return valor; //retornamos el valor de el tiempo en la variable valor }//final de la funcion generar tiempo objeto Uso del: system(cls) Sirve para limpiar la consola de la interfaz usuario de cpp en automtico.

(129)

Creacin de un objeto en C++ //Esta es la forma como se declara su prototipo:


void detalle (int tabulacion,int espacio,int sensor,int bandera); void detalle (int,int,int,int); //una forma especial de prototipo void detalle (int tabulacion,int espacio,int sensor,int bandera) { //adornos del objeto char caracter[16]= {'-','*','=','>',':','@','_','<','.','+','x','#','?','M','|','X'}; char mansu[8]={' ','(','[','{',' ',')',']','}'}; char menu[7]={'W','O','8','/','9','6','o'}; //variables locales a detalle int global,global2,global3,global4; global=global2=global3=global4=0; //validacin de todas en una lnea if((tabulacion<0)|(espacio<0)|(sensor<0)|(bandera<0)) { detalle(1,1,0,666); //llamada recursiva } if(bandera==0) { if((tabulacion==0)&(espacio==0)) {} //hall else if((tabulacion==0)&(espacio!=0)) { for(global4=1;global4<=espacio;global4++){printf(" ");} } else { for(global4=1;global4<=tabulacion;global4++){printf("\n");} if(sensor!=0){detalle(0,espacio,0,bandera);} } }//fin de bandera=0 if((bandera<200)&((bandera==1)|(bandera>=2))| ((tabulacion==0)&(espacio==0)&(sensor!=0))) { if((sensor==0)&(espacio==0)) { if((tabulacion>-1)&(tabulacion<25)) { global3=79; if((bandera>2)&(bandera<80)) { global3=global3+bandera*(-1)+2; } if((bandera>=80)&(bandera<156)) { global2=1; if(bandera!=155) { global4=1; } if((bandera>80)&(bandera<155)) { global3=global3+bandera*(-1)+80; } }

if(bandera>155) {detalle(1,2,0,666);} while(global<global3) { if((global2==0)&(global4>=0)) { if((tabulacion>(-1))&(tabulacion<6)) { printf("%c",menu[tabulacion]); } else { if(tabulacion<22) { if(espacio==0) { sensor=tabulacion; sensor=sensor-6; espacio++; } printf("%c",caracter[sensor]); //W } else if(tabulacion==23) { if(global!=0) { if(global%2==0) { printf("%c",menu[4]); //O } else if((global%2!=0)|(bandera==2)) { printf("%c",menu[5]); } } else { printf("%c",mansu[0]); //O } } else { if(global%2==0) //case 24 { printf("%c",caracter[5]); } else if((global%2!=0)|(bandera==2)) { printf("%c",menu[3]); //O } } } if(bandera==2) { global=78; } if(global4==1) { global2=1; } } else {

//W

detalle(0,1,1,0); global2=0; } global++; } } else {detalle(1,0,0,666);} } else { if((tabulacion==0)&(espacio==0)&(sensor!=0)) { espacio=sensor; tabulacion=bandera; bandera=-1; } else { if(espacio>70) { sensor=espacio-71; //se cambio por detalle(2,sensor,1,0); //en automatico se puede copiar y pegar a gusto } detalle(bandera,sensor,1,0); //en automatico se puede copiar y pegar a gusto //se cambio por detalle(bandera+1,sensor,1,0); } if((espacio<4)&(espacio>-1)) { printf("%c%d%c",mansu[espacio],tabulacion,mansu[espacio+4]); } else if(espacio==4) { printf("%d",tabulacion); } else if((espacio>4)&(espacio<26)) { global=espacio-5; detalle(global,0,0,2); } else if((espacio>25)&(espacio<34)) { global=espacio-26; printf("%d%c",tabulacion,mansu[global]); } else if((espacio>33)&(espacio<50)) { global=espacio-34; printf("%d%c",tabulacion,caracter[global]);} else if(espacio==50) {printf("%c%c",caracter[0],caracter[8]); // -. } else if(espacio==51) { printf("%c%c",caracter[2],caracter[3]); // => } else if(espacio==52) { printf("%c%c",caracter[3],caracter[0]); // >} else if(espacio==53) {

printf("%c%c",caracter[7],caracter[3]); // <> } else if(espacio==54) { printf("%c%c",caracter[0],caracter[3]); // -> } else if(espacio==55) { printf("%c%c%c",caracter[7],caracter[0],caracter[3]); // <-> } else if((espacio>55)&(espacio<59)) { global=1; if(espacio==56) { printf("%c%c",mansu[global],mansu[global+4]); // () } if(espacio>56) { global++; if(espacio==57) { printf("%c%c",mansu[global],mansu[global+4]); // [] } if(espacio>57) { global++; printf("%c%c",mansu[global],mansu[global+4]); // {} }}} else if(espacio==59) { printf("%c%c",caracter[1],caracter[0]); // *} else if(espacio==60) { printf("%c%c",menu[1],caracter[0]); // O} else if(espacio==61) { printf("%c%c%c",mansu[2],caracter[15],mansu[6]); // [X] } else if(espacio==62) { printf("%c%c",mansu[6],caracter[0]); // ]} else if(espacio==63) { printf("%c%c",menu[6],caracter[0]); // o} else if(espacio==64) { printf("%c%c%c%c%c",caracter[6],menu[6],menu[1],menu[6],caracter[6]); //_oOo_ } else if(espacio==65) { printf("%c%d%c",caracter[14],tabulacion,caracter[14]); // o|o } else if(espacio==66) { printf("%c%c%d%c%c",caracter[6],menu[6],tabulacion,menu[6],caracter[6]); // _o*o_ } else if(espacio==67)

{ printf("%c%c%d%c%c",caracter[0],mansu[2],tabulacion,mansu[6],caracter[0]); } else if(espacio==68) { printf("%c%c%d%c%c",caracter[0],mansu[3],tabulacion,mansu[7],caracter[0]); } else if(espacio==69) { printf("%c%c%d%c%c",caracter[0],mansu[1],tabulacion,mansu[5],caracter[0]); } else if(espacio==70) { printf("%c%c%c%d%c%c%c",caracter[6],menu[6],caracter[14],tabulacion,caracter[14], menu[6],caracter[6]); } if((bandera==(-1))) {} else { if(espacio<71) { detalle(0,1,0,0); //es en automatico //se cambio por detalle(0,bandera,0,0); } else { if(sensor!=0) { sensor/=2; if(sensor%2!=0) { sensor=sensor-1; } detalle(0,sensor,0,0); //no es automatico }}}}} if(bandera==666) { //tutorial y capciones del objeto

if((sensor==666)&(espacio==666)&(tabulacion==666)) {

printf("\n\n TUTORIAL: detalle(x,c,v,z); Version Premiun\n\n"); printf("(x,0,0,0) baja un x numero de lineas en blanco(1) \n si x=300...aprox limpia pantalla por arriva\n"); printf("(0,c,0,0) escribe un caracter vacio un c numero de\n veces(2)\n"); printf("(x,c,1,0) hace (1) y (2) al mismo tiempo\n"); printf("(x,0,0,1) separa segun el valor de x que se ponga x=[0...]\n"); printf("(x,0,0,2) imprime un solo caracter x=[0...]\n"); printf("(x,c,v,z) x numero de opcion 1,c caracter [1], v espaciado(1) 1x1 _[1],\n z espaciado(2) [1]_\n"); printf(" x=[1,..], c=[1,..], v=[0,..], z=[1,..]\n"); printf("(0,0,v,z) (4)imprime caracteres v especiales,\n y la opcion z si tienen numeracion\n"); printf("(0,0,v,0) imprime tambien caracteres v especiales como (4),\n sin numeracion z=0\n"); printf("(x,0,0,81>z>2) separa recortando la linea escojida\n segun el valor de z\n"); printf("(x,0,0,z=80) coloca una linea semirecortada\n"); printf("(x,0,0,155>z>80) recorta la linea semirecortada segun x\n"); printf("(x,0,0,155) centra la linea de separacion x\n"); printf("(0,0,0,0) accion estable no pasa nada...\n"); printf("\n\n SOLO: USO de accion en CORRERMENU(c,y1,y2,...,i) => detalle(x,c,v,z)\n"); printf(" paramero recomendado para z es 2 por defecto\n"); printf("\n\n c=70 MAX signos (variable caracter) hace (1) y (2)\n\n automatic...OK!\n"); printf("\n\n CODIGO HECHO POR <-/DZ/-> trabaja por mi!\n"); } else { if(tabulacion==1) { printf("\n\n Mal uso de detalle(x,x,x,x)"); if(espacio==0) { printf("\n\n Parametro fuera de alcanze de arreglos\n\n 25-30 caracteres MAX...\n"); } if(espacio==1) { printf("\n\n La funcion no asepta parametros negativos\n"); } if(espacio==2) { printf("\n\n ha pasado al menos un parametro mal bandera debe ser < 155\n"); }}}}}

//fin del objeto Las aplicaciones de este objeto son varias aunque solo se use para la aadir adornos a los mens, cpielo en un archivo cpp y gurdelo con la extensin .hpp para llamarlo a otro archivo .cpp cuando quiera.

(135)

Plantilla de men en C++ (una forma muy bsica)


#include #include #include #include #include #include #include <stdlib.h> /*libreras estndar de C*/ <stdio.h> /*libreras estndar de C*/ <iostream.h> /*uso del cin y cout por a veces puede arrojar warning*/ <time.h> <conio.h> <string.h> detalle.hpp //se agrega un archivo de cabecera que es precisamente //el objeto que se creo anterior mente int escribir(int,int); // prototipo de funcin simplificado equivale a // int escribir(int menu,int liga) int main() { int client,taqui,titu; char indi; indi='?'; client=taqui=titu=0; /* B L O Q U E D E L P R O G R A M A */ escribir(0,0); //escritura detalle(1,0,1,0); //tabulacion detalle(2,0,0,1); //separa detalle(1,4,1,0); //tabulacion escribir(0,1); //escritura detalle(1,0,0,0); //tabulacion detalle(2,0,0,1); //separa detalle(1,0,1,0); //tabulacion escribir(0,2); //escritura escribir(0,3); //escritura scanf("%s",&indi); //lectura de la variable menu detalle(0,0,0,1); //separa switch(indi) { //hay solo 3 casos case '1': detalle(300,0,0,0); //limpia la pantaya detalle(1,4,1,0); //tabula escribir(1,0); //escritura detalle(1,4,1,0); //tabula escribir(1,2); //escritura detalle(1,4,1,0); //tabula escribir(1,3); //escritura detalle(2,0,0,0); //limpia la pantaya goto reynapepiada; //se hace un salto de linea break; case '2': detalle(300,0,0,0); //limpia la pantaya escribir(2,0); //escritura detalle(2,0,0,0); //asi se separa goto reynapepiada; //se hace un salto de linea break; default: //caso 3 o o una letra!!! if(indi=='3') {

/*F I N

B L O Q U E

D E L

P R O G R A M A */

panconqueso: detalle(1,4,1,0); escribir(3,0);

//etiqueta 1 //tabula //escritura

} else { detalle(300,0,0,0); //limpia la pantaya detalle(0,4,1,0); //tabula if((indi=='4')|(indi=='5')|(indi=='6')|(indi=='7')|(indi=='8')|(indi=='9')| (indi=='0')) { escribir(3,1); //escritura } else { escribir(3,2); //escritura } reynapepiada: //etiqueta 2 detalle(0,0,0,1); //separa escribir(2,1); //escritura escribir(0,3); //escritura scanf("%s",&indi); //lectura de la variable men detalle(0,0,0,1); //separa if(indi=='1') { detalle(300,0,0,0); //limpia la pantaya main(); //se hace la bendita llamada al main } else { goto panconqueso; //se hace un salto de lnea }} break; } return 0; }

/*A CONTINUACION SE DESCRIBE LA FUNCION ESCRIBIR*/ int escribir(int menu,int liga) { if(menu==0) { if(liga==0) {printf("\n Universidad Central de Venezuela \n Facultad de Ciencias\n Escuela de Computacion\n");} else if(liga==1) {printf("\n EL BANCO ESTA ABIERTO... \n\n SIMULACION DE UNA COLA EN UN BANCO\n");} else if(liga==2) {printf(" Menu de opciones: \n\n 1) Comenzar simulacin \n\n 2) Desarrolladores \n\n 3) Salir");} else {printf("\n\n Escoja una opcion: ");} } else if(menu==1) { if(liga==0) {printf("CARGANDO DATOS PARA LA SIMULACION...OK\n");} else if(liga==1) {printf("GENERANDO SISTEMA DE COLAS UNIFORME...OK\n");} else if(liga==2) {printf("REGISTRANDO LAS OPERACIONES DEL DIA...OK\n");} else {printf("ADMINISTRADO LA ATENCION AL CLIENTE...OK\n");} } else if(menu==2) { if(liga==0) {printf("\n Hecho por:\n\n Daniel Zenobio CI 17141735");} else {printf("\n Precione (1) para volver al menu principal \n precione otra tecla para salir. ");} } else { if(liga==0){printf("Gracias por usar nuestro programa...!!!\n\n");} if(liga==1){printf("ERROR!!! OPCION U PARAMETRO INVALIDO\n");} if(liga==2){printf("ERROR!!! NO PUEDE ESCRIBIR LETRAS SOLO NUMEROS\n");} } return 0; }

(138)

Recursividad en C++ Le lenguaje C soporta recursividad, un programa u objeto que se comporta de manera recursiva, es aquel que se invoca a si mismo un numero finito de veces, para encontrar una solucion, basara ver el cdigo del objeto detalle del cual se hablo anteriormente, el cual usa mucha recursividad. La funcin factorial puede representarse de manera recursiva de manera: int factorial(int aux) {

} No obstante la recursividad suele crear problemas cuando se le pasan parmetros muy altos, adems de ello cada vez que un programa se invoca a si mismo este apila una cantidad de datos que usara en el siguiente nivel recursivo lo que indica una gasto en memoria, en ciertos problemas los programas que resuelven recursivamente un problema especifico encuentran su solucin en un nivel recursivo, sin embargo estos continan llamndose recursivamente por lo que el valor se pierde en el siguiente nivel recursivo en tales casos es conveniente el uso de hoyos, es decir que cuando se encuentre la solucin se haga una llamada al objeto pero que esta caiga en un lugar vaco, ejemplo con factorial: Supongamos se la llamada se efecta en el main() de la forma: factorial(5,0); { int factorial(int aux,int indicador) If(indicador==0) { if(aux==0) { return(1); } else { if (aux<=3) {} //no hace nada else {return(aux*factorial(aux-1,indicador));} }

if(aux==0) { return(1); } else { return(aux*factorial(aux-1)); }

(139)

Los ciclos infinitos de C++ (uso de palabras break y continue) Una forma de hacerlos es la siguiente: while(1){} do{}while(1); //desde luego estas no son formas normales

Progresivos El contador aumenta


Ciclos(bucles)

Ciclo condicional, puede ejecutarse o no. Ciclo incondicional, se ejecuta siempre El contador es independiente, si su lmite de incremento o decremento depende de una constante El contador dependiente el lmite de incremento o decremento lo puede modificar el usuario

Regresivos El contador disminuye

Instrucciones de salto de lnea Palabra reservada continue:

El nmero del contador indica un caso o situacin especial como es el caso especial del FOR

opcion=0;n=4; while (opcion<n) //el contador aumenta dependiendo del valor de n { printf(" YO ENTRO SIEMPRE "); opcion++; if(opcion==2)continue; //se es verdadero la siguentes lineas no se ejecuta //sino que se inicia el siguiente ciclo printf("->CON PERMISO"); } Corrida en fro: opcin 0 1 2 3 4=n YO YO YO YO Cadena1 ENTRO SIEMPRE ENTRO SIEMPRE ENTRO SIEMPRE ENTRO SIEMPRE Cadena2 "CON PERMISO" (se salta la lnea) "CON PERMISO" "CON PERMISO"

Tanto el while() como el do-while() son como funciones que reciben datos booleanos 0 es falso y distinto de cero es verdad.

(140)

Es decir genera la secuencia: YO ENTRO SIEMPRE->CON PERMISO YO ENTRO SIEMPRE YO ENTRO SIEMPRE->CON PERMISO YO ENTRO SIEMPRE->CON PERMISO Existen otras formas de usar las sentencias con continue otra forma es: opcion=0;n=4; while (opcion<n) { printf(" YO ENTRO SIEMPRE "); opcion++; if(opcion==2) { printf("->SIN PERMISO"); continue; //salto de lnea } //sino que se inicia el siguiente ciclo printf("->CON PERMISO"); } Corrida en fro: opcin 0 1 2 3 4=n opcion=0; n=4; while(opcion<n) { printf(" YO ENTRO SIEMPRE "); opcion++; if(opcion==2) { printf("->SIN PERMISO"); /*si entra aqu ya salio del condicional incluido del sino por lo que pasa a la lnea despus del continue*/ } else continue; //es equivalente a else{continue}; printf("->CON PERMISO"); } YO YO YO YO Cadena1 ENTRO SIEMPRE ENTRO SIEMPRE ENTRO SIEMPRE ENTRO SIEMPRE Cadena2 "CON PERMISO" "SIN PERMISO" "CON PERMISO" "CON PERMISO"

(141)

Corrida en fro: opcin 0 1 2 3 4=n YO YO YO YO Cadena1 ENTRO SIEMPRE ENTRO SIEMPRE ENTRO SIEMPRE ENTRO SIEMPRE comparacin 1==2(false) "SIN PERMISO" 3==2(false) 4==2(false) Cadena2 (se salta la linea) "CON PERMISO" (se salta la lnea) (se salta la lnea)

Sin embargo considere el siguiente conjunto de instrucciones: while (opcion<4) { printf("YO ESRIBO SIEMPRE"); if(opcion==2)continue; /*si opcin=2 las lneas siguientes no se leern por el programa ya que se iniciara el siguiente ciclo*/ printf("YO ESRIBO"); opcion++; // ERROR!!!

Este conduce a un ciclo infinito ya que la sentencia continue esta antes del incremento por lo que cuando opcion=2 es errneo. Corrida en fro: opcin 0 1 2 2 2 (2==4)? YO YO YO YO YO Cadena1 ENTRO SIEMPRE ENTRO SIEMPRE ENTRO SIEMPRE ENTRO SIEMPRE ENTRO SIEMPRE comparacin 0==2(false) 1==2(false) 2==2(true) 2==2(true) 2==2(true) Cadena2 YO ESCRIBO YO ESCRIBO (se salta la lnea) (se salta la lnea) (se salta la lnea)

Este error ocurre porque se esta saltando el incremento por lo que en ciclos la sentencia continue debe colocarse despus del incremento. Veamos ahora un ciclo incondicional, con contador, usando la sentencia break.

(142)

n=0; while(1) { opcion++; /* . conjunto de intrucciones que se ejecutaran n veces . . */ } if(opcion==n)break;

Otra forma de programar con break. opcion=0; while(1) { opcion++; printf(" YO ENTRO SIEMPRE "); if(opcion==2) { printf("->SIN PERMISO"); break; }else{ printf("->CON PERMISO"); }

Estas instrucciones generan la secuencia: YO ENTRO SIEMPRE ->CON PERMISO YO ENTRO SIEMPRE ->SIN PERMISO "

opcin 0 1 2

Cadena1 YO ENTRO SIEMPRE YO ENTRO SIEMPRE

comparacin 1==2(false) 2==2(true)

Cadena2 "CON PERMISO"* "SIN PERMISO"

*Hay un salto de lnea en la lnea que sigue a esta por el break. (143)

Otra forma quizs ms formal de escribir un ciclo es: opcion=n; while(1) { /* . conjunto de instrucciones que se ejecutaran n+1 veces . . */ if(opcion<n){opcion++;}else break; } Instrucciones inmediatas: Son de la forma por ejemplo opcion=0; if(opcion!=0) printf(prueba 1); printf(prueba 2); printf(prueba 3); En otros casos: for(opcion=0;opcion<4;opcion++) printf("prueba"); cuerpo del for implicito se escribe 4 veces printf(prueba 2); fuera del cuerpo del for se escribe una vez Una instruccin inmediata es el cuerpo implcito restringido a una lnea que se ubica justo despus de una sentencia con alguna palabra reservada. En donde se ubica una sola instruccin. Con bucles como while y do while no es aconsejable el uso de instrucciones inmediatas. Este es el cuerpo de alcance del if, no se ejecuta Se ejecuta ya que esta fuera del alcance se sigue ejecutando

(144)

Paso de punteros y variables a objetos Pase por valor Tambin llamado paso por copia, significa que cuando C++ compila la funcin y el cdigo que llama a la funcin, la funcin recibe una copia de los valores de los parmetros. Si se cambia el valor de un parmetro, variable local, el cambio solo afecta a la funcin, la funcin solo recibe una copia de los valores de los parmetros. Paso de punteros por referencia Cuando una funcin debe modificar el valor de parmetro pasado y devolver este parmetro pasado a la funcin llamadora se ha utilizado el mtodo de paso parmetro por referencia o direccin. Ejemplo: main() { int i=6; func_i(i); return; } func_i(int i) { i++; return; //es igual a return 0; }

El mtodo por defecto de pasar parmetros por valor es por valor, a menos que se pasen arrays, ya que los arrays se pasan siempre por direccin.

(145)

struct persona { int ID; persona *prox; }; main() { int A ,*B,*C,*D; //se declara una variable y tres apuntadores a entero A=7; //A puede no inicializarse char *name[10]; //arreglo de apuntadores char aname[3][4]; //es un arreglo de 2D de 200 elementos. <TDD> E[n]={g0,g1,g2,g3,.,g(n-1)}; //un arreglo cualquiera n>-1 persona *tipo; tipo=new persona; tipo->prox=NULL; tipo->ID=0; B=&A; *B=10; //B es un alias de A y contiene la direccin de memoria donde esta A //A y *B ahora valen 10, // B=10? las posiciones de memoria no pueden modificarse C=&(*B); //C contiene la direccin de memoria donde esta el apuntador B D=&(*C); //D contiene la direccin de memoria donde esta el apuntador C *D = 100; //*D,*B,*C,A ahora valen 100 A=func_1(A); int func_1(int A){A++;return A;} Funcion2(A); Funcion3(&B,&C,&D); Funcion4(B,C,D); Funcion5(*B,*C,*D); Funcion6(E); /*se esta pasando la primera posicin de memoria del arreglo E Equivale a: Funcion6(&E[0]); */ Funcion7(tipo); //se pasa un apuntador a al primer nodo por valor Funcion8(&tipo); // se pasa un apuntador a al primer nodo por referencia return 0; } Sobre el arreglo name: name tiene 10 elementos que son apuntadores no inicializados. La ventaja es que los vectores de cada fila pueden ser de longitudes diferentes name[3][4] y aname[3][4]. Son correctas en C.

(146)

int func_1(int A){} En este caso el valor de A si se modifica al tomar el valor que devuebe fun_1. ya que se modifican la posiciones de memoria con el operador return. En el hall*. *Entindase por hall un bloque de la forma {} int Funcion2(int &A){} En este caso gracias al operador de dereferenciacin el valor de A se modifica dentro y despus de llamarse la funcin. Ya que se pasa por referencia. int Funcion3(int **B,int **C,int **D){**B++;} En este caso se pasan apuntadores por referencia, el trabajo que se puede hacer dentro de hall la variable debe tener el mismo tamao del asterisco debe ser el mismo al tamao de los asteriscos especificado en los parmetros. int Funcion4(int *B,int *C,int *D){*B=10;} Los apuntadores se pasan por referencia. int Funcion5(int B,int C,int D){B=10;} Los apuntadores se pasan por valor. int Funcion6(int E[n]){B[0]=10;} //otra forma es Funcion6(int *E){B[0]=10;} Los arrays sempre se pasan por referencia ya que lo que realmente se pasa es la direccion de memoria del primero elemento del arreglo. Cuando se trabajan con registros y punteros la otra forma es: int Funcion7(struct persona *tipo) {tipo=new <Nregistro>; tipo-><campo>=<valor>;} De esta forma el puntero tipo se pasa por valor. int Funcion8(struct persona **tipo) {*tipo=new <Nregistro>;(*tipo)-><campo>=<valor>;} De esta forma el puntero tipo se pasa por referencia. En los struct los apuntadores por lo general se suelen pasar por referencia siempre, un apuntador cuando se declara no tiene valor especifico, solo tiene una direccin de memoria donde se encuentra un dato en especifico. Si no apunta a ningn valor almacenado en alguna variable, el apuntador por lo general apunta a null.

(147)

Lnea de comandos: El siguiente cdigo le indicara la direccin en donde se encuentra su programa: main(int argc,char **argv) { int i; printf("argc= %d\n",argc); /*programa que imprime los argumentos de la lnea de comandos*/ for(i=0;i<argum;++i) { printf("argc[%d]: %s\n",i,argv[i]); } scanf("%d",&i); } Entrada / Salida *Archivos La primera operacin sobre un archivo antes de usarlo es abrirlo: FILE *fopen(char *name,char *mode) Los modos de apertura incluyen: r lectura wescritura ainsertar al final append. *Para abrir un archivo se debe declarar un (file pointer) que apunta a un escritura del tipo FILE. FILE *stream, *fopen(); if((stream=fopen(myfile.dat,r))==NULL) { printf(No se pudo abrir el archivo %s\n,myfile.dat); exit(1); //finaliza la ejecucin del programa en algunos compiladores, }

(148)

Variables vs Apuntadores *C es un apuntador de enteros, contiene solo un espacio en memoria no apunta a nada, NULL por defecto A es una variable, contiene una direccin en memoria y un valor asignado. Si se le coloca el & entonces A se convierte en una apuntador que devuelve la direccin de la variable. Nota: *C y A ambos son variables. Mientras que C y &A, ambos indican una posicin de memoria especifica de memoria. A=*(&A); mientras igual para C=*(&C)=&A;

El uso del operador & es generalmente para variables mientras que el * es para apuntadores. Objeto vs Clase Si se programa usando una clase implica a la vez que se programa tambin mediante el uso de objetos, cuando se programa orientado a objetos lo contrario no es cierto Un objeto se dice que es operativo, una clase no Una clase constituye un mbito implcito donde se relacionan o no variables y objetos, mientras que en la programacin orientada a objeto este mbito pareciera no existir ya que los objetos se relacionan de manera explicita, los pase de variables llamadas a objetos, variables globales locales, todo lo establece explcitamente el programador Si un objeto siempre va a ser una instancia lo que lo hace independiente de la clase, pero si pertenece a una clase se dice que es un mtodo de una clase, una clase necesita poseer mtodos Los objetos son las instancias bsicas a usar en caso de resolver problemas bsicos como la funcin factorial Las clases son usadas mas para problemas mas complejos donde el numero de objetos es numeroso al igual que las variables y se necesita de alguna manera un mbito que ordene estos mtodos, los relacione, establezca una jerarqua, separe, etc. por el programador, por ejemplo un problema que abarque el uso de mas de 20 objetos Cuando se programa orientado a objetos todos los objetos a excepcin de main tienen la misma jerarqua Hasta ahora no se conoce si un problema puede resolverse mediante clases o objetos La programacin orientada a objetos corresponde perfectamente con el mtodo divide y vencers, desde un enfoque mas bsico que si se usa una clase que los engloba y los relaciona de manera implcita (149)

Un struct es un objeto supongamos no usamos clase, este es una plantilla pero si manejamos el struct como si fuera una clase y es valido! este seria adems un mbito en donde estn unas variables u objetos es decir una clase es una plantilla tambin pero de objetos y/o variables* el cual es el concepto que se le da en los primeros semestres. La programacin usando clases es de alguna forma mas elegante que la programacin orientada a objetos, ya que si se tiene un gran numero de estos probablemente estos estn relacionados pero dispersos lo que les da un aspecto de desordenados B. define una clase como un conjunto de objetos que comparten una estrutura (mbito) y comportamiento comunes. Una clase no abarca espacio en memoria. El almacenamiento se asigna cuando se crea un objeto de una clase Una variable puede ser un objeto, lo contrario no es cierto *variables que en los primero semestres se les denominan campos tales como el nombre, apellido, cedula, edad, cargo, etc. que pueden ser manipulados dentro de la clase como si esta fuera un registro Aprendiendo a programar con Clases: Definicin de una clase: Antes que un programa pueda crear objetos de cualquier clase, esta debe ser definida. La definicin de una clase significa que se debe dar a la misma un nombre, darle nombre a los elementos que almacenan sus datos y describir las funciones que realizaran las acciones consideradas en los objetos. Las definiciones o especificaciones no son cdigos de programa ejecutable. Se utilizan para asignar almacenamiento a los valores de los atributos usados por el programa y reconocer las funciones que utilizar el programa, normalmente se sitan en archivos diferentes de los archivos de cdigos ejecutables, utilizando un archivo para cada clase. Se conocen como archivos de cabecera que se almacenan con un nombre de archivo con extensin, luego llame a la clase en el main() con la instruccin: #include extension.hpp (Para mas informacin consulte las paj. (48) de este manual) Formato: class nombre_clase { <campos1n>; //variables por lo general . <objetos1n>; //acciones, funciones, datos miembros de la clase . }; (150)

Ejemplo: class punto { public: int leerx(); //prototipo de una funcin void fijarx(int); // accin private: int x; //variables int y; }; Otra forma es: class edad { private: int edadhijo,edadmadre,edadpadre; //datos public; edad(); void iniciar (int,int,int); //functiones miembro de la clase int leerhijo(); int leermadre(); int leerpadre(); } Prototipo de clases: Una declaracin de una clase consta de una palabra reservada class y el nombre de la clase. Una declaracin de la clase se utiliza cuando el compilador necesita conocer una determinada clase definida totalmente en alguna parte del programa. Por ejemplo: class punto; //definida en algn lugar Objetos de clases: Una vez que la clase ha sido definida, un programa puede contener una instancia de una clase, denominado un objeto de una clase. Formato: nombre_clase identificador; As la definicin del objeto punto es: Punto p;

(151)

El operador acceso a un miembro (.) selecciona un miembro individual de un objeto de la clase. Las siguientes sentencias por ejemplo, crean un punto P, que fija su coordenada x y la visualiza a continuacin. Punto p; p.fijarx(100); cout<< coordenada

x es <<p.leer();

El operador punto se utiliza con los nombres de las funciones miembro para especificar que son miembros de un objeto. Ejemplo: class DiaSemana; DiaSemana Hoy; Hoy.visualizar(); //contiene la funcin visualizar //Hoy es un objeto //ejecuta la funcin visualizar

Se puede asignar un objeto de una clase a otro; por defecto, C++realiza una copia bit a bit de todos los miembros dato. En otras palabras, todos los miembros fsicamente contenidos en el rea de datos del objeto fuente se copian en el objeto receptor. Por ejemplo, el siguiente cdigo crea un punto llamado P2 y lo inicializa con el contenido de P. Punto P; //. . . Punto P2; P2=P; Un principio fundamental en programacin orientada a objetos es la ocultacin de informacin que significa que a determinados datos del interior de una clase no se puede acceder por funciones externas de la clase. El mecanismo principal para ocultar datos es ponerlos en una clase y hacerlos privados. A los datos o funciones privados solo se puede acceder desde dentro de la clase. Por el contrario las funciones pblicas son asequibles desde el exterior de la clase.

CLASE
No asequibles desde el exterior de la clase (acceso denegado)

Privado Datos o funciones

Asequible desde el exterior de la clase Secciones pblicas y privadas de la clase.

Publico Datos o funciones

(152)

Se utilizan tres diferentes especificadotes de acceso para controlar el acceso a los miembros de la clase estos son: public, private, protected. Se utiliza el siguiente formato general en definiciones de la clase situando primero las funciones miembro publicas, seguidas por los miembros protegido y privado (este orden sin embargo no es obligatorio). Formato: class nombre_clase { public: //elementos pblicos protected: //elementos protegidos private: //elementos privados }; El especificados public define miembros pblicos, que son aquellos a los que se puede acceder por cualquier funcin. A los miembros que siguen el especificador private solo se puede acceder por funciones miembro a la clase o por funciones y clases amigas. A los miembros que siguen el especificador protected se puede acceder por funciones miembros de la clase o clases derivadas de la misma(Subclase), as como por amigas. Los especificadotes public, private y protected pueden aparecer en cualquier orden. Tipo de miembro private protected public M. de la clase X X X Clase amiga X X X M. una Subclase X X F. no miembro

Si se omite el especificador de acceso, el acceso por defecto es privado, en la siguiente clase Estudiante, por ejemplo todos los datos son privados, mientras que las funciones miembro son publicas. class estudiante { long numid; char nombre[40]; int edad; public: long leerNumid(); char *Leernombre(); int leeredad(); }; 1- Siempre se pone la seccin privada de primero, debido a que contiene los atributos datos. 2- Poner la seccin publica de segundo debido a que las funciones miembros y los constructores son la interfaz del usuario de la clase. (153)

Funciones miembro: Las funciones miembro son funciones que se incluyen dentro de una clase, estos son llamados tambin mtodos de la clase. class producto { private: int numerodeproducto; char nombredelproducto[30]; descrip_producto[80]; float precio_producto, num_unidades; public: producto(int, char[],char[],float,float); void verproducto(); float obtenerpresio(); void actualizarproducto(int) }; La clase Punto define las coordenadas de un punto en un plano. Por cada dato se proporciona una funcin miembro que devuelve su valor y una que fija su valor. class Punto { Public: int leerX(){return x;} int leery(){return y;} void FijarX (int valx){x=valx;} void FijarY (int valy){y=valy;} private: int x; int y; }; Las funciones miembro de una clase se definen de igual modo que cualquier otra funcin, excepto que se necesita incluir el operador de resolucion de mbito (o conocido como operador de alcance unario). :: en la definicin de la funcin (en su cabecera). Formato: <TDD> <nomb_clase>::<nomb_funcion>(<lista de parametro>) {} Las declaraciones de las funciones en este ejemplo son tambin definiciones ya que se ha incluido el cuerpo de cada funcin. Si un cuerpo de la funcin consta de una nica sentencia, muchos programadores sitan el cuerpo de la funcin en la misma lnea en el nombre de la funcin. Por otra parte, si una funcin contiene mltiples sentencias, cada una debe ir en una lnea independiente. Por ejemplo:

(154)

class Punto { public: void fijarX(int valx) { if((valx>=-100)&&(valx<=100)) x=valx; else cerr<<Error: Fijarx() argumento fuera de rango; } // . . . }; Tipos de funciones miembro Las funciones miembro que pueden aparecer en la definicin de una clase se clasifican en funcin de tipo de operacin que representan. *Constructores y destructores, son funciones miembro a las que se llama automticamente cuando un objeto se crea o se destruye. *Selectores que devuelven los valores de los miembros dato. *Modificadores o mutadores que permiten a un programa cliente cambiar los contenidos de los miembros dato. *Operadores que permiten definir operadores estndar C++ para los objetos de las clases. *Iteradotes que procesan colecciones de objetos, tales como arrays y listas. Funciones en lnea y fuera de lnea Hasta ese momento, todas las funciones se han definido dentro del cuerpo de la definicin de clase. Se denominan definiciones de funcin en lnea (inline). Para el caso de funciones ms grandes, es preferible codificar solo el prototipo de la funcin dentro del bloque de la clase y codificar la implementacin de la funcin en el exterior. Esta forma permite al creador de la clase ocultar la informacin de la funcin al usuario de la clase proporcionando solo el cdigo fuente del archivo de cabecera, junto con un archivo de implementacin de la clase precompilada. class punto { public: void fijarx(int valx); Private: int x; int y; };

Programador, creador de la clase (conjunto de Implementaciones)

Usuario (interfaz)
(155)

CLASE

Ejemplo Definir una clase DiaAnyo que contiene los atributos mes y dia y una funcin miembro visualizar. El mes se registra como un valor entero en mes (1,Enero,2,Febrero,etc). El da del mes se registra en la variable entera da. Escribir un programa que haga uso de la clase y ver su salida. //uso de la clase DiaAnyo #include <iostream.h> class diaAnyo { public: void visualizar(); int mes; int dia; }; //programa que usa diaAnyo int main() { diaAnyo, hoy cumpleanyos; //se declaran dos objetos distintos de la clase diaAnyo cout<<introduzca fecha del dia de hoy: \n; cout<<introduzca el numero del mes:; cin>>hoy.mes; //lecturas cout<<Introduzca el dia del mes: ; cin>>hoy.dia; cout<<Introduzca su fecha de nacimiento: \n; cout<<introduzca el numero del mes:; cin<<cumpleanyos.dia; cout<<Introduzca el dia del mes: ; cin<<cumpleanyos.mes; cout<<la fecha de hoy es; hoy.visualizar(); //llamada a la funcin visualizar cout<<la fecha de su nacimiento es: ; cumpleanyos.visualizar(); if((hoy.mes==cumpleaos.mes)&&(hoy.dia==cumpleanyos.dia)) cout<<Feliz cumpleaos! \n; else cout<<Feliz dia! \n; return 1; } La implementacin de una funcin miembro externamente a la definicin de la clase, se hace una definicin de la funcin fuera de lnea. Su nombre debe ser precedido por el nombre de la clase y el signo de puntuacin :: denominado operador de resolucin de mbito. El operador :: permite al compilador conocer que fijarx pertenece a la clase punto y, es por consiguiente, diferente de una funcin global que pueda tener el mismo nombre o de una funcin que tenga ese nombre que puede existir en otra clase. La siguiente funcin global, por ejemplo, puede coexistir dentro del mismo mbito que Punto::FijarX (156)

void FijarX(int valx) { //. . . } El smbolo :: (operador de resolucin de mbitos) se utiliza en sentencias de ejecucin que accede a los miembros estticos de la clase. Por ejemplo, la expresin Punto::x se refiere al miembro dato esttico x de la clase Punto. La palabra reservada inline La decisin de elegir funciones en lnea y fuera de lnea es una cuestin de eficiencia en tiempo de ejecucin. Una funcin en lnea se ejecuta normalmente ms rpida, ya que el compilador inserta una copia fresca de la funcin en un programa en cada punto en que se llama la funcin. La definicin de una funcin miembro en lnea no garantiza que el compilador lo haga realmente en lnea; es un decisin que el compilador toma, basado en los tipos de las sentencias dentro de la funcin y cada compilador C++ toma esta decisin de modo diferente. Si una funcin se compila en lnea, se ahorra tiempo de la CPU al no tener que ejecutar una instruccin call para bifurcar a la funcin y no tener que ejecutar una instruccin return para retornar al programa llamador. Si una funcin es corta y se llama cientos de veces se puede apreciar un incremento en eficiencia cuando acta como funcion en lnea. Una funcin localizada fuera del bloque de la definicin de una clase se puede beneficiar de las ventajas de las funciones en lnea si esta precedida por la palabra reservada inline. inline void punto::Fijarx(int valx) { x=valx; } Dependiendo de la implementacin de su compilador, las funciones que utilizan la palabra reservada inline se pueden situar en el mismo archivo de cabecera que la definicin de la clase. Las funciones que no utilizan inline se sitan en el mismo modulo de programa, pero no el archivo de cabecera. Estas funciones se sitan en un archivo .cpp (.cc, .cxx. .c. etc.). Nombres de parmetros y funciones miembro: Al igual que sucede con los prototipos de funciones globales, se pueden omitir los nombres de parmetros de una declaracin de funciones miembro e identificar slo los tipo (TDD) de parmetros. Por ejemplo:

(157)

class punto { public: void fijarx(int); // igual a void fijarx(int nombre_de_variable); void fijarx(int *); // igual a void fijarx(int *nombre_de_apuntador); }; Sin embargo esta definicin no siempre es deseable, ya que como la definicin de clase es tambin la interfaz de la clase, una funcin miembro sin ms informacin que los TDD de parmetros no proporcionara informacin suficiente sobre como llamar a la funcin. class Demo { public: Funciondemo (int,float,char *,int); }; Si los nombres de los parmetros aparecen tanto en la declaracin como en la implementacin de la funcin, no es necesario que los nombres sean idnticos pero su orden tipo si han de serlo: class punto { public: void girar(int valx,int valy); // . . . }; void girar(int x,int y) { // . . . } Consejo: Es conveniente incluir un comentario de una o dos lneas en la declaracin de una funcin que indiquen los que hace la funcin y cuales son los valores de entrada/salida correspondientes. Implementacin de clases El cdigo fuente para la implementacin de funciones miembro de una clase es cdigo ejecutable. Se almacena, por consiguiente, en archivos de texto con extensiones .cp, .cpp, Normalmente se sita la implementacin de cada clase en un archivo correspondiente. Cada implementacin de una funcin tiene la misma estructura general. Obsrvese que una funcin comienza con una lnea de cabecera que contiene entre otras cosas, el nombre de la funcin y su cuerpo esta acotado entre una pareja de signos llave. Las clases pueden proceder de diferentes fuentes: (158)

*Se pueden declarar e implementar sus clases propias. El cdigo fuente siempre estar disponible. *Se pueden utilizar clases de hayan sido escritas por otras personas o incluso que se han comprado. En este caso, se puede disponer del cdigo fuente o estar limitado a utilizar el cdigo objeto de la implementacin. *Se puede utilizar clases de las bibliotecas del mismo programa que acompaan al software de desarrollo C++. La implementacin de estas clases se proporciona siempre como cdigo objeto. En cualquier forma, se debe disponer de las versiones de texto de las declaraciones de clase para que pueda utilizarlas su compilador. Archivos de cabecera y de clases: Las declaraciones de clases se almacenan normalmente en sus propios archivos de cdigo fuente, independientes de la implementacin de sus funciones miembro. Estos son los archivos de cabecera que se almacenan con una extensin .h o bien .hpp en el nombre del archivo. El uso de archivos de cabecera tiene un beneficio muy importante Se puede tener disponible la misma declaracin de clases a muchos programas sin nesecidad de duplicar la declaracin esta propiedad facilita la declaracin de programas en C++, el cual es un C pero con clases. Para tener acceso a los contenidos de un archivo de cabecera, un archivo que contiene la implementacin de las funciones de la clase declarada en el archivo de cabecera o un archivo que crea objetos de la clase declarada en el archivo de cabecera incluye (include), o mezcla, el archivo de cabecera utilizando una directiva de compilador, que se una instruccin al compilador que se procesa durante la compilacin. Las directivas del compilador comienzan con el signo almohadilla (#). La directiva que mezcla el contenido de un archivo de cabecera en un archivo que contiene el cdigo fuente de una funcin es: #include nombre_archivo Opciones de compilacin: Si el archivo de cabecera esta en un directorio diferente entonces se coloca la ubicacin completa en el include: Ejemplo: #include <iostream> utiliza la biblioteca de clases que soporta entrada/salida #include \mi_cabezera\cliente.h (159)

Constructores Un constructor es una funcin miembro de propsito especfico que se ejecuta automticamente cuando se crea un objeto de una clase. Un constructor sirve para inicializar los miembros dato de una clase. Un constructor tiene el mismo nombre que la propia clase. Cuando se define un constructor no se puede especificar un valor de retorno, ni incluso vid (un constructor nunca devuelve un valor). Un constructor puede, sin embargo, tomar cualquier numero de parmetros (cero o ms). Reglas: 1- El constructor tiene el mismo nombre de la clase. 2- Puede tener cero, o ms parmetros 3- No devuelve ningn valor. La clase Rectngulo tiene un constructor con cuatro parmetros: class Rectangulo { private: int LDerecho; int LSuperior; int LInferior; int LIzquierdo; public: Rectangulo(int A,int B,int C,int D); //constructor //definiciones de otras funciones miembro }; Cuando se define un objeto, se pasan los valores de los parmetros al constructor utilizando una sintaxis similar a una llamada normal de la funcin. Rectangulo rect(25,25,75,75); Esta definicin crea una instancia del objeto Rectngulo e invoca al constructor de la clase pasndole los parmetros con valores especificados. Caso particular Se puede tambin pasar los valores de los parmetros cuando se crea una instancia de una clase utilizando el operador new. Rectangulo *crect = new Rectangulo(25,25,75,75); El operador new invoca automticamente al constructor del objeto que se crea (sta es una ventaja importante de utilizar new en lugar de otros mtodos de asignacin de memoria tales como la funcin malloc). (160)

Constructor por defecto Un constructor que no tiene parmetros se llama constructor por defecto. Un constructor por defecto normalmente inicializa los miembros dato asignndoles valores por defecto. Ejemplo: El constructor por defecto en este caso inicializa x y a y en 0. class Punto { public: Punto() { X=0; Y=0; } private: int x; int y; };

//constructor por defecto

Ejemplo: Otro constructor alternativo de la clase P, que visualiza un mensaje despus de ser llamado. Punto::Punto(int valx,int valy) { fijarX(valx); fijarY(valy); cout<<Llamado el constructor de Punto .\n; } Constructores sobrecargados Al igual que se puede sobrecargar una funcin global, se puede tambin sobrecargar el constructor de la clase o cualquier otra funcin miembro de una clase excepto el destructor. De hecho los constructores sobrecargados son bastantes frecuentes; proporcionan medios alternativos para inicializar objetos nuevos de una clase. Solo un constructor se ejecuta cuando se crea un objeto, con independencia de cuantos constructores hayan sido definidos. Ejemplo: class Punto { public: Punto(); //constructor Punto(int valx,int valy); //constructor sobrecargados // }; (161)

Declaracin de un objeto punto puede llamar a cualquier constructor Punto P; Punto Q(25,50); //llamada al constructor por defecto //llamada al constructor alternativo

Constructor de copia: Existe un tipo especializado de constructor denominado constructor de copia, que se crea automticamente por el compilador. El constructor de copia se llama automticamente cuando un objeto se pasa por valor: se construye una copia local del objeto que se construye. El constructor de copia se llama tambin cuando un objeto se declara he inicializa con otro objeto del mismo tipo. Ejemplo: Punto P; Punto T(P); Punto Q=P; Por defecto, C++ construye una copia bit a bit de un objeto. Sin embargo, se puede tambin implementar el constructor de la copia y se utiliza para notificar al usuario que una copia se ha realizado, normalmente como una ayuda de depuracin. Regla: si existe un constructor alternativo, C++ no generar un constructor por defecto. Para prevenir a los usuarios de la clase de crear un objeto sin parmetros, se puede 1) Omitir el constructor por defecto o bien; 2) Hacer el constructor privado en la clase. Ejemplo: class Punto { public: Punto(int valx,int valy); private: Punto(); // }; ... Punto T; //error el constructor no esta asequible Inicializacion de miembros en constructores: No esta permitido inicializar un miembro dato de una clase cuando se define. Por consiguiente, la siguiente definicin de la clase genera errores:

(162)

class C { private: int T=0; //Error const int Cint = 25; //Error int &Dint = T; //Error // }; No tiene sentido inicializar un miembro dato dentro de una definicin de la clase, dado que la definicin de la clase indica simplemente el tipo de cada miembro dato y no reserva realmente memoria. En su lugar, se desea inicializar los miembros dato cada vez que se crea una instancia especfica de la clase. El sitio lgico para inicializar miembros datos, por consiguiente, esta dentro del constructor de la clase. El constructor de la clase inicializa los miembros dato, por consiguiente, est dentro del constructor de la clase. El constructor de la clase inicializa los miembros dato utilizando expresiones de asignacin. Sin embargo, ciertos tipos de datos especficamente constantes y referencias- no pueden ser valores asignados. Para resolver este problema, C++ proporciona una caracterstica de constructor especial Conocido como lista inicializadora de miembros que permite inicializar (en lugar de asignar) a uno o ms miembros dato. Una lista inicializadota de miembros se sita inmediatamente despus de la lista de parmetros en la definicin del constructor; consta de un carcter dos puntos, seguido por uno o ms inicializadores de miembro, separados por comas. Un inicializador de miembros consta del nombre de un miembro dato seguido por un valor inicial entre parntesis. Ejemplo: class C { private: int T; const int Cint; int &Dint; // public: C(int Param): T (Param), Cint(25), Dint(T) { //cdigo del constructor } // }; La definicin siguiente crea un objeto: C CObjeto(0);

(163)

con los miembros dato T y CInt se inicializan a 0 y 25, y el miembro dato CInt se inicializa de modo que se refiere a T. Disear y construir una clase contador que cuente cosas. (Cada vez que se produzca un suceso al contador se incrementa en 1.) El contador puede ser consultado para encontrar la cuenta actual. // contador .cpp // objeto representa una variable contador #include <iostream> class contador { private: unsigned int cuenta; //contar public: contador(){cuenta=0;} //constructor void inc_cuenta(){cuenta++;} //cuenta void leer_cuenta(){return cuenta;} //devuelve cuenta }; void main() { contador c1,c2; cout<<\nc1 = <<c1.leer_cuenta(); cout<<\nc2 = <<c2.leer_cuenta(); c1.inc_cuenta(); c2.inc_cuenta(); c2.inc_cuenta(); cout<<\nc1 = <<c1.leer_cuenta(); cout<<\nc2 = <<c2.leer_cuenta(); //visualiza de nuevo

La clase Contador tiene un elemento dato: cuenta, del tipo unsigned int (la cuenta siempre es positivo ya que unsigned acta como un valor absoluto). Tiene tres funciones miembro contador(); inc_cuenta(), que aade 1 a cuenta; y leer_cuenta(); que devuelve el valor actual de cuenta.

(164)

Destructores En una clase se puede definir una funcin miembro especial conocida como destructor, que se llama automticamente siempre que se destruye un objeto de una clase. El nombre del destructor es el mismo que el nombre de la clase, precedida por el carcter: .En este manual se le cambiara por . Al igual que un constructor, el destructor se puede definir sin ningn tipo de retorno (ni incluso void); al contrario que un constructor, no puede aceptar parmetros. Slo puede existir un destructor. Ejemplo: class Demo { private: int datos; public: Demo() {datos=0;} Demo(){} };

//constructor //destructor hall vaco

Regla: *Los destructores no tienen valor de retorno. *Tampoco tienen argumentos El uso mas frecuente del destructor es liberar memoria que fue asignada por el constructor. Si un destructor no se declara explcitamente, C++ crea un vaco automticamente. Si un objeto tiene mbito local, su destructor se llama cuando su control pasa fuera de su bloque de definicin. Si un objeto tiene mbito de archivo, el destructor se llama cuando termina el programa principal (main), Si un objeto se asign dinmicamente (utilizando new y delete), el destructor se llama cuando se invoca el operador delete. //El destructor notifica cuando se ha destruido un punto class Punto { public: Punto() { cout <<Se ha llamado al destructor de punto \n; } // . . . };

(165)

Sobrecarga de funciones (polimorfismo) C++ soporta una de las propiedades ms sobresalientes en el mundo de la programacin: la sobrecarga. La sobrecarga de funciones permite escribir y utilizar mltiples funciones con el mismo nombre, pero con diferentes lista de argumentos. La lista de argumentos es diferente si tiene un argumento con un tipo de dato distinto, si tiene un nmero diferente de argumentos, o ambos. La lista de argumentos se suele denominar signatura de la funcin. Consideremos la funcin cuadrado definida de la forma siguiente: int cuadrado(int x) { return x*x; } Si se desea implementar una funcin similar para procesar un valor long o double y no se dispone de la propiedad de sobrecarga, se pueden definir funciones independientes que utilicen un nombre diferente para cada tipo, tal como: long lcuadrado(long x); double dcuadrado(double x); Como C++ soporta sobrecarga se podran funciones sobrecargadas que tuvieran el mismo nombre y argumentos diferentes: int cuadrado(int x); long cuadrado(long x); double cuadrado(double x); En su programa basta con llamar la funcin cuadrado() con el argumento correcto long radio=42500; resultado =cuadrado(radio); El compilador C++ verifica el tipo de parmetro enviado para determinar cual es la funcin a llamar. As, en la llamada anterior, C++ llama a: long cuadrado(long x); ya que el parmetro radio es un TDD long.

(166)

Plantillas de funciones (templates) Las plantillas de funciones (funcin templates) proporcionan un mecanismo para crear una funcin genrica. Una funcin genrica es una funcin que puede soportar simultneamente diferentes tipos de datos para su parmetro o parmetros. Las plantillas son una de las grandes aportaciones de C++. La mayora de los fabricantes de compiladores (Borland, Microsoft) incorporan plantillas (templates). Las plantillas son muy tiles para los programadores y se emplean cuando se necesita utilizar la misma funcin, pero con diferentes tipos de argumentos. Los programadores que utilizan el lenguaje C resuelven este problema normalmente con macros, sin embargo, esta solucin no es eficiente. Consideremos por ejemplo la funcin abs() que devuelva el valor absoluto de su parmetro. (El valor absoluto de un numero es x si x es mayor que cero, o x si x es menor que cero.) para implementar abs(), de modo que pueda aceptar parmetros int, flota, long y double, se han de escribir cuatro funciones distinta; sin embargo, como C++soporta funciones sobrecargadas, es posible entonces sobrecargar la funcin abs para admitir los cuatro TDDs citados. int abs(int x) { return (x<0) } int abs(int x) { return (x<0) } int abs(int x) { return (x<0) } int abs(int x) { return (x<0) }

? x : x;

? x : x;

? x : x;

? x : x;

Para este tipo de problemas, sin embargo, C++ proporciona un mecanismo ms gil y potente, las plantillas de funciones. En lugar de escribir las cuatro funciones abs(), se puede escribir una nica plantilla de funcin, que se decena como: template <clase <TDD>> TDD abs(<TDD> x) { return (x<0) ? x : x; }; La palabra reservada template indica al compilador que una plantilla de funcin que se ha definido. El smbolo tipo indica al compilador que puede ser sustituido por el tipo de dato apropiado: int, float,,etc. (167)

Una plantilla de funcin tiene el siguiente formato: template <class <TDD>> declaracin de la funcin o expresado ms en detalle: template <class <TDD>> <TDD> funcion (<TDD> arg1,<TDD> arg2,) { //cuerpo de la funcin } Algunas declaraciones tpicas son: // 1era FORMA template <class T> T f(int a,T b) { //cuerpo de la funcin } // 2da FORMA template <class T> T max (T a,T b) { return a>b ? a : b; } La plantilla funcin max se declara con un nico TDD genrico T y con dos argumentos. // 3da FORMA template <class T1, class T2> T1 max (T1 a,T2 b) La plantilla funcin max se declara con dos TDD diferentes posibles. Devuelve un valor de tipo T1 y requiere dos argumentos: uno de tipo T1 y otro de tipo T2. Utilizacin de las plantillas de funciones La primera operacin a realizar consistir en disear una plantilla de funcin con uno o varios tipos genricos T. Una vez diseada la plantilla de funciones, que puede servir para manejar cualquier tipo de datos, tales como datos simples, estructuras, punteros, etc., se puede utilizar ya la plantilla de funciones con un tipo de dato especifico, con lo que se crea una funcin de plantillas (estos son trminos confusos, pero son los mismos que Stroustrup utiliza en su libro de C++). As por ejemplo, consideremos la funcin Func1()

(168)

template <class Tipo> Tipo Func1(Tipo arg1,Tipo arg2) { //cuerpo de la funcin Func1 } void main() { int i,j; float a,b; //uso de la funcin Func1() con valores enteros Func1(i,j); //uso de la funcin Func2() con variables float Func1(a,b);

El programa anterior declara una funcin plantilla Func1() y utiliza la funcin con argumentos enteros (int) o reales (float). Cuando el compilador va la funcin plantilla, no sucede nada asta que la funcin se utiliza realmente en el programa. Cuando la funcin Func1() se utiliza por primera vez, se llama con dos argumentos enteros. El compilador examina la funcin plantilla, observa que los argumentos se declaran con variables de tipo genricos y se construye una funcin correspondiente que utiliza enteros como argumentos. El compilador genera la siguiente funcin real de la funcin plantilla:

template <class Tipo> Tipo Func1(Tipo arg1,Tipo arg2)

Compilador

int Func1(int arg1, int arg2) { //cuerpo de la funcin Func1 } El tipo objeto int se utiliza en cualquier parte que la variable Tipo estaba declarada. Cuando la funcin Func1() se utiliza la segunda vez con argumentos float, el compilador genera la siguiente funcin real de la funcin plantilla: float Func1(float arg1, float arg2) { //cuerpo de la funcin Func1 }

(169)

Plantillas de funcin min y max El listado minmax.h declara dos plantillas de funciones min() y max(). //minmax.h #ifdef _ _MINMAX_H #define _ _MINMAX_H //evita inclusiones mltiples

template <class T> T max(T a,T b) { if(a>b) return a; else return b; } Template <class T> T min(T a,T b) { if(a<b) return a; else return b; } #endif Un programa que utiliza las funciones de plantilla, mediante prototipo que el compilador utiliza para escribir los cuerpos de las funciones reales: // Archivo PLANTMMX.CPP #include <iostream.h> #include minmax.h //archivo de cabecera

int max(int a,int b); //prototipo de funcin template for int double max(double a,double b); //prototipo de funcin template for double char max(char a,char b); //prototipo de funcion template for char main() { int e1=400, e2=500; double d1=2.718283, d2=3.141592; char c1='X', c2='t'; cout<<maximo(e1,e2) = <<max(e1,e2)<<endl; cout<<maximo(d1,d2) = <<max(d1,d2)<<endl; cout<<maximo(c1,c2) = <<max(c1,c2)<<endl; return; (170)

Visibilidad de una funcin El mbito de un objeto (incluido variable) es su visibilidad desde otra parte del programa y la duracin de un objeto es su tiempo de vida, lo que implica que no solo cuanto tiempo existe la variable, sino cuando se crea y cuando se hace disponible. El mbito de un objeto en C++ depende de donde se site la definicin y de los modificadores que la acompaan. En resumen, se puede decir que un objeto definido dentro de una funcin tiene mbito local (alcance local), o si se define fuera de cualquier funcin, se dice que tiene mbito global. Existen dos clases de almacenamiento en C++: auto y static. Una variable auto es aquella que tiene una duracin automtica. No existe cuando el programa comienza la ejecucin, se crea en algn punto durante la ejecucin y desaparece en algn punto antes de que el programa termine la ejecucin. Una variable static es aquella que tiene una duracin fija. El espacio para el objeto se establece en tiempo de compilacin; existe en tiempo de ejecucin y se elimina solo cuando el programa desaparece de memoria en tiempo ejecucin. prog_demo.c

Las variables globales declaradas en este nivel tienen mbito global. Son validas para todas las funciones de este archivo fuente a menos que se utilice la palabra reservada static. Funcion_a(); Las variables declaradas en este nivel son locales y tienen clase de almacenamiento auto al salir de la ejecucin, a menos que se utilice la palabra reservada static. Visible solo a esta funcin. variable global

variable local

Las variables con mbito global se denominan variables globales y son definidas externamente a la funcin (declaracin externa). Las variables globales tienen el siguiente comportamiento y atributos: Las variables globales tienen duracin esttica por defecto. El almacenamiento se utiliza en tiempo de compilacin y nunca desaparece. Por definicin, una variable global no puede ser una variable auto. Las variables globales son visibles globalmente en el archivo fuente, se pueden referenciar por cualquier funcin, a continuacin del punto de definicin del objeto. (171)

Las variables globales estn disponibles, por defecto, a otros archivos fuente. Esta operacin se denomina enlace externo. Variables locales frente a variables globales Adems de las variables globales, es preciso considerar las variables locales. Una variable local esta definida solamente dentro del bloque o cuerpo de la funcin y no tiene significado (vida) fuera de la funcin respectiva. Por consiguiente, si una funcin define una variable como local, el mbito de la variable esta protegido. La variable no se puede utilizar, cambiar o borrar desde cualquier otra funcin sin una programacin especifica mediante el paso de valores (parmetros). Una variable local es una variable que se define dentro de una funcin. Una variable global es una variable que puede ser utilizada por todas las funciones de un programa dado, incluyendo main(). Para construir variables globales en C++, se deben definir fuera de la funcin main(). En la figura siguiente la variable global es x0y la variable local es x1. La funcin puede realizar operaciones sobre x0, ya que x1 no esta definida fuera del bloque de la funcin funcion1(). Cualquier intento de utilizar x1 fuera de funcion1() producir un error.

int x0; funcion1() ; main() { } Funcion1() { int x1; }

//variable global //prototipo funcional (o de funcin)

//variable local a Funcion1 //dentro del cuerpo Funcion1

Examine ahora la figura siguiente. Esta vez existen dos funciones, ambas definen x1 como variable local. Nuevamente x0 es una variable global. La variable x1 solo se puede utilizar dentro de dos funciones. Sin embargo cualquier operacin sobre x1 dentro de funcion1() no afecta al valor de x1 dentro de funcion2() y viceversa. En otras palabras, la variable x1 de funcion1() se considera una variable independiente de la x1 de funcion2(). (172)

int x0; funcion1(); funcion2(); main() { } funcion1() { int x1; } funcion2() { int x1; }

//declaracion y definicin de variable //prototipo de funcion1 //prototipo de funcion2

Al contrario que las variables, las funciones son externas por defecto, Es preciso considerar la diferencia entre definicin de una funcin y declaracin. Si una declaracin de variable comienza con la palabra reservada extern, no se considera definicin de variable. Sin esta palabra reservada es una definicin. Cada definicin de variable es al mismo tiempo una declaracin de variable. Se puede utilizar un variable solo despus que ha sido declarada (en el mismo archivo). nicamente las definiciones de variables asignan memoria y pueden por consiguiente, contener inicializaciones. Una variable solo se define una vez, pero se puede declarar tantas veces como se desee. Una declaracin de variable a nivel global (externa a las funciones) es valida desde esa declaracin hasta el final del archivo; una declaracin en el interior de una funcin es vlida solo en esa funcin. En este punto, considere que las definiciones y declaraciones de variables globales son similares a las funciones; la diferencia principal es que se puede escribir la palabra reservada extern en declaraciones de funcin. La palabra reservada extern se puede utilizar para notificar al compilador que la declaracin del resto de la lnea no esta definida en el archivo fuente actual, pero esta localizada en otra parte. El siguiente ejemplo utiliza extern:

(173)

//main.cpp int Total; extern int Suma; extern void f(void); void main(void); //MODULO.CPP int Suma; void f(void); Utilizando la palabra reservada extern se puede acceder a smbolos externos definidos en otros mdulos. Suma y la funcin f() se declaran externas Las funciones son externas por defecto al contrario de las variables. Variables estticas y automticas: Los valores asignados a las variables locales de una funcin se destruyen cuando se termina la ejecucin de la funcin y no se puede recuperar su valor para ejecuciones posteriores de la funcin. Las variables locales se denominan variables automticas, significando que se pierden cuando termina la funcin. Se puede utilizar auto para declarar una variable: auto int ventas; Aunque las variables locales se declaran automticas, por defecto, y por consiguiente el uso de auto es opcional y, de hecho no se utiliza. Las variables estticas (static), por otra parte, mantienen su valor despus que una funcin se ha terminado. Una variable de una funcin declarada como esttica, mantiene su valor a travs de ejecuciones posteriores de la misma funcin. Haciendo una variable local como esttica, su valor, se retiene de una llamada a la siguiente de la funcin en que esta definida. Se declaran las variables estticas situando la palabra reservada static delante de la variable. Por ejemplo: static int ventas= 10000; static int dias= 500; Este valor se almacena en la variable esttica, slo la primera vez que se ejecuta la funcin. Si su valor no esta definido, el compilador almacena un cero en una variable esttica por defecto.

(174)

El siguiente programa ilustra el concepto esttico de una variable: #include <iostream.h> void Ejemplo_estatica(int); void main() { Ejemplo_estatica(1); Ejemplo_estatica(2); Ejemplo_estatica(3); } //ejemplo del uso de una variable esttica: void Ejemplo_estatica(int llamada) { static int Cuenta; cuenta=1; cout<<\n El valor de cuenta en llamada n: <<llamada<< es: <<cuenta; ++cuenta; } Al ejecutar el programa se visualiza: El valor de cuenta en llamada n:1 es: 1; El valor de cuenta en llamada n:2 es: 2; El valor de cuenta en llamada n:3 es: 3; Si quita la palabra reservada static de la declaracin de Cuenta, el resultado ser: El valor de cuenta en llamada n:1 es: 1; El valor de cuenta en llamada n:2 es: 1046; En donde no se puede predecir cual es el valor de Cuenta en llamadas posteriores. Las variables globales se pueden ocultar de otros archivos fuente utilizando el especificados de almacenamiento de clase static. Para hacer una variable global privada al archivo fuente (y por consiguiente, no til a otros mdulos de cdigo) se le hace preceder por la palabra static. Por ejemplo, las siguientes variables se declaran fuera de las funciones de un archivo fuente: static static static static static int m =25; char linea_texto[80]; int indice_linea; char buffer[MAXLOGBUF]; char *pBuffer; //prototipo de la funcin

(175)

Las variables anteriores son privadas al archive fuente. Obsrvese este ejemplo: const OFF=1; const ON=0; static unsigned char maestro = OFF; main() { // } function_a() { // } maestro se puede utilizar en function_a() como en main(), en este archivo fuente, pero no se puede declarar como extern a otro modulo fuente. Se puede hacer tambin una declaracin de funcin static. Por defecto, todas las funciones tienen enlace externo y son visibles a otros mdulos de programa. Cuando se sita la palabra reservada static delante de la declaracin de la funcin, el compilador hace privada a la funcin al modulo fuente. No se puede, entonces reutilizar el nombre de la funcin en otros mdulos fuente del programa. Compilacin separada: Hasta este momento, casi todos los ejemplos que se han expuesto en el capitulo se encontraban en un solo archivo fuente. Los programas grandes son ms fciles de gestionar si se dividen en varios archivos fuente, tambin llamados mdulos, cada uno de los cuales puede contener una o ms funciones. Estos mdulos se compilan y enlazan por separado posteriormente con un enlazador, o bien con la herramienta correspondiente del entorno de programacin. Cuando se divide un programa grande en pequeos, los nicos archivos que se recompilan son los que se han modificado. El tiempo de compilacin se reduce, dado que pequeos archivos fuente se compilan ms rpido que los grandes. Los archivos grandes son difciles de mantener y editar, ya que su impresin en un proceso lento que utilizara cantidades excesivas de papel.

(176)

En la figura siguiente se muestra como el enlazador puede construir un programa ejecutable utilizando mdulos objetos cada uno de los cuales se obtiene compilando un modelo fuente.

Archivo Fuente1

Archivo Fuente2

Archivo Fuente n

Compilador

Archivo Objeto1

Archivo Objeto2

Archivo Objeto n

Mdulos Biblioteca

Enlazador

Programa ejecutable

Cuando se tiene ms de un archivo fuente, se puede referenciar una funcin en un archivo fuente desde una funcin de otro archivo fuente. Al contrario de las variables, las funciones son externas por defecto. Si desea, por razones de legibilidad no recomendable- puede utilizar la palabra reservada con un prototipo de funcin y en una cabecera. Se puede desear restringir la visibilidad de una funcin, hacindola visible slo a otras funciones de un archivo fuente. Una razn para hacer esto es reducir la posibilidad de tener dos funciones con el mismo nombre. Otra razn es reducir el nmero de referencias externas y aumentar la velocidad del proceso del enlace. Se puede hacer una funcin no visible al exterior de un archivo fuente utilizando la palabra reservada static. Con la cabecera de la funcin y la secuencia del prototipo de funcin. Se escribe la palabra static antes del tipo de valor(TDD) devuelto por la funcin. Tales funciones no sern pblicas al enlazador, de modo que otros mdulos no tendrn acceso a ellas. La palabra reservada static, tanto para variables globales como para funciones, es til para evitar conflictos de nombres y prevenir el uso accidental de ellos. Por ejemplo, imaginemos un programa muy grande que consta de muchos mdulos, en el que se busca un error producido por una variable global; si la variable es esttica, se puede restringir su bsqueda al mdulo en que esta definida; si no es as, se extiende nuestra investigacin a los restantes mdulos en que esta declarada (con la palabra reservada extern). (177)

Como regla general, son preferibles las variables locales a las globales. Si realmente es necesario o deseable que alguna variable, sea global, es preferible hacerla esttica, lo que significa que ser local en relacin al archivo en que est especificada. Ejemplo: //MODULO.CPP #include <iostream.h> main() {

void f(int i), f(void); extern int n; //declaracin de n (no definicin) f(8); n++; q(); cout<<Fin de programa \n;

//MODULO2.CPP #include <iostream.h> int n=100; //definicin de n, tambin declaracin static int m=7; void f(int i) { n+=i+m; }

//n=n+1+i+m, n=(100+1)+8+7;

void g(void) { cout<<n =<<n<<endl; } f y g se definen en el modulo 2 y se declaran en el modulo1. Si se ejecuta el programa, se produce la salida: n=116; Fin de programa. Se puede hacer una funcin invisible fuera de un archivo fuente utilizando la palabra reservada static con la cabecera y el prototipo de la funcin.

(178)

Parmetro const de una funcin Con el objeto de aadir seguridad adicional a las funciones, se puede aadir a una descripcin de un parmetro el especificados const, que indica al compilador que slo es de lectura en el interior de la funcin. Si se intenta re_escribir en este parmetro se producir un mensaje de error de compilacin. void falso(const int item,const char &car) { item=123; //fallo en tiempo de compilacin car='A'; //fallo en tiempo de compilacin } La tabla siguiente muestra un resumen de los diferentes tipos de parmetros: Parmetro especificado como: int item const int item int &item cons int &item item pasado por: Valor Valor Referencia Referencia Cambia item dentro de la funcin: Si No Si No modifica parmetros al exterior No No Si No

Argumentos por omisin: Como una funcin tiene un cierto nmero de parmetros normalmente el mismo nmero de argumentos debe indicarse cuando se llama a la funcin. En C++, sin embargo. Una caracterstica poderosa de las funciones C++ es que ellas pueden establecer valores por omisin o ausencia (por defecto) para los parmetros. Se puede asignar argumentos por defecto a los parmetros que es un argumento por defecto a los parmetros de una funcin. Cuando se omite e argumento de un parmetro que es un argumento por defecto, se utiliza automticamente ste. La nica restriccin es que se deben incluir todas las variables desde la izquierda hasta el primer parmetro omitido. Si se pasan valores a los argumentos omitidos, se utiliza ese valor, si no se pasa un valor a un parmetro opcional, se utiliza el valor por defecto como argumento. El valor por defecto debe ser una expresin constante. El ejemplo siguiente muestra cmo utilizar argumentos por defecto, en una funcin cuyo prototipo es: void asteriscos(int fila, int col,int num, char c ='*'); Se puede llamar a la function asteriscos de dos formas equivalentes: asteriscos(4,0,40); o bien asteriscos(4,0,40,'*'); (180)

Sin embargo, si se desea cambiar el carcter utilizado por la funcin se puede escribir: asteriscos(4,0,40,'#'); En donde el argumento implcito (#) anula el carcter por omisin (*); Otro ejemplo es la funcin funcdef() char funcdef(int arg1=1,char c='A',float f_val=45.7f); Se puede llamar a funcdef con cualquiera de las siguientes sentencias: funcdef(9,'Z',91.5); funcdef(25,'W'); funcdef(90); funcdef(); //Anula los tres primeros parmetros (1) //Anula los dos primeros argumentos (2) //Anula el primer argumento (3) //Anula los tres argumentos por defecto (4)

Las sentencias anteriores son equivalentes a: funcdef(9,'Z',91.5); funcdef(25,'W',45.7f); funcdef(90,'A',45.7f); funcdef(1,'A',45.7f); // // // // ->(1) ->(2) ->(3) ->(4)

Sin embargo, no se puede omitir un argumento a menos que se omitan todos los argumentos a su derecha. Por ejemplo, la siguiente llamada a la funcin no es correcta: funcdef( ,'Z',99.99); // ERROR!!

Se debe tener cuidado y situar cualquier argumento que tenga valores por defecto a la derecha de una funcin. f(); f(a); f(a,b); f(a,b,c); La funcin escribir_car tiene dos parmetros. El primero indica el carcter a escribir (visualizar) y el segundo indica el nmero de veces que este carcter debe escribirse: void escribir_car(char c,int num=1) { for(int i=1; i<=num;i++) cout<<c; } El parmetro num se la ha dado el valor por defecto de 1. Este valor se utilizar automticamente si se omite el argumento correspondiente en una llamada. Si no se omite el argumento, se utilizara este valor. Llamadas vlidas son: (181)

escribir_car('x',4); escribir_car('y');

//se escribe cuatro veces 'x' // se escribe una 'y'

El programa ARGDEFEC.CPP muestra cmo asignar valores por omisin a variables parmetro: // ARGDEFEC.CPP // Muestra el uso de valores de parmetros por defecto #include <iostream.h> void f(int a=10,int b=20,int c=30) { cout<<a = << a<<endl; <<b = << b<<endl; <<c = << c<<endl; } void main(void) { f(); f(1); f(1,5); f(1,2,3); cout<<Pulse Intro (Enter) para continuar; cin.get(); } Regla de construccin de argumentos por defecto 1- Los argumentos por defecto se deben pasar por valor, Un nombre de un argumento por defecto no se puede pasar por referencia. 2- Los valores de los argumentos por defecto pueden ser valores literales o definiciones const. No pueden ser variables. En otras palabras si se declara int n y a continuacin int x = n, se rechazara n como parmetro por defecto, Sin embargo n si se declara con const int n =1 entonces se acepta la declaracin. 3- Todos los argumentos por defecto deben colocarse al final en el prototipo de funcin. Despus del primer argumento por defecto, todos los argumentos posteriores deben incluir tambin valores por defecto Ejemplo: Sea la funcin: void f(int anchura,float v=3.14159,char x='*'); Las llamadas siguientes son legales: f(10); f(10,7.5); f(10,7.5,'$'); (182)

La llamada siguiente no es legal: f(10, ,'^'); Ya que se ha intentado saltar uno de los parmetros por defecto. Otro ejemplo puede ser la funcin h(): void h(int a=1, int b=2, int c=3, int d=4); Y llamadas vlidas son: h(); h(9); h(9,18); h(9,18,25); h(9,18,25,4); Y llamadas no vlidas son: h(9, , ,4); Ejemplo: void escribir_car(char c,int num=1,bool lineas_indep= false) { for(int i=1;i<num;i++) { cout<<c; if(lineas_indep) // if(lineas_indep==true) siendo una valor cout<<endl; // booleano } } Algunas llamadas vlidas son: escribir_car('x'); escribir_car('#',5); escribir_car('%',5,true); // se escribe una x // se escribe 5 # en una sola lnea // se escribe 5 % en lneas independientes

(183)

Detalles de programacin bsica Contenidos: -Ambito Variables y condicionales -Dato y funcin Pueden o no se lo mismo? -Cdigo de escape -Operadores de asignacin especiales Operadores de incrementacin y decrementacin Asignaciones booleanas -Operadores de direcciones -Operador condicional [?] -Operador coma [,] Ambito: Se entiende por el espacio, contenido interior entre un par de llaves o llamado bloque, si este bloque es vaco se le conoce como hall. Variables y condicionales Considere el siguiente cdigo: int main() { int A; if(A==1){} if(A==2){} if(A==3){} } Por ahora como es lgico A debe tener asignado por defecto cualquier valor y no se ejecutara ninguno se los condicionales es buena prctica de programacin validar las variables una vez que se declaran siempre, as: Pseudocodigo accion principal entero A; A0; leer(A). Si(A=1)entonces fin_si; Si(A=2)entonces fin_si; Si(A=3)entonces fin_si; fin_accion Las variables locales se declaran fuera de cualquier funcin y son visibles a todas las funciones. Las variables locales se declaran dentro de una funcin y pueden ser utilizadas por esa funcin. (184)

Ejemplo: int i; //variable global, ambito de programa static int j; main() { int d,e; // } //mbito de archivo

//variable local, mbito de funcin

func(int j) { if(j>3) {

} // i no es visible ya.

int i; //mbito de bloque for(i=0;i<20;i++) func(i); //instruccin inmediata a for printf(HOLA MUNDO); //se escribe una sola vez fuera de dominio //de for

Obsrvese que func() es una funcin recursiva por definicin se puede llamar a si misma. Dato y funcin Pueden o no se lo mismo? Este es un dilema de la programacin, ya que asta ahora en este manual se ha definido tanto lo que es un dato y una funcin pero pueden darse casos en la programacin donde se confunden los conceptos lo cierto es que dicha confusin se plantea de la forma siguiente: Una funcin puede ser un dato (es una abstraccin de la funcin), pero una dato no puede ser una funcin Respuesta: Por lo tanto un dato y una funcin no son lo mismo. Estructura de una funcin: <TDD> <nombre _ funcin> (<lista de parmetros>) { //declaracin de variables //Cuerpo de la funcin return <expresion>; //valor devuelto } <expresin> puede ser: 0, como en el caso del int main() . Si en lugar de int main(), fuera una funcin cualquiera cuyo prototipo fuera: int funcion_suma (int a, int b); sta podra implementarse as: (185)

int funcion_suma(int a, int b) { return a+b; //siendo a+d evidentemente una expresin } Una funcin puede retornar una arrays, un puntero a una estructura, o as misma recursividad. Advertencia no se pueden declarar funciones anidadas. Una funcin puede comportarse como una accin si retorna 0. Vase la siguiente accin cuadrado() que calcula los cuadrados de numero enteros. A partir de un numero dado(n). int cuadrado(int n) { int cuadrado=0; while(cuadrado<=1000) //el cuadrado ha de ser menor o igual que 1000 cuadrado=n*n; cout<<El cuadrado de: <<n<< es <<cuadrado<<endl; return 0; } El ejemplo clsico de que una funcin puede ser vista como un dato es el siguiente: int main() { int a,b; //declaracin de datos locales a main a=b=0; //inicializacin printf(Inserte un numero entero: ); scanf(%d,&a); printf(Inserte otro numero entero: ); scanf(%d,&b); cuadrado(funcion_suma(a,b)); // funcion_suma(a,b) es vista como un dato //esta forma de programar es valida. Aunque se return 0; //calcula el cuadrado de a+b } El programa escrito es equivalente a: int main() { int a,b; //declaracin de datos locales a main a=b=0; //inicializacin printf(Inserte un numero entero: ); scanf(%d,&a); printf(Inserte otro numero entero: ); scanf(%d,&b); cuadrado(a+b); return 0; } (186)

Cdigo de escape (Tambin se conocen como secuencias de escape, vase la pgina 6 de este manual) Secuencia de escape \a \b \f \n \r \t \v \\ \? \ \000 \x \0 Significado Alarma Retroceso de espacio Avance de pgina Retorno de carro y avance de lnea Retorno de carro Tabulacin Tabulacin vertical Barra inclinada Signo de interrogacin Dobles comillas Nmero octal Nmero hexadecimal Cero,nulo (ASCII 0)

Operadores de asignacion especiales Simbolo = *= /= %= += -= ++ -** Uso a=b a*=b a/=b a%=b a+=b a-=b a++ (incremento) a-- (decremento) a** Descripcion Asigna el valor de b a a a = a*b a=a/b a=resto(a/b) a=a+b a=a-b a=a+1 a=a-1 a=a*a

Las expresiones ++a y a++ tienen el mismo efecto, como a-- y --a Operador de negacin ( ! ) : if (A!=B) se lee si a es distinto de b.

Siendo el operador (=) el de asignacin y el de (==) el de igualdad C++ no tiene datos lgicos o booleanos, como Pascal, para representar los valores verdadero(true) y falso(false). En su lugar se utiliza el tipo int para este propsito, con el valor entero 0 que representa falso y distinto de cero verdadero. Asignaciones booleanas o lgicas: Las sentencias de asignacin se pueden escribir de modo que se puede dar un valor de tipo bool.

(187)

Ejemplo: //declara una variable boleaba //asigna verdad a MayorDeEdad, se valida //asigna el valor de x==y a MayorDeEdad //si MayorDeEdadtrue; si a=b; si //a!=b entonces MayorDeEdad=false; Las sentencias siguientes asignan valores a dos tipos de variables bool, rango y hez letra. La variable rango es verdadera (true) y el valor de n esta en el rango -100 a 100, la variable es_letra es verdadera si car es una letra mayscula o minscula. rango=((n>-100)&&(n<100)); es_letra=((('A'<=car)&&(car<='Z'))||(('a'<=car)&&( 'z'<=car))); En ambas sentencias los valores que booleanos de rango y es_letra dependen de los valores que puedan tener las variables n y car. Operadores de direcciones Son operadores que permiten manipular las direcciones de los objetos: *expresion &valor_i (lvalue) objeto.miembro puntero_hacia_objeto -> miembro Operador bool MayorDeEdad; MayorDeEdad=true; MayorDeEdad=(x==y);

* & . ->

Accin Lee o modifica el valor apuntado por la expresin. Se corresponde con un puntero y el resultado es del TDD apuntado. Devuelve un puntero al objeto utilizado como operando, que debe ser un Ivalue (variable dotada de una direccin de memoria). El resultado es un puntero de tipo idntico al del operando. Permite acceder a un miembro de un objeto agregado (unin, estructura o clase) Accede a un miembro de un objeto agregado (unin, estructura o clase) apuntado por el operando de la izquierda.

Operador condicional ? El operador condicional, ?: , es un operador ternario que devuelve un resultado cuyo valor depende de la condicin comprobada. Tiene asosiatividad a derechas. Al ser un operador ternario requiere tres operndoos. El operador condicional se utiliza para reemplazar a la sentencia if-else lgica en algunas situaciones. El formato del operador condicional es: <expresion_c> ? <expresion_v> : <expresion_f>; (188)

Se evalua la expresion_c y su valor (cero=falso, distinto de cero = verdadero) determina cul es la expresin a ejecutar; si la condicin es verdadera se ejecuta expresion_v si es falsa se ejecuta la expresion_f . La figura siguiente muestra el funcionamiento del operador condicional: (ventas>150000) ? (comisin=100) : (comisin=0); Si venta es > 150000 comisin= 100 en ejecucin: comicion=100; Otros usos del operador :? Son: n>=0 ? 1 : -1; // 1 si n es positivo, -1 si n es negativo n>=n ? m : n; // devuelve el mayor entre m y n La precedencia de ? y : es menor que la de cualquier otro operando tratado hasta ese momento. Su asociatividad es de derecha. Operador coma: El operador coma permite combinar dos o ms expresiones separadas por comas en una sola lnea. Se evala primero la expresin de la izquierda y luego las restantes expresiones de izquierda a derecha. La expresin ms a la derecha determina el resultado global. El uso del operador coma es como sigue: expresion_1, expresion_2, expresion_3,, expresion_n. Cada expresin se evala empezando desde la izquierda y continuando hacia la derecha. Por ejemplo, en: int i=10, j=25; Dado que el operador coma se asocia de izquierda a derecha, la primera variable est declarada e inicializada antes que la segunda variable j, Otros ejemplos son: i++,j++; i++,j++,k++ equivale a i++;j++; equivale a i++;j++;k++; comicion=0; si es menor que 150000 entonces comisin=0

El operador coma tiene prioridad de todos los operadores C++, y se asocia de izquierda a derecha.

(189)

El resultado de la expresin global se determina por el valor de la expresin. Por ejemplo: int i,j,resultado; int j; resultado=j=10; i=j;i++; El valor de i es 11. En primer lugar, a j se asigna el valor de 10, a continuacin a i se le asigna el valor de j. Por ultimo, i se incrementa a 11. La tcnica del operador coma permite operaciones interesantes. i=10; j=(i=12,i+8); Cuando se ejecute la seccin de cdigo anterior, j vale 20, ya que i vale 10 en la primera sentencia, en la segunda toma i el valor 12 y a sumar i=12 con(+) i=8 resulta i=20. La biblioteca estndar C++ de funciones en tiempo ejecucin incluye gran cantidad de funciones. Se agrupan por categoras, entre las que destacan: *manipulacin de caracteres *numricas *tiempo y hora *conversin de datos *bsqueda y ordenacin *etc.

(190)

Resumen de la programacin con clases *Una clase es un tipo de dato definido por el usuario que sirve para representar objetos del mundo real. *Un objeto de una clase tiene dos componentes: un conjunto de atributos y un conjunto de comportamientos (operaciones). Los atributos se llaman miembros dato y los comportamientos se llaman funciones miembro. class circulo { double x_centro, y_centro; double superficie(void); }; *Cuando se crea un nuevo tipo de clase, se debe realizar dos etapas fundamentales: determinar los atributos y el comportamiento de los objetos. *Un objeto es una instancia de una clase. *Una declaracin de una clase se divide en tres secciones: pblica, privada, protegida. La seccin pblica contiene declaraciones de los atributos y el comportamiento del objeto que son asequibles a los usuarios del objeto. Se recomienda la declaracin de los constructores en la seccin pblica. La seccin privada contiene las funciones miembro y los miembros dato que son ocultos o inasequibles a los usuarios del objeto. Estas funciones miembro y atributos dato son asequibles slo por la funcin miembro del objeto. *El acceso a los miembros de una clase se puede declarar como privado (private, por defecto), pblico(public) o protegido(protected). class circulo { public: double superficie(void); void fijar_centro(double x,double y); void leer_radio(void); double leer_radio(void); private: double centro_x,cemtro_y; double r; } Los miembros dato centro_x, centro_y y r son ejemplos de ocultacin de datos. *Una funcin definida dentro de una clase, tal como fijar_centro(), se declara inicialmente en lnea (inline). El operador de resolucin de mbito :: se utiliza par definir una funcin miembro externa a la definicin de la clase . double circulo::dar_radio(void){return r;} Las funciones definidas as no son implcitamente inline. (191)

*Existen dos mtodos fundamentales de especificar un objeto. circulo c; circulo *ptr_objeto; //se crea un objeto de tipo circulo //se crea un apuntador a un objeto

Y dos mtodos para especificar un miembro de una clase: radio = 10.0; double circulo :: ptr_miembro //miembro de la clase //puntero a un miembro

Se pueden utilizar dos operadores diferentes para acceder a miembros de una clase: 1- El operador de acceso a miembro (el operador punto) c.radio=10.0; 2- El operador de acceso a miembro de la clase (el operador flecha) ptr_objeto->radio=10.0; 3- Un operador puntero a miembro ptr_objeto radio=10.0; *Un constructor es una funcin miembro con el mismo nombre de su clase. Un constructor no puede devolver un TDD pero puede ser sobrecargado. class complejo // complejo(double a,double y); complejo(const complejo &c) Para una clase, x, un constructor con el prototipo, x::x(const x&), se conoce como constructor de copia. *Un constructor es una funcin miembro especial que se invoca cuando se crea un objeto. Se utiliza normalmente para inicializar los atributos de un objeto. Los argumentos por defecto hacen al constructor ms flexible y util. *El proceso de crear un objeto se llama instanciacin (creacin de instancia) *Una funcin miembro constante es una que no puede cambiar los atributos de sus objetos. Si se desea utilizar objetos de funcin clase const, se debe definir funciones miembro const. inline double complejo::real(void) const { return result; }

(192)

*Un destructor es una funcin miembro especial que se llama automticamente siempre que se destruye un objeto de la clase. ?complejo(); //en C++ el ? es el acento de la n que la hace

Errores de programacin frecuente en POO con clases Las facilidades en el uso de la estructura clase aumenta las posibilidades de errores. 1. Mal uso de palabras reservadas. Es un error declarar una clase sin utilizar fielmente una de las palabras reservadas class, struct o unin en la declaracin. 2. La palabra reservada class no se necesita para crear objetos de clases. Por ejemplo, se puede escribir class C { }; C c1,c2; //definiciones de objetos En lugar de: class C c1,c2; //no se nesecita class

3. Si un miembro de una clase es privado (private), se puede acceder slo por mtodos de funciones amigas de la clase. Por ejemplo, ste cdigo no es correcto: class c { int x; public: c() { x=-9999; } }; void f() { C c; cout<<c.x; }

// ERROR!!

Ya que x es privado a la clase C (por defecto) y la funcin f no es ni un mtodo ni una amiga de C

(193)

4. Uso de constructores y destructores. *No se puede especificar un tipo de retorno en un constructor o destructor, ni en su declaracin ni en su definicin. Si C es una clase, entonces no ser legal: void C::C { } //ERROR

*De igual modo, no se puede especificar ningn argumento en la definicin o declaracin de un constructor por omisin de la clase. C::C(void) //ERROR { } *Tampoco se pueden especificar argumentos, incluso void, en la declaracin o definicin del destructor de una clase. *No se pueden tener dos constructores de la misma clase con los mismos tipos de argumentos. *Un constructor de una clase C no puede tener un argumento de un tipo C, pero s puede tener un argumento de tipo referencia, C&. Este constructor es el constructor de copia. 5. Inicializadores de miembros. class C { //ERROR }; int x=5;

class C { int x; public: C()={x=5;}; };

//correcto

6. No se puede acceder a un miembro dato privado fuera de su clase, excepto a travs de una funcin amiga (friend). Por ejemplo, el cdigo: class C { int x; };

(194)

int main() { C c; c.x=10; // ERROR, x es privado en t } Contiene un error, ya que x es privado en C y por consiguiente asequible slo por los mtodos o amigas de C. 7. No se puede acceder a un miembro dato protegido (protected) fuera de su jerarqua de clases, excepto a travs de una funcin amiga. Por ejemplo: class C // clase base { protected: int x; }; class D:public C { }; int main() { C c1; c1.x=10; }

// ERROR, x es protegido

Contiene un error, ya que x solo es accesible por mtodos de C y mtodos y amigas de las clases derivadas de C, tales como D. 8. No se pueden sobrecargar ninguno de estos operadores: . * :: ?: sizeof

9. No se puede utilizar this como parmetro, ya que es una palabra reservada. Tampoco se puede utilizar en una sentencia de asignacin tal como: this = ; //this es constante ERROR

10. Un constructor de una clase C no puede esperar un argumento de tipo C: class C; { }; (195)

C::C(C c) { } C::C(C &c) { } // CORRECTO, ste cdigo es una continuacin

11. Un miembro dato static no se puede definir dentro de una clase, aunque s debe ser declarado dentro de la declaracin de la clase. class C { static int x=7; }; class D { static int x; };

// ERROR

// definicin con inicializacin 12. Los constructores o destructores no se pueden declarar static. 13. Olvido de punto y coma en definicin de clases. Las llaves {} son frecuentes en cdigo C++, y normalmente no se sita un punto y coma despus de la llave de cierre. Sin embargo, la definicin de class siempre termina en }; . Un error tpico es olvidar ese punto y coma. class Producto { public: // private: // } // olvido del punto y coma 14. Olvido de inicializacin de todos los campos de un constructor. Todo constructor necesita asegurar que todos los campos (miembros) de datos se fijen en los valores apropiados.

(196)

class Empleado { public: Empleado(); Empleado(string n); //se olvida el parmetro salario // private: string nombre; float salario; }; 15. Referencia a un atributo privado de una clase. Los identificadores declarados como atributos o funciones privados de una clase no pueden ser referenciados desde el exterior de la clase. Cualquier intento de referencia producir mensaje de error similar a: undefined symbol 16. Fallo por no incluir un archivo de cabecera requerido. Se generan numerosos mensajes de error por ese fallo de programacin ya que un archivo de cabecera contiene la definicin de un nmero de los identificadores utilizados en su programa y el mensaje ms frecuente de stos errores sra: undefined symbol 17. Fallo por definir una funcin como miembro de una clase. Este error se puede producir por varias formas: 1- Fallo al prefijar la definicin de la funcin por el nombre de su clase y el operador de resolucin de mbito (::). 2- Fallo al escribir el nombre de la funcin correctamente. 3- Omisin completa de la definicin de la funcin de la clase. En cualquiera de los casos el resultado es el mismo; un mensaje de error del compilador que indica que la funcin llamada no existe en la clase indicada. is not a member Ejemplo: Si se invoca a una funcin imprimir del objeto c1 de la clase contador en la sentencia de C++: c1.imprimir(); Aparece en el programa cliente; se visualizar el mensaje: imprimir if not a member of contador

(197)

18. Olvido de punto y coma en prototipos y cabeceras de funciones. La omisin de un punto y coma al final del prototipo de una funcin puede producir el mensaje de error: O bien: Statement missing Declaracin terminated incorrectly Ms sobre el goto El goto no es una estructura legible de programacin, es sustituible por formas mas entendibles de programacin, si se programa y a mitad de la realizacin del cdigo hay que colocar un ciclo se pueden presentar complicaciones en el hecho de que hay que cuidad el orden de las llaves y la colocacion de la comparacin o condicin a comparar y ademas de ello el tipo de condicion a comparar si es al principio o al final. Un goto solventa esta situacin de forma rapida aunque esta instruccin debe de alguna manera ser controlada, se ahorra en tiempo.

etiq1: //bloque de instrucciones goto etiq1; //ciclo indefinido

goto etiq1; //salto de linea //bloque de instrucciones 1 etiq1: //bloque de instrucciones 2

//ideal para ensamblador //etiqueta //bloque de instrucciones 1 goto etiq2; //itera, continue controlado //bloque de instrucciones opcional 2 goto etiq1; //salto de linea, break controlado //bloque de instrucciones opcional 3 goto etiq2; //repite ciclo, puede ser controlada etiq1: //etiqueta de final del ciclo etiq2:

(198)

Conclusiones El presente manual contiene informacin bsica para aprender a programar en C++ y adems comprender y gozar de las facilidades que el lenguaje C++ ofrece, el este lenguaje en materia de programacin es un excelente programa con el nico defecto de que no es un lenguaje portable, el lenguaje C++ es un lenguaje muy formal y se pueden hallar muchas formas de escribir cdigos que resuelvan problemas, si se va a disear programas para otros usuarios se tener en cuenta que ciertas funciones de C++ pueden no ser reconocidas por otros compiladores. Las funciones son la base de la construccin de programas en C++. Se utilizan funciones para subdividir problemas grandes en tareas ms pequeas. El encapsulamiento de las caractersticas en funciones, hace los programas ms fciles de mantener. El uso de funciones ayuda al programador a reducir el tamao de su programa, ya que se puede llamar repetidamente y reutilizar el cdigo dentro de una funcin. El entorno de un programa tiene cuatro tipos de mbito: de programa, archivo fuente, funcin y bloque. Una variable est asociada a uno de esos mbitos y es invisible (no accesible) desde otros mbitos. El programa C++. Un buen programa se obtiene combinando Visual C++ 6.0 con Dev C++, que es un compilador de C/C++ estndar y automticamente usa libreras del Visual C++. Comando til para el programa: [ Alt Gr+: ] sirve para tener acceso a la biblioteca del programa. Insuficiencias del manual: El manual no presenta informacin acerca la representaciones de interfaz graficas en C++, tampoco explica en profundidad el comportamiento y creacin de estructuras de almacenamiento tales como listas, arboles,etc. pero presenta material abundante sobre punteros, manejo de struct, creacin de objetos, manejo de variables, llamada a funciones. Lo cual constituyen el conocimiento bsico para iniciarse en la creacin de estructuras de listas, rboles, presenta adems un enfoque muy orientado al objeto accin, funcin que se subsana en la recopilacin III donde se explica con mas detalle lo que son las clases ntese que al comienzo de esta recopilacin se plantea un debate sobre objeto vs clases muy interesante, se explica muy poco acerca de los origenes del lenguaje C++ al principio. En fin el lenguaje C++ es un sper conjunto del lenguaje C como lo podramos catalogar y este manual se queda corto. Se omiten adems las reglas para la creacin de pseudocdigo ya que esto no forma parte del lenguaje C++, pero en algunas definiciones a manera general se tomo en cuenta las reglas de representacin del pseudocodigo por ejemplo en la recopilacin I. Tambin podra catalogarse de falla el hecho de que algunos conceptos se repitan en la obra de hecho la recopilacin III es material terico el cual esta explicado de forma practica en captulos anteriores, y en la recopilacin II aparezca material que expliquen tpicos ya explicados en la recopilacin I, como apuntadores, no obstante el manual no se diseo con el objetivo de que se lleve un orden lineal por lo que se recomienda seleccionar el material adecuado a su nesecidad de programacin y implementarlo en su programa, sin embargo el manual contiene diversas lecturas indispensables para programar en C++. (199)

Bibliografa consultada: Recopilacin hecha de: -UCV Profesores: J. Parada #1, J.Jaimes, Robinson, R. Carmona -Internet. -Grupo de investigacin UCM. -GUA DE SINTAXIS DEL LENGUAJE C++: (ESTNDAR C++ ANSI) (Fundamentos de Programacin gua de L. J. Aguilar) -Otros cursos por la Web sobre programacin en C++, -Cdigos fuentes/guas para laboratorios de C/C++ UCV. -tecnun CAMPUS TECNOLGICO DE LA UNIVERSIDAD DE NAVARRA Profesores: Pal Bustamante Iker Aguinaga Miguel Aybar Luis Olaizola

Iigo Lazacano -Programacin en Algoritmos, estructuras de datos y objetos L. Joyanes Aguilar

(200)

La clase string #include <iostream> #include <string> using namespace std; /* * inicio de la clase String * * uso de una clase string */ class String { public: String(); //constructores String(const char * const); //constructor de copia String(const String &); //destructor ~String(); //operadores sobrecargados /*operador [] que devuelve una referencia a char. Se utiliza en instrucciones como UnaCadena[3]=\'x\' */ char & operator[] (unsigned short offset); //operador [] que devuelve un char. No modifica ningun valor \"const\" char operator[] (unsigned short offset) const; String operator+ (const String &); void operator+= (const String &); String & operator= (const String &); //metodos generales unsigned short GetLen() const {return itsLen;} const char * GetString() const {return itsString;} private: //constructor privado, se utiliza unicamente desde alguna funcion interna de la clase String (unsigned short); //declaracion de variables //contiene la cadena char * itsString; //contiene la longitud de la cadena unsigned short itsLen; }; //constructor predeterminados. Crea una cadena de 0 bytes String::String() { //inicializamos la cadena itsString=new char[1]; //colocamos como primera posicion de la cadena el final de linea itsString[0]=\'\\0\'; itsLen=0;

} //convierte un array de caracteres en una cadena String::String (const char * const cString) { //strlen=devuelve la longitud de una cadena, sin contar con el caracter nulo de terminacion. itsLen=strlen(cString); itsString=new char[itsLen+1]; //llenamos la cadena con el array recibido for (unsigned short i=0;i<itsLen;i++) itsString[i]=cString[i]; itsString[itsLen]=\'\\0\'; } //constructor de copia //rhs es una referencia al mismo control String String::String (const String & rhs) { itsLen=rhs.GetLen(); itsString=new char[itsLen+1]; for (unsigned short i=0;i<itsLen;i++) itsString[i]=rhs[i]; itsString[itsLen]=\'\\0\'; } //destructor String::~String() { delete [] itsString; itsLen=0; } //operador [] sobrecargado char & String::operator[] (unsigned short offset) { if(offset>itsLen) return itsString[itsLen-1]; else return itsString[offset]; } //operador [] sobrecargado char String::operator[] (unsigned short offset) const { if(offset>itsLen) return itsString[itsLen-1]; else return itsString[offset]; } //crea una cadena nueva al agregar a la cadena actual el contenido de rhs String String::operator+ (const String & rhs)

unsigned short totalLen=itsLen+rhs.GetLen(); //utilizamos el constructor privado \"String (unsigned short);\" String temp(totalLen); unsigned short i; for (i=0;i<itsLen;i++) temp[i]=itsString[i]; for (unsigned short j=0;j<rhs.GetLen();j++,i++) temp[i]=rhs[j]; temp[totalLen]=\'\\0\'; return temp;

//crea una cadena nueva al agregar a la cadena actual el contenido de rhs. No devuelve nada, modifica el valor actual. void String::operator+= (const String & rhs) { unsigned short totalLen=itsLen+rhs.GetLen(); //utilizamos el constructor privado \"String (unsigned short);\" String temp(totalLen); unsigned short i; for (i=0;i<itsLen;i++) temp[i]=itsString[i]; for (unsigned short j=0;j<rhs.GetLen();j++,i++) temp[i]=rhs[i-itsLen]; temp[totalLen]=\'\\0\'; //modificamos el valor actual de la variable *this=temp;

//operador igual a String & String::operator= (const String & rhs) { //this es una variable que se pasa ocula y hace referencia al lado derecho de la asignacion (a=b) //comprovamos si el apuntador del lado derecho de la asignacin (this) es igual a la misma referencia // de memoria que el lado izquerdo de la asignacion. if(this==&rhs) return *this; //eliminamos la referencia actual de la cadena delete [] itsString; //cogemos la nueva longitud itsLen=rhs.GetLen(); itsString=new char[itsLen+1]; for (unsigned short i=0;i<itsLen;i++) itsString[i]=rhs[i]; itsString[itsLen]=\'\\0\'; return *this; }

//constructor privado (ayudante), solo lo utilizan los metodos de la clase // para crear una cadena nueva del tamao requerido y llena de caracteres nulos. //recibe el parametro \'len\', que indica la longitud de la cadena a crear. String::String (unsigned short len) { itsString=new char[len+1]; for (unsigned short i=0;i<=len;i++) itsString[i]=\'\\0\'; itsLen=len; } /* * fin de la clase */ int main() { //utilizamos el constructor sobrecargado: \"String(const char * const);\" para crear la variable s1 String s1(\"prueba inicial\"); cout << \"s1\\t\" << s1.GetString() << endl; //creamos una variable temporal y la inicializamos char * temp =\"Hola mundo!\"; //utilizamos el operador de copia: \"String & operator= (const String &);\" s1=temp; cout << \"s1\\t\" << s1.GetString() << endl; //definimos una variable char de 30 caracteres char tempDos[30]; //copiamos el texto \"; es grandioso estar aqui!\" en la variable tempDos strcpy(tempDos,\"; es grandioso estar aqui!\"); cout << \"tempDos\\t\" << tempDos << endl; s1+=tempDos; cout << \"s1\\t\" << s1.GetString() << endl; cout << \"s1[3]\\t\" << s1[3] << endl; //modificamos el 4 caracter por una \'x\' s1[3]=\'x\'; cout << \"s1\\t\" << s1.GetString() << endl; misma //intentamos mostrar una posicion de la cadena superior a la largada real de la

//se utilizar el operador sobrecargado [] \"char & String::operator[] (unsigned short);\" //devuelve la ultima posicin de la cadena cout << \"s1[999]\\t\" << s1[999] << endl; String s2(\"otra cadena\"); String s3; //utilizamos el operador de suma \"String operator+ (const String &);\" s3=s1+s2; cout << \"s3\\t\" << s3.GetString() << endl;

String s4; //utiliza el constructor \"String(const char * const);\" s4=\"Porque trabaja esta funcion?\"; cout << \"s4\\t\" << s4.GetString() << endl; //una cadena char normal char s5[]=\"Hola mundo!\"; cout << endl << \"s5\\t\" << s5 << endl; //modificamos el 4 valor de la cadena s5[3]=\'x\'; cout << \"s5\\t\" << s5 << endl; //cualquier posicin de memoria... puede contener cualquier caracter cout << \"s5[100]\\t\" << s5[100] << endl; } return 0;

You might also like