You are on page 1of 102

UNIVERSIDAD AUTNOMA DE GUERRERO UNIDAD ACADMICA DE INGENIERA INGENIERIA EN COMPUTACION

APUNTES DE: PROGRA MACION 1


SEVERINO FELICIANO MORALES

Estos apuntes estn destinados como material didctico que sirva de apoyo a la unidad de aprendizaje de Programacin I, del Programa Educativo de Ingeniero en Computacin. Contiene toda la fundamentacin terica, as como ejemplos donde se pueden verificar todas las instrucciones ejecutables dentro de un entorno integrado que pueda compilar programas en C++. Adems, al final se agregan varios ejemplos que se pueden compilar y ejecutar en C++.

I.

INTRODUCCIN A LA PROGRAMACIN EN C++ ANTECEDENTES DEL LENGUAJE C++ ANTECEDENTES DE PROGRAMACIN EVOLUCION DE LA PROGRAMACIN PARADIGMAS DE PROGRAMACION CLASIFICACIN DE LOS LENGUAJES DE PROGRAMACIN

II.

FUNDAMENTOS DE LA PROGRAMACIN EN C++ OPERADORES ARITMTICOS OPERADORES RALACIONALES OPERADORES LGICOS ESTRUCTURA GENERAL DE UN PROGRAMA EN LENGUAJE C++ TIPOS DE DATOS INSTRUCCIONES BSICAS DE ENTRADA Y SALIDA ENTORNO DE DESARROLLO DE PROGRAMAS EN C++
3

III. ESTRUCTURAS DE CONTROL


ESTRUCTURAS DE CONTROL SELECTIVAS ESTRUCTURAS DE CONTROL ITERATIVAS

IV. ARREGLOS Y CADENAS DE CARACTERES CARACTERISTICAS DE UN ARREGLO ARREGLOS DE UNA DIMENSION ARREGLOS DE DOS DIMENSIONES ARREGLOS DE MAS DE DOS DIMENSIONES CADENAS DE CARACTERES
V.

FUNCIONES DEFINIDAS POR EL PROGRAMADOR FUNCIONES QUE DEVUELVEN VALOR FUNCIONES VACIAS (VOID) ARGUMENTOS DE UNA FUNCION

VI. PUNTEROS

Y TIPOS DE DATOS ESTRUCTURADOS

CARACTERISTICAS DE LOS PUNTEROS

DECLARACION E INICIALIZACION DE PUNTEROS PUNTEROS A PUNTEROS ARREGLOS DE PUNTEROS ARITMETICA DE PUNTEROS ESTRUCTURAS UNIONES

I. INTRODUCCIN A LA PROGRAMACIN EN C++

ANTECEDENTES DEL LENGUAJE C++

En 1967 Martin Richards cre un lenguaje de programacin BCPL, para escribir sistemas operativos y compiladores y Ken Thompson cre el lenguaje Bbasndose en el BCPL. Con B, Thompson escribi las primeras versiones de UNIX en los laboratorios Bell durante 1970. Estos 2 lenguajes muy rsticos y dejaban muchas tareas C++ al programador. En 1972 Denis Ritchie escribe un lenguaje basado en BCPL y B con varias a lo mejoras su llam C. que La contribuyen popularidad; posterior Apareci en: Diseado por: Tipo de dato: Paradigma: multiparadigma: orientado a objetos, imperativo, programacin genrica. 1983 Bjarne Stroustrup fuerte, esttico

eficiencia del C en trminos de ejecucin y administracin de recursos lo hizo el preferido de

Implementacion GNU Compiler es: Collection, Microsoft las empresas de software que Visual C++, Borland C++ Builder, Dev-C+ diseaban sistemas operativos y +, C-Free. compiladores. Una de sus Dialectos: ISO C++, ANSI C++ principales caractersticas es su 1998, ANSI C++ 2003 independencia del hardware, lo Influido por: C, Simula cual permita inicialmente correr Ha influido: Ada, C#, Java, PHP, D, programas C en cualquier Perl plataforma con mnimas modificaciones. Pero las empresas de software comenzaron a disear versiones de C particulares que le quitaban portabilidad a los programas. Por eso, en el 1983 el ANSI cre un comit tcnico para su standarizacin. La versin aprobada junto a la ISO vi la luz en 1990 y se lo conoce como ANSI C.

En 1980 Bjarne Stroustrup en los Laboratorios Bell, comenz a experimentar con versiones mejoradas de C (C con clases) con la nica finalidad de escribir programas de simulacin orientada a eventos. El nombre de C++ fue idea de Rick Masciatti haciendo uso del operador postincremento del lenguaje y sugera que era el lenguaje que le segua a C. Este compilador fue creciendo con renovadas caractersticas que lo hacen muy original, manteniendo la compatibilidad con su antecesor C. C++ incorpora clases y funciones virtuales basndose en SIMULA67, tipos genricos y expresiones deADA, la posibilidad de declarar variables en cualquier lugar de ALGOL68, as como otras caractersticas que no existan antes: herencia mltiple, espacios en nombres, funciones virtuales puras, etc. Alex Stepanov y Adrew Koenig idearon la biblioteca STL, la cual le da a C++ una potencia nica entre los lenguajes de alto nivel. Debido a la enorme difusin de C++, y a las diferentes versiones que fueron apareciendo, las organizaciones ANSI e ISO se reunieron en 1990 para definir el Standard de este lenguaje, el cual fue aprobado en 1998. Hoy da, C++ posee una notable insercin en el mundo de las computadoras y es un de los lenguajes clsicos de programacin: tanto sistemas operativos y compiladores, como aplicaciones.

ANTECEDENTES DE LA PROGRAMACIN
Los primeros lenguajes de programacin surgieron de la idea de Charles Babagge a mediados del siglo XIX. Consista en lo que el denominaba la maquina analtica, pero que por motivos tcnicos no pudo construirse hasta mediados del siglo XX. Con el colaboro Ada Lovelace, la cual es considerada como la primera programadora de la historia, pues realizo programas para aquella supuesta maquina de Babagge, en tarjetas perforadas. Como la maquina no llego nunca a construirse, los programas de Ada, lgicamente, tampoco llegaron a ejecutarse, pero si suponen un punto de partida de la programacin.

En 1936, Turing y Post introdujeron un formalismo de manipulacin de smbolos (la denominada mquina de Turing) con el que se puede realizar cualquier cmputo que hasta ahora podemos imaginar. Esta fue una va de comunicacin entre los problemas formales de la computacin y de la matemtica. La unin permiti demostrar que no existe ninguna mquina de Turing que pueda reconocer si una sentencia es o no un teorema de un sistema lgico formal; pero tambin permiti demostrar que si un clculo puede explicitarse sin ambigedad en lenguaje natural, con ayuda de smbolos matemticos, es siempre posible programar un computadora digital capaz de realizar el clculo, siempre que la capacidad de almacenamiento de informacin sea la adecuada. Desde el punto de vista de la ingeniera, los progresos en lenguajes de programacin han sido paralelos a los diseos de las nuevas computadoras. Babbage ya escribi programas para sus mquinas, pero los desarrollos importantes tuvieron lugar, igual que en las computadoras, alrededor de la segunda guerra mundial. Cuando surgi la primera computadora, el famoso Eniac, su programacin se basaba en componentes fsicos, o sea, que se programaba, cambiando directamente el Hardware de la maquina, lo que se hacia era cambiar cables de sitio para conseguir as la programacin binaria. Los "Lenguajes Maquina" y los "Lenguajes Ensambladores" (primera y segunda generacin) son dependientes de la maquina. Cada tipo de maquina, tal como VAX de digital, tiene su propio lenguaje maquina distinto y su lenguaje ensamblador asociado. El lenguaje ensamblador es simplemente una representacin simblica del lenguaje maquina asociado, lo cual permite una programacin menos tediosa que con el anterior. Sin embargo, es necesario un conocimiento de la arquitectura mecnica subyacente para realizar una programacin efectiva en cualquiera de estos niveles lenguajes. Los lenguajes de alto nivel son normalmente fciles de aprender porque estn formados por elementos de lenguajes naturales, como el ingls. A continuacin se muestra la evolucin de los distintos lenguajes en base a las influencias que recibieron:

Ao 1951-55

Influencias y Nueva Tecnologa Hardware: Computadoras de tubos de vaco; memorias de lnea aplazada de mercurio. Mtodos: Lenguajes ensamblador; conceptos base: subprogramas, 8

estructuras de datos. Lenguajes: Uso experimental de compiladores de expresin. 1956-60 Hardware: Almacenamiento en cinta magntica; memorias de ncleo; circuitos de transistores. Mtodos: Tecnologa de compiladores inicial; gramticas BNF; optimizacin de cdigo; intrpretes; mtodos de almacenamiento dinmicos y procesamiento de listas. Lenguajes: FORTRAN, ALGOL 58, ALGOL 60, COBOL, LISP. 1961-65 Hardware: Familias de arquitecturas compatibles, almacenamiento en discos magnticos Mtodos: Sistemas operativos de multiprogramacin, compiladores de sintaxis-dirigida. Lenguajes: COBOL-61, ALGOL 60 (revisada), SNOBOL, JOVIAL, notacin APL Ao 1966-70 Influencias y Nueva Tecnologa Hardware: Aumento de tamao y velocidad y reduccin de los costes; mini computadoras, microprogramacin; circuitos integrados. Mtodos: Sistemas interactivos y tiempos-compartidos; compiladores optimizados; sistemas de escritura traductores. Lenguajes: APL, FORTRAN 66, COBOL 65, ALGOL 68, SNOBOL 4, BASIC, PL/I, SIMULA 67, ALGOL-W 1971-75 Hardware: Microcomputadores; Edad de mini computadoras; sistemas de almacenamiento pequeos; declive de las memorias de ncleo y crecimiento de memorias de semiconductores Mtodos: Verificacin de programas; programacin estructurada; inicio del crecimiento de ingeniera de software como disciplina de estudio Lenguajes: Pascal, COBOL 74, PL/I (standar), C, Scheme, Prolog 1976-80 Hardware: Microcomputadores de calidad comercial, sistemas de gran almacenamiento; computacin distribuida. Mtodos: Abstraccin de datos; semnticas formales; tcnicas de

programacin en tiempo real, concurrencia y fijos. Lenguajes: Smalltalk, Ada, FORTRAN 77, ML. Ao 1981-85 Influencias y Nueva Tecnologa Hardware: Computadores personales; primeras estaciones de trabajo; juegos de vdeo; redes de rea local; Arpanet. Mtodos: Programacin orientada a objetos; entornos interactivos; editores de sintaxis dirigida. Lenguajes: Turbo Pascal, Smalltalk-80, crecimiento de Prolog, Ada 83, Postscript. 1986-90 Hardware: Edad de microcomputadores; crecimiento de estaciones de trabajo de ingenieras; arquitectura RISC; redes globales; Internet. Mtodos: computacin cliente/servidor. Lenguajes: FORTRAN 90, C++, SML (ML Standar). 1991-95 Hardware: Estaciones de trabajo y microcomputadores mucho ms econmicos; arquitectura paralelas masivas; voz, vdeo, fax, multimedia. Mtodos: Sistemas abiertos; entorno de ventanas; Infraestructura de Informacin Nacional ("autopistas de la informacin"). Lenguajes: Ada 95, lenguajes de procesos (TCL, PERL). La evolucin de los lenguajes de programacin ha estado guiada por la evolucin de: Las computadoras y sus sistemas operativos. Las aplicaciones. Los mtodos de programacin. Los fundamento tericos. La importancia dada a la estandarizacin. Los lenguajes de programacin han evolucionado a travs de generaciones. En cada nueva generacin, van necesitndose menos instrucciones para 10

indicarle a la computadora que tarea efectuar. Es decir, un programa escrito en un lenguaje de primera generacin (maquina y/o ensamblador) puede requerir mas de 100 instrucciones; ese mismo programa requerir menos de 25 instrucciones en un lenguaje de tercera generacin (Alto nivel). Informtico.

EVOLUCION DE LA PROGRAMACIN
Sobre los ltimos 50 aos, los lenguajes de programacin han evolucionado del cdigo binario de mquina a herramientas poderosas que crean las abstracciones complejas. Es importante entender por qu los idiomas han evolucionado, y qu capacidades que los lenguajes ms nuevos nos dan. "Tan largo como no haba mquinas, programar era ningn problema; cuando tuvimos unos pocas computadoras dbiles, programar lleg a ser un problema templado y ahora que tenemos las computadoras gigantescas, programar ha llegado a ser un problema igualmente gigantesco. En este sentido que la industria electrnica no ha resuelto un solo problema, ha creado el problema de usar su producto". Primera Generacin Al desarrollarse las primeras computadoras electrnicas, se vio la necesidad de programarlas, es decir, de almacenar en memoria la informacin sobre la tarea que iban a ejecutar. Las primeras se usaban como calculadoras simples; se les indicaban los pasos de clculo, uno por uno. John Von Neumann desarroll el modelo que lleva su nombre, para describir este concepto de "programa almacenado". En este modelo, se tiene una abstraccin de la memoria como un conjunto de celdas, que almacenan simplemente nmeros. Estos nmeros pueden representar dos cosas: los datos, sobre los que va a trabajar el programa; o bien, el programa en s. Cmo es que describimos un programa como nmeros? Se tena el problema de representar las acciones que iba a realizar la computadora, y que la memoria, al estar compuesta por switches correspondientes al concepto de bit, solamente nos permita almacenar nmeros binarios. La solucin que se tom fue la siguiente: a cada accin que sea capaz de realizar nuestra computadora, asociarle un nmero, que ser su cdigo de operacin (opcode) . Por ejemplo, una calculadora programable simple podra asignar los opcodes : 1 = SUMA, 2 = RESTA, 3 = MULTIPLICA, 4 = DIVIDE. Supongamos que queremos realizar la operacin 5 * 3 + 2, en la calculadora descrita arriba. En memoria, podramos "escribir" el programa de la siguiente forma: 11

Podemos ver que con esta representacin, es simple expresar las operaciones de las que es capaz el hardware (en este caso, nuestra calculadora imaginaria), en la memoria. La descripcin y uso de los opcodes es lo que llamamos lenguaje de mquina. Es decir, la lista de cdigos que la mquina va a interpretar como instrucciones, describe las capacidades de programacin que tenemos de ella; es el lenguaje ms primitivo, depende directamente del hardware, y requiere del programador que conozca el funcionamiento de la mquina al ms bajo nivel. Los lenguajes ms primitivos fueron los lenguajes de mquina. Esto, ya que el hardware se desarroll antes del software, y adems cualquier software finalmente tiene que expresarse en el lenguaje que maneja el hardware. Segunda Generacin El primer gran avance que se dio, como ya se coment, fue la abstraccin dada por el Lenguaje Ensamblador, y con l, el nacimiento de las primeras herramientas automticas para generar el cdigo mquina. Esto redujo los errores triviales, como poda ser el nmero que corresponda a una operacin, que son sumamente engorrosos y difciles de detectar, pero fciles de cometer. Sin embargo, an aqu es fcil para el programador perderse y cometer errores de

12

lgica, pues debe bajar al nivel de la forma en que trabaja el CPU, y entender bien todo lo que sucede dentro de l. Tercera Generacin Con el desarrollo en los 50s y 60s de algoritmos de ms elevado nivel, y el aumento de poder del hardware, empezaron a entrar al uso de computadoras cientficos de otras ramas; ellos conocan mucho de Fsica, Qumica y otras ramas similares, pero no de Computacin, y por supuesto, les era sumamente complicado trabajar con lenguaje Ensamblador en vez de frmulas. As, naci el concepto de Lenguaje de Alto Nivel, con el primer compilador de FORTRAN (FORmula TRANslation), que, como su nombre indica, inici como un "simple" esfuerzo de traducir un lenguaje de frmulas, al lenguaje ensamblador y por consiguiente al lenguaje de mquina. A partir de FORTRAN, se han desarrollado innumerables lenguajes, que siguen el mismo concepto: buscar la mayor abstraccin posible, y facilitar la vida al programador, aumentando la productividad, encargndose los compiladores o intrpretes de traducir el lenguaje de alto nivel, al lenguaje de computadora. Hay que notar la existencia de lenguajes que combinan caractersticas de los de alto nivel y los de bajo nivel (es decir, Ensamblador). Mi ejemplo favorito es C: contiene estructuras de programacin de alto nivel, y la facilidad de usar libreras que tambin son caractersticas de alto nivel; sin embargo, fue diseado con muy pocas instrucciones, las cuales son sumamente sencillas, fciles de traducir al lenguaje de la mquina; y requiere de un entendimiento apropiado de cmo funciona la mquina, el uso de la memoria, etctera. Por ello, muchas personas consideramos a lenguajes como C (que fue diseado para hacer sistemas operativos), lenguajes de nivel medio.

Cuarta Generacin Los lenguajes de la cuarta generacin parecen segn las instrucciones a las de la tercera generacin. Lo nuevo de estos lenguajes son conceptos como clases, objetos y eventos que permiten soluciones ms fciles y lgicos. Lenguajes como C++, java y C# se llaman lenguajes orientadas al objeto.

13

Los lenguajes modernos, tal como C++ y Java, no slo permite las abstracciones, pero permite la implementacin impuesta de restricciones en abstracciones. La mayora de los lenguajes modernos son objetivas orientado, que permite que modele el mundo verdadero que usa mi idioma.

Quinta Generacin Como la quinta generacin estn conocidos los Lenguajes de inteligencia artificial. Han sido muy valorados al principio de las noventa - mientras ahora el desarrollo de software toma otros caminos. Lo que veremos en el futuro es menos dependencia en el idioma, y ms en el modelando herramientas, tal como el Unificado Modelando el Idioma (UML). La salida del modelando herramienta producir mucho de nuestro cdigo para nosotros; en el muy menos, producir arquitectnico y los modelos del diseo y la estructura de nuestro cdigo. Esto producir un diseo (y posiblemente cdigo) eso puede ser validado por el cliente antes de completar la implementacin y probar. Cuando los problemas diarios que resolvemos llegan a ser ms grande, nosotros tenemos cada vez menos tiempo "volver a hacer" el cdigo. Los das de decir, "acabamos de escribir una versin de Beta y el cliente entonces pueden decir nosotros lo que ellos quieren realmente," son pasados. Las organizaciones que fallan de obtener completa y corrige los requisitos de cliente antes de escribir el cdigo saldr del negocio. Por qu? Porque toma demasiado largo, y cuesta tambin mucho, para escribir cdigo dos o ms vez. Las

organizaciones que tienen un compromiso a la comprobacin y la validacin antes de producir cdigo prosperarn - los otros fallarn.

14

15

PARADIGMAS DE PROGRAMACIN
El paradigma imperativo es considerado el ms comn y est representado, por ejemplo, por el C o por BASIC. El paradigma funcional est representado por la familia de lenguajes LISP, en particular Scheme o Haskell. Definicin Terica Un paradigma est constituido por los supuestos tericos generales, las leyes y las tcnicas para su aplicacin que adoptan los miembros de una determinada comunidad cientfica. -Las leyes explcitamente establecidas y los supuestos tericos. Por ejemplo, las leyes de movimiento de Newton forman parte del paradigma newtoniano y las ecuaciones de Maxwell forman parte del paradigma que constituye la teora electromagntica clsica. -El instrumental y las tcnicas instrumentales necesarios para hacer que las leyes del paradigma se refieran al mundo real. La aplicacin en astronoma del paradigma newtoniano requiere el uso de diversos telescopios, junto con tcnicas para su utilizacin y diversas tcnicas para corregir los datos recopilados. Tipos de Paradigmas de Programacin hoy. Paradigmas Imperativo: Modelo abstracto que consiste en un gran almacenamiento de memoria donde la computadora almacena una representacin codificada de un clculo y ejecuta una secuencia de comandos que modifican el contenido de ese almacenamiento. Algoritmos + Estructura de Datos = Programa. 2. Paradigmas Procedimentales: Modelos de Desarrollo: Orientado a Objetos, a Eventos, y a Agentes. Secuencia computacional realizada etapa a etapa para resolver el problema. Su mayor dificultad reside en determinar si el valor computado es una solucin correcta del problema. 3. Paradigmas Declarativos. - Modelos de Desarrollo: Funcional, Lgico y de Flujo de Datos. Se construye sealando hechos, reglas, restricciones, ecuaciones, transformaciones y otras propiedades derivadas del conjunto de valores que configuran la solucin. 4 Paradigmas Demostrativos.- Modelos de Desarrollo: Gentico. Cuando se programa bajo un paradigma demostrativo (tambin llamada programacin por ejemplos), el programador no especifica procedimentalmente cmo construir una solucin sino que presentan soluciones de problemas similares. 5. Paradigmas Funcional: Modelo matemtico de composicin funcional donde el

16

resultado de un clculo es la entrada del siguiente, y as sucesivamente hasta que una composicin produce el valor deseado. 6. Paradigma Orientado a Objeto: disciplina de ingeniera de desarrollo y modelado de software que permite construir ms fcilmente sistemas complejos a partir de componentes individuales. Objetos + Mensajes = Programa. Los grandes paradigmas de programacin han llevado a que existan lenguajes de propsito general orientados nicamente a uno de estos paradigmas, o lenguajes que permiten, de una forma muy flexible, usar uno u otro de estos paradigmas. As mismo, los patrones de diseo, en s, no estn ligados, de forma estrecha, a un paradigma concreto, con lo que se pueden llevar a cabo, normalmente, en la mayora de lenguajes de propsito general. Los paradigmas de programacin ms importantes son:

Spaguetti: este tipo de programacin est basada en la consecucin de mandatos y rdenes en lneas consecutivas, y una serie de etiquetas o numeracin de las mismas lneas, que permitan el salto, en cualquier momento, de una parte del cdigo a otra. Lenguajes de este tipo son: Ensambladores, Basic, Logo y muchos tipos de shell script. Funcional o Procedimental: este tipo de programacin se basa en la separacin del cdigo en unidades funcionales, normalmente identificadas como verbos o acciones (abrir, cerrar, coge, eliminar, imprime, ). Los lenguajes que hacen uso de este tipo de paradigma son: PHP, Perl, C, Fortran y Pascal, entre otros. Modular: es parecido al tipo anterior, solo que las unidades funcionales se agrupan en mdulos, bajo un nombre (o jerarqua de nombres), que le permite tener una organizacin y uso ms lgico, as como seguridad y tipos de optimizacin al poder incluir solo partes o mdulos especficos al cdigo. Los lenguajes que hacen uso de la modularizacin son: PHP (versin 5.3 y superiores), Perl, Modula-2 y C (con los namespaces), entre otros. Orientada a Objetos: este tipo de programacin muestra una ideologa que se centra en los datos en s, con una nomenclatura diferente a la funcional, que incluye trminos como: clase, objeto, atributo, mtodo, herencia, etc. Los lenguajes orientados a objetos son: Smalltalk, C++, Java y Python, entre otros. Declarativo: es otra ideologa diferente a la funcional, que se usa, sobre todo, en Inteligencia Artificial. Se basa en decir qu es lo que hay que hacer, y no el cmo. En este tipo de lenguajes encajaran todos los de 4 generacin, como puede ser incluso SQL, pero los lenguajes ms comunes son: Prolog y Lisp; otros lenguajes que derivan de estos: Scheme y Clips. Orientado a la Concurrencia: en un mundo cada vez ms paralelo, donde cada proceso de servidor se ejecuta de forma paralela, pero con necesidad de combinacin con otros procesos, nace la necesidad de un paradigma de programacin que se base en la concurrencia, ms que en los dems 17

aspectos. Con esta visin hay lenguajes como: Haskell, Erlang y Scala, entre otros; que permiten hacer concurrencia de forma ms fcil. Orientado a Eventos: este tipo de programacin est ntimamente ligada al lenguaje y entorno en que se programe, ya que los eventos sern dados por el sistema en s, y su forma de tratarlos y las facilidades que se puedan conseguir vendrn determinadas, en parte, por el lenguaje que se use. Es el caso de la programacin de interfaces de usuario con Swing en Java

Un lenguaje de programacin es un lenguaje artificial que puede ser usado para controlar el comportamiento de una mquina, especialmente una computadora. Estos se componen de un conjunto de reglas sintcticas y semnticas que permiten expresar instrucciones que luego sern interpretadas. Debe distinguirse de lenguaje informtico, que es una definicin ms amplia, puesto estos incluyen otros lenguajes como son el HTML o PDF que dan formato a un texto y no es programacin en s misma. El programador es el encargado de utilizar un lenguaje de programacin para crear un conjunto de instrucciones que, al final, constituir un programa o subprograma.

CLASIFICACIN DE LOS LENGUAJES DE PROGRAMACIN


Los lenguajes de programacin se pueden clasificar atendiendo a varios criterios:

Segn el nivel de abstraccin Segn el paradigma de programacin que poseen cada uno de ellos lenguaje de ensamblador

Segn su nivel de abstraccin Lenguajes de Mquina Estn escritos en lenguajes directamente legibles por la mquina (computadora), ya que sus instrucciones son cadenas binarias (0 y 1). Da la posibilidad de cargar (transferir un programa a la memoria) sin necesidad de traduccin posterior lo que supone una velocidad de ejecucin superior, solo que con poca fiabilidad y dificultad de verificar y poner a punto los programas. Lenguajes de bajo nivel Los lenguajes de bajo nivel son lenguajes de programacin que se acercan al funcionamiento de una computadora. El lenguaje de ms bajo nivel por excelencia es el cdigo mquina. A ste le sigue el lenguaje ensamblador, ya que al programar en ensamblador se trabajan con los registros de memoria de la computadora de forma directa. Ejemplo:

18

;Lenguaje ensamblador, sintaxis Intel para procesadores x86 mov eax,1 ;mueve a al registro eax el valor 1 xor ebx, ebx ;pone en 0 el registro ebx int 80h ;llama a la interrupcin 80h (80h = 128 sistema decimal) Ejecutar ese cdigo en sistemas UNIX o basados en l equivale a una funcin exit(0) (terminar el programa retornando el valor 0)

Lenguajes de medio nivel Hay lenguajes de programacin que son considerados por algunos expertos como lenguajes de medio nivel (como es el caso del lenguaje C) al tener ciertas caractersticas que los acercan a los lenguajes de bajo nivel pero teniendo, al mismo tiempo, ciertas cualidades que lo hacen un lenguaje ms cercano al humano y, por tanto, de alto nivel. Ejemplo: /*Lenguaje C*/ /*declaracin de las funciones estandars de entrada y salida*/ #include <stdio.h> int main(int argc, char **argv) { char *p; /*creamos un puntero a un byte*/ if(argc == 1){ printf("\nIngrese un argumento al programa\n");/*imprimimos el texto*/ return 1; } p = 0x30000 /*el puntero apunta a 0x30000 */ *p = argv[1][0] /*el primer caracter del primer argumento lo copiamos a la posicin 0x30000 */ return 0; } El ejemplo es muy simple y muestra a los punteros de C, stos no son muy utilizados en lenguajes de alto nivel, pero en C s. Lenguajes de alto nivel Los lenguajes de alto nivel son normalmente fciles de aprender porque estn formados por elementos de lenguajes naturales, como el ingls. En BASIC, uno de los lenguajes de alto nivel ms conocidos, los comandos como "IF CONTADOR = 10 THEN STOP" pueden utilizarse para pedir a la computadora que pare si el CONTADOR es igual a 10. Esta forma de trabajar puede dar la sensacin de que las computadoras parecen comprender un lenguaje natural; en realidad lo hacen 19

de una forma rgida y sistemtica, sin que haya cabida, por ejemplo, para ambigedades o dobles sentidos. Ejemplo: {Lenguaje Pascal} program suma; var x,s,r:integer; {declaracin de las variables} begin {comienzo del programa principal} writeln('Ingrese 2 nmeros enteros');{imprime el texto} readln(x,s); {lee 2 nmeros y los coloca en las variables x y s} r:= x + s; {suma los 2 nmeros y coloca el resultado en r} writeln('La suma es ',r); {imrpime el resultado} readln; end.{termina el programa principal} Ese es el lenguaje Pascal, muy utilizado por principiantes al aprender a programar. Segn el paradigma de programacin Un paradigma de programacin representa un enfoque particular o filosofa para la construccin del software. No es mejor uno que otro, sino que cada uno tiene ventajas y desventajas. Dependiendo de la situacin un paradigma resulta ms apropiado que otro. Atendiendo al paradigma de programacin, se pueden clasificar los lenguajes en :

El paradigma imperativo o por procedimientos es considerado el ms comn y est representado, por ejemplo, por el C o por BASIC. El paradigma funcional est representado por la familia de lenguajes LISP (en particular Scheme), ML o Haskell. El paradigma lgico, un ejemplo es PROLOG. El paradigma orientado a objetos. Un lenguaje completamente orientado a objetos es Smalltalk.

Nota: La representacin orientada a objetos mejora la estructura de los datos y por lo tanto se ha aplicado a diferentes paradigmas como Redes de Petri, Imperativo Secuencial, Lgica de Predicados, Funcional, etc. No obstante, la manipulacin no queda fundamentalmente afectada y por lo tanto el paradigma inicial tampoco a pesar de ser re-orientado a objetos. Si bien puede seleccionarse la forma pura de estos paradigmas a la hora de programar, en la prctica es habitual que se mezclen, dando lugar a la programacin multiparadigma. Actualmente el paradigma de programacin ms usado debido a mltiples ventajas respecto a sus anteriores, es la programacin orientada a objetos.

20

Lenguajes imperativos Son los lenguajes que dan instrucciones a la computadora, es decir, ordenes. Lenguajes Funcionales Paradigma Funcional: este paradigma concibe a la computacin como la evaluacin de funciones matemticas y evita declarar y cambiar datos. En otras palabras, hace hincapi en la aplicacin de las funciones y composicin entre ellas, ms que en los cambios de estados y la ejecucin secuencial de comandos (como lo hace el paradigma procedimental). Permite resolver ciertos problemas de forma elegante y los lenguajes puramente funcionales evitan los efectos secundarios comunes en otro tipo de programaciones. Lenguajes Lgicos La computacin lgica direcciona mtodos de procesamiento basados en el razonamiento formal. Los objetos de tales razonamientos son "hechos" o reglas "if then". Para computar lgicamente se utiliza un conjunto de tales estamentos para calcular la verdad o falsedad de ese conjunto de estamentos. Un estamento es un hecho si sus tuplas verifican una serie de operaciones. Un hecho es una expresin en la que algn objeto o conjunto de objetos satisface una relacin especfica. Un regla if then es un estamento que informa acerca de conjuntos de tuplas o estamentos relacionados que pueden predecir si otras tuplas satisfacern otras relaciones. Un estamento que es probado verdadero como resultado de un proceso se dice que es una inferencia del conjunto original. Se trata por tanto de una descripcin de cmo obtener la veracidad de un estamento dado que unas reglas son verdaderas. La computacin lgica est por tanto relacionada con la automatizacin de algn conjunto de mtodos de inferencia. Lenguajes orientados a objetos La Programacin Orientada a Objetos (POO u OOP segn sus siglas en ingls) es un paradigma de programacin que usa objetos y sus interacciones para disear aplicaciones y programas de computadora. Est basado en varias tcnicas, incluyendo herencia, modularidad, polimorfismo y encapsulamiento. Su uso se populariz a principios de la dcada de 1990. Actualmente son muchos los lenguajes de programacin que soportan la orientacin a objetos.

21

La implementacin de un lenguaje es la que provee una manera de que se ejecute un programa para una determinada combinacin de software y hardware.

II.

FUNDAMENTOS DE LA PROGRAMACIN EN C++ OPERADORES ARITMTICOS

1. Los operadores de expresiones que se encuentran entre pares de parntesis se evalan primero. Adems, los parntesis pueden utilizarse para forzar el orden de evaluacin y establecer cualquier secuencia deseada por el programador. Los parntesis tienen el nivel ms alto de precedencia. 2. Las operaciones de multiplicacin, divisin y mdulo, los operadores se aplican de izquierda a derecha. Se dice que la multiplicacin, la divisin y mdulo, se encuentran en el mismo nivel de precedencia. 3. Las operaciones de suma y resta se aplican al final. Si una expresin contiene varias operaciones de suma y resta, los operadores de suma y de resta, los operadores se aplican de izquierda a derecha. La suma y la resta tienen el mismo nivel de precedencia. 1. OPERADORES ARITMETICOS Prioridad 1 2 3 4 5 T= 10 % 3 :. T =1 10 % 3 = 1 Operador () % *, / +, = Descripcin Agrupacin Modulo o Residuo Multiplicacin / Divisin Suma / resta Asignacin

3 3 10 1 2. OPERADORES RELACIONES O DE COMPARACION Descripcin Menor qu

Operador <

22

> <= >= == !

Mayor qu Menor o igual qu Mayor o igual qu Igual No igual

Tambin llamados operadores de igualdad y de relacin. Un error es confundir el operador de igualdad, ==, con el de asignacin, =, puede ocasionar errores lgicos. El operador de igualdad debe leerse como es igual que, y el operador de asignacin debe leerse recibe o recibe el valor o se le asigna el valor. Algunas personas prefieren leer el operador de igualdad como doble igualdad.
3. OPERADORES LGICOS: Se usan en combinacin con los operadores de comparacin cuando la expresin de la condicin lo requiere.

And Or Not

&& || !

if(x>10||x<0+1 1 1 2 3

ESTRUCTURA GENERAL DE UN PROGRAMA EN LENGUAJE C++


1-DIRECTIVAS DEL PREPROCESADOR Y MACROS DEL PROCESADOR (EJEMPLO) #Include iostream.h #include <conio.h> #define 2- DECLARACIONES GLOBALES PROGRAMADOR Y VARIABLES) (FUNCIONES DEFINIDAS POR EL

3- Funcin principal main Void main ( ) { -declaraciones locales -cuerpo de la funcin main (sentencias) 23

} 4-DISEO DE LAS FUNCIONES (definidas por el programador) Las declaradas en la parte superior.

TIPOS DE DATOS EN C++


TIPO char unsigned char signed char int unsigned int signed int long int float double TAMAO EN BITS 8 8 8 16 16 16 32 32 64 RANGO -127 a 127 0 a 255 -127 a 127 -32767 a 32767 0 a 65537 -32767 a 32767 -2147483647 a 2147483647 Seis dgitos de precisin Diez dgitos de precisin

INSTRUCCIONES DE ENTRADA Y SALIDA


Una instruccin de entrada (o simplemente entrada) consiste en asignar a una o ms variables, uno o ms valores (datos) recibidos desde el exterior. Normalmente, los datos son recogidos desde la entrada estndar (el teclado), pero, tambin existen otros dispositivos de entrada (el ratn, el escner,...). Una instruccin de salida (o simplemente salida) consiste en llevar hacia el exterior los valores (datos) obtenidos de la evaluacin de una lista de expresiones. Normalmente, los datos son enviados a la salida estndar (la pantalla), pero, tambin existen otros dispositivos de salida (la impresora, el plotter,...).

cin
24

Instruccin que nos permite leer entradas del exterior (el teclado es el estndar) y almacenarlas en variables.

Sintaxis: cin>>var1>>var2>>>>var n; Ejemplo: cin>>a;

cout
permite mandar la salida hacia el dispositivo de salida que por default es la pantalla, que funciona como una interfaz. Sintaxis: Cout<<cadena1<<var1<<cadena2<<var2. Ejemplo: cout<<La suma de dos nmeros es:<<suma; EJEMPLO 1: DISEE UN PROGRAMA QUE PERMITA LEER 2 NUMEROS ENTEROS Y REPORTE COMO RESULTADO LA SUMA DE ESTOS DOS EN UNA VARIABLE. #include iostream.h #include conio.h int a,b,suma; void main() { clrscr(); gotoxy(10,8); cout<<introduzca 2 numeros enteros:; cin>>a>>b; suma=a+b; 25

gotoxy(10,20); cout<<la suma de:<<a<<y<<b<<es:<<suma; getch(); }

Ejemplo 2: DISEE UN PROGRAMA QUE PERMITA LEER 3 NUMEROS Y AL FINAL LOS SUME, LOS RESTE, LOS DIVIDA Y LOS MULTIPLIQUE. #include <iostream.h> #include <conio.h> int a,b,c,d; float S,R,M,N; void main (){ cout<<"ingrese el valor de a:"; cin>>a; cout<<"ingrese el valor de b:"; cin>>b; cout<<"ingrese el valor de c:"; cin>>c; cout<<"ingrese el valor de d:"; cin>>d; S=a+b+c;

26

R=a-b-c; M=a*b*c; N=a/b/c; cout<<"El resultado de la suma de los numeros es:"; cout<<S; cout<<"El resultado de la resta de los numeros es:"; cout<<R; cout<<"El resultado de la multiplicacion de los numeros es:"; cout<<M; cout<<"El resultado de la division de los numeros es:"; cout<<N; getch (); } Otras operaciones de salida printf: Imprimir en pantalla Para utilizar la funcin printf en nuestros programas debemos incluir la directiva: #include <stdio.h> Si slo queremos imprimir una cadena basta con escribir la siguiente lnea de cdigo. printf( "Cadena" ); Como resultado muestra en pantalla: Cadena Lo que pongamos entre las comillas es lo que vamos a sacar por pantalla Si volvemos a usar otro printf, por ejemplo: #include <stdio.h> void main() { printf( "Cadena" ); printf( "Segunda" ); }

27

Otras operaciones de entrada Algo muy usual en un programa es esperar que el usuario introduzca datos por el teclado. Para ello contamos con varias posibilidades: Usar las funciones de la biblioteca estndar, crear nuestras propias interrupciones de teclado (MS-Dos) o usar funciones de alguna biblioteca diferente (como por ejemplo Allegro). Las funciones estndar estn bien para un programa sencillito. Pero cuando queremos hacer juegos por ejemplo, no suelen ser suficiente. Demasiado lentas o no nos dan todas las posibilidades que buscamos, como comprobar si hay varias teclas pulsadas. Para solucionar esto tenemos dos posibilidades: scanf El uso de scanf es muy similar al de printf con una diferencia, nos da la posibilidad de que el usuario introduzca datos en vez de mostrarlos. No nos permite mostrar texto en la pantalla, por eso si queremos mostrar un mensaje usamos un printf delante. Un ejemplo: #include <stdio.h> void main() { int num; printf( "Introduce un nmero " ); scanf( "%i", &num ); printf( "Has tecleado el nmero %i\n", num ); } Primero vamos a ver una nota de esttica, para hacer los programas un poco ms elegantes. El scanf no mueve el cursor de su posicin actual, as que en nuestro ejemplo queda: Introduce un nmero _ /* La barra horizontal indica dnde esta el cursor */ getch y getche Si lo que queremos es que el usuario introduzca un carcter por el teclado usamos las funciones getch y getche. Estas esperan a que el usuario introduzca un carcter por el teclado. La diferencia entre getche y getch es que la primera saca por pantalla la tecla que hemos pulsado y la segunda no (la e del final se refiere a echo=eco). Ejemplos: #include <stdio.h> void main() { char letra; printf( "Introduce una letra: " ); fflush( stdout ); letra = getche();

28

printf( "\nHas introducido la letra: %c", letra ); } Resultado: Introduce una letra: a Has introducido la letra: a Qu es el fflush( stdout )?. Pues bien, cuando usamos la funcin printf, no escribimos directamente en la pantalla, sino en una memoria intermedia (lo que llaman un bufer). Cuando este bufer se llena o cuando metemos un carcter '\n' es cuando se enva el texto a la pantalla.

ENTORNO DE DESARROLLO DE PROGRAMAS EN C++


Un entorno de programacin es un programa que proporciona todas las herramientas que el programador necesita para desarrollar sus programas. Estas bsicamente son: Un editor de texto para escribir el cdigo fuente. Un compilador para obtener el cdigo ejecutable. Un entorno para la ejecucin segura de los programas creados. Un depurador para corregir los errores de ejecucin. Quizs la parte ms importante de un entorno de programacin es el compilador, cuya funcin vamos a explicar a continuacin. Cuando se escribe un programa en un determinado lenguaje de programacin, el ordenador por si mismo no es capaz de ejecutarlo, pues las instrucciones que aparecen en el programa no son reconocidas por la CPU. Esta slo reconoce las instrucciones pertenecientes a su cdigo mquina. Es necesario utilizar otro programa que traduzca los programas en C++ (u otro lenguaje) al conjunto de operaciones en cdigo mquina que entienda y ejecute el ordenador. Esta es la labor del compilador. El compilador es especfico de cada lenguaje, as por ejemplo, un compilador de C++ no es capaz de compilar un programa escrito en Pascal, ni viceversa. Durante el proceso de compilacin se parte de un fichero escrito en el lenguaje de programacin elegido (al que llamaremos fichero fuente) y lo transformaremos hasta obtener el fichero que contenga las instrucciones en cdigo mquina (al que llamaremos fichero ejecutable).

29

Dev-C++, un entorno de programacin El entorno de programacin. Alguna de las ventajas que tiene Dev-C++ sobre otros entornos de programacin son las siguientes: tiene la misma interfaz que Windows, es de libre distribucin y adems es fcil de usar. Por ejemplo, Dev-C++ es una IDE (Integrated Development Environment, es decir, Entorno de Desarrollo Integrado) que facilita herramientas para la creacin y depuracin de programas en C y en C++.

III. ESTRUCUTRAS DE CONTROL

ESTRUCUTRAS DE CONTROL SELECTIVAS.


En lenguajes de programacin, las estructuras de control permiten modificar el flujo de ejecucin de las instrucciones de un programa. Con las estructuras de control se puede:

De acuerdo a una condicin, ejecutar un grupo u otro de sentencias (If-Then-Else y Select-Case) Ejecutar un grupo de sentencias mientras exista una condicin (Do-While) Ejecutar un grupo de sentencias hasta que exista una condicin (Do-Until) Ejecutar un grupo de sentencias un nmero determinado de veces (For-Next) Etc

Todas las estructuras de control tienen un nico punto de entrada y un nico punto de salida. Las estructuras de control se puede clasificar en: secuenciales, iterativas y de control avanzadas. Esto es una de las cosas que permite que la programacin se rija por los principios de la programacin estructurada. Los lenguajes de programacin modernos tienen estructuras de control similares. Bsicamente lo que vara entre las estructuras de control de los

30

diferentes lenguajes es su sintaxis, cada lenguaje tiene una sintaxis propia para expresar la estructura. Estructura if en C++ if es una estructura de control utilizada para tomar decisiones segn se cumpla una condicin (o varias) o no. Su estructura bsica es la siguiente: if(condicin/es){ accin a realizar; } else{ accin a realizar en caso de que no se cumpla; }

Veamos un ejemplo bsico para entenderlo mejor: if(edad>=18){ Comprar cerveza; } else{ imprimiir "No puedes comprar cerveza porque no tienes 18 aos"; } e incluso podemos realizar condicionales mas completas como el siguiente caso: if((edad>=18)&&(dinero>0)){ Puedes comprar cerveza porque tienes 18 y tu dinero es mayor que 0; } else{ imprimir "O no tienes dineros o no tienes los 18" ; }
Ejemplo: #include iostream.h #include conio.h

31

Int a, r; Void main() { Clrscr(); Gotoxy(10,5); cout<<introduzca un nmero:; cin>>a; r=a%2; if(r==0) { gotoxy(10,10); cout<<el numero es par; } else { gotoxy(10,10); cout<<el numero es impar; } getch(); }

Ejemplo: #include iostream.h #include conio.h Int a, b, mayor; Void main() { Clrscr(); Cout<<introduzca 2 numeros: Cin>>a>>b; If(a>=b) Mayor=a; Else Mayor=b; Cout<<el mayor de:<<a<< y <<b<<es: <<mayor; Getch(); }

Ejemplo: #include iostream.h

32

#include conio.h Int a, b, c, mayor; Void main() { clrscr(); cout<<"Programa que compara tres numeros, demostrando si son iguales o no \n\n"; cout<<"introduzca tres numeros:"; cin>>a>>b>>c; if(a==b && b==c) cout<<"Todos los numeros son iguales"; else if(a>=b) mayor=a; else if(b>=c) mayor=b; cout<<"el numero mayor es: "<<mayor; getch(); }

Estructura switch Toma distintas decisiones en funcin de distintos estados de la variable. Su sintaxis es la siguiente: switch(identificador: tipo de dato ordinal){ case valor1: sentencia(s) a ejecutar cuando la expresin tiene como valor valor1 break ; case valor2: sentencia(s) a ejecutar cuando la expresin tiene como valor valor2 break ; case valor3: sentencia(s) a ejecutar cuando la expresin tiene como valor valor3 break ; default: sentencia que se ejecutar por defecto cuando no se cumpla ninguna de las condiciones anteriores.

33

EJEMPLO: DISEE UN PROGRAMA QUE PERMITA LEER UN CARCTER DEL TECLADO, LO GUARDE EN UNA VARIABLE DE TIPO char Y POSTERIORMENTE DETECTAR SI SE PULSO UNA VOCAL EN CASO CONTRARIO DECIR QUE EL CARCTER PULSADO NO ES UNA VOCAL. #include "iostream.h" #include "conio.h" char caracter; void main () { clrscr (); cout<<"Pulse un caracter:"; caracter=getch(); switch (caracter) { case 'a': case 'A':cout<<"\n\n pulso la letra A"; break; case 'e': case 'E':cout<<endl<<endl<<"pulso la letra E"; break; case 'i': case 'I':cout<<"\n\n pulso la letra I"; break; case 'o': case 'O':cout<<"\n\n pulso la letra O"; 34

break; case 'u': case 'U':cout<<"\n\n pulso la letra U"; break; default:cout<<"\n\n la letra que pulso no es vocal"; } getch (); }

ESTRUCTURAS DE CONTROL ITERATIVAS


Ciclo for: El bucle for se usa para repetir una misma operacin un nmero determinado de veces. Su sintaxis es la siguiente: for(inicializacin(es);condicin(es);incremento(s){ sentencia a ejecutar mientras se cumpla la condicin } El bucle for esta compuesto de 3 partes: - Inicializacin(es): Se ejecuta tan solo al iniciar por primera vez el bucle. En esta parte se suele colocar la(s) variable(s) que contar el nmero de veces que se repite el bucle. - Condicin(es): Es la condicin o condiciones que se evaluarn cada vez que se inicie el bucle. Esta condicin es la que determina la duracin del bucle.

35

- incremento(s): Sirve para indicar los cambios que queremos ejecutar en las variables cada vez que se ejecuta el bucle. Un ejemplo de su uso seria el siguiente: for(i=0;i<=10;i++){ imprimir "El nmero actual es",i; } De esta forma escribira todos los nmeros contenidos entre 0 y 10. Ejemplo: Disee un programa que imprima 10 nmeros incrementados de 2 en 2 empezando por el numero 2.

#include <iostream.h> #include <conio.h> #include <iomanip.h> void main() { cout<<"programa que imprime nmeros pares: \n\n"; for(int i=1,p=2; i<=10; i++) {

cout<<setw(5)<<p; p=p+2; } getch(); }

36

#include <iostream.h> #include <conio.h> #include <iomanip.h> void main() {

cout<<"programa que imprime nmeros pares: \n\n"; for(int i=1,p=2; i<=10; i++) { cout<<p+2; } getch(); }

CICLOS ANIDADOS

Ejemplo: Disee un programa que imprima un triangulo formado por asteriscos. Se debe preguntar el tamao del triangulo es decir:

N=3 * ** ***

N=5 * ** *** **** *****

#include <iostream.h> 37

#include <conio.h> #include <iomanip.h> int n; void main() { cout<<"De que tamao desea el triangulo:"; cin>>n; for(int i=1;i<=n; i++) { for(int j=1;j<=i; j++) cout<<"*"; cout<<endl; } getch(); }

Ejemplo #include<conio.h> #include<iostream.h> #include<iomanip.h>

int n,num=1; void main () { cout<<"De que tamao desea el triangulo:";

38

cin>>n; for(int i=1;i<=n;i++) { for(int j=1;j<=i;j++) cout<<setw(5)<<num++; cout<<endl; } getch(); }

Bucles while Bucle while Este bucle se usa cuando queremos repetir la ejecucin de unas sentencias un nmero indefinido de veces. Su sintaxis es la siguiente: while(condicin){ sentencia(s) a ejecutar } Para entender mejor el uso de while nos serviremos del siguiente ejemplo: while(color != "rojo"){ color= dame un color; } Este es un ejemplo de lo que se puede hacer con while. En este caso siempre y cuando el color no sea rojo nos dir que introduzcamos un color. Ejemplo
#include <conio.h> #include <iostream.h> #include <iomanip.h> int n,i,j; void main () {

39

cout<<" De que tamao desea el cuadrado:"; cin>>n; i=1; while(i<=n) { int j=1; while(j<=n) { cout<<"* "; j++; } cout<<endl; i++; } getch(); }

Bucle do...while Este bucle se usa cuando no sabemos el nmero de veces que va a ejecutarse un bucle pero lo que si tenemos claro es que por lo menos una vez si que se ejecutara la accin. Su sintaxis es la siguiente: do{ sentencia del bucle }while(condicin) Ejemplo: #include<conio.h> #include<iostream.h> void main () { int i=0; do(i<=20) { i=i+2; cout<<i<<

40

}while(i<20); getch(); }

break Se usa para detener el bucle y dejar de interpretar el cdigo que sigue despus del break continue Sirve para volver al principio del bucle desde cualquier parte del bucle.

41

IV. ARREGLOS Y CADENAS DE CARACTERES


CARACTERISTICAS DE UN ARREGLO.
Arreglos se define como una coleccin finita, homognea y Ordenada de elementos. Finita: Todo arreglo tiene un lmite, es decir, debe determinarse cual Ser el numero mximo de elementos que podrn formar parte del Arreglo. Homognea: Todos los elementos de un arreglo son del mismo tipo o Naturaleza (todos enteros, todos booleanos, etc.- ), pero nunca una Combinacin de distintos tipos. Ordenada: Se debe determinar cual es el primer elemento, el segundo, El tercero..... Y el ensimo elemento. Un arreglo, array en ingls, es un grupo consecutivo de localidades de memoria que tienen el mismo nombre y el mismo tipo. Para referirnos a una localidad o elemento particular de un arreglo, especificamos el nombre del arreglo y la posicin del elemento dentro de ste encerrndola entre corchetes ([]). En C, el primer elemento de cualquier arreglo es el elemento cero; por lo tanto, el primer elemento del arreglo est en la posicin 0, el segundo en la posicin 1, ..., el isimo elemento esta en la posicin i-1. Los arreglos ocupan espacio de memoria. El programador especifica el tipo de cada elemento y el nmero de elementos requerido por cada arreglo, de modo que el compilador reserve la memoria necesaria. Para declarar un arreglo, se utiliza la declaracin tipo nombre_del_arreglo [tamao]; Los arreglos pueden tener mltiples dimensiones. Podemos usar un arreglo de dos dimensiones para representar: una matriz, una tabla, un tablero, etc. Un arreglo de mltiples dimensiones se declara de la siguiente forma tipo nombre_del arreglo[tamao1][tamao2]...[tamaoN]; Ventajas y desventajas de usar arreglos: Si conocemos la posicin dentro del arreglo del elemento que queremos consultar, la consulta toma un tiempo constante. Pueden ser usados para implementar otras estructuras de datos sofisticadas como pilas, colas, tablas hash. En cuanto a las dimensiones los arreglos pueden ser: Unidimensional o vector: un solo ndice Bidimensional o matriz: dos ndices Multidimensional: ms de dos ndices Diferencia con registros Las dos diferencias sustanciales entre arreglos y registro son: 1) Un arreglo puede almacenar N elementos del mismo tipo, mientras que un 42

Registro puede almacenar N elementos de distintos tipos que se llaman Campos. 2) Los componentes de un arreglo se acceden por medio de ndices, mientras Que en un registro los campos se acceden por medio de su nombre, el cual es nico. ARREGLOS DE UNA DIMENSION Un arreglo unidimensional es un tipo de datos estructurado que est formado de una coleccin finita y ordenada de datos del mismo tipo. Es la estructura natural para modelar listas de elementos iguales. El tipo de acceso a los arreglos unidimensionales es el acceso directo, es decir, podemos acceder a cualquier elemento del arreglo sin tener que consultar a elementos anteriores o posteriores, esto mediante el uso de un ndice para cada elemento del arreglo que nos da su posicin relativa. Los arreglos ocupan espacio en memoria. El programador especifica el tipo de cada elemento y el nmero de elementos que se requieren para el arreglo, de la siguiente manera:

Tipo nombreArreglo[tamaoArreglo];
Y el compilador reserva la cantidad apropiada de memoria.

ARREGLOS DE UNA DIMENSION 0 1 int A[20]; 2 3 4 19 20

float calificacin[60]; variable

Ejemplo: Disee un programa que permita leer n nmeros, los guarde en un arreglo de una dimensin de tipo entero (unidimensional), y al final imprimir el mayor.

43

#include "iostream.h" #include "conio.h" int n,i,mayor,num[100]; void main() { clrscr(); cout<<"\n de que tamao desea el arreglo:"; cin>>n; for (i=0; i<n; i++) { cout<<"\n Introduzca el numero "<<i+1<<" : "; cin>>num[i]; } mayor=num[0]; for(i=0;i<n; i++) if(num[i]>mayor) mayor=num[i]; cout<<endl<<endl; cout<<"el mayor es:"<<mayor; getch(); }

ARREGLOS DE DOS DIMENSIONES Este tipo de arreglos al igual que los anteriores es un tipo de dato estructurado, finito ordenado y homogneo. El acceso a ellos tambin es en forma directa por medio de un par de ndices.
ARREGLOS DE DOS DIMENSIONES for(i=0; i<m; i++) for(j=0; j<n; j++) cin>>a[i][j].

44

Ejemplo: int max=10, A[10][10], B[10][10], C[10][10]; int m,n,i,j; void main() { clrscr(); cout<<"De que orden desea las matrices [M,N]:"; cin>>m>>n; cout<<"\n\n matriz A:\n"; for(i=0; i<m; i++) for(j=0;j<n ; j++) {cout<<"A["<<i+1<<"]["<<j+1<<"]:"; cin>>A[i][j];} cout<<"\n\n Matriz B:\n"; for (i=0;i<m ;i++) for (j=0; j<n ; j++) { cout<<"B["<<i+1<<"]["<<j+1<<"]:"; cin>>B[i][j]; } for(i=0 ; i<m;i++) for(j=0;j<n ;j++) C[i][j]= A[i][j] + B[i][j]; cout<<"la matriz resultante es :"; int col=5,ren=2; for(i=0; i<m;i++) { for(j=0;j<n;j++) { gotoxy(col,ren); cout<<C[i][j]; col=col+5; } ren++; col=5; }

getch(); }

ARREGLOS DE MAS DE DOS DIMENSIONES

Cabe mencionar que en c++ se pueden representar arreglos con mas de dos dimensiones, desde 3 dimensiones, hasta n dimensiones

CADENA DE CARACTERES

45

En matemticas o en programacin, una cadena de caracteres, palabra, ristra de caracteres o frase (string en ingls) es una secuencia ordenada de longitud arbitraria (aunque finita) de elementos que pertenecen a un cierto alfabeto. En general, una cadena de caracteres es una sucesin de caracteres (letras, nmeros u otros signos o smbolos). Desde un punto de vista de la programacin, si no se ponen restricciones al alfabeto, una cadena podr estar formada por cualquier combinacin finita de todo el juego caracteres disponibles (las letras de la 'a' a la 'z' y de la 'A' a la 'Z', los nmeros del '0' al '9', el espacio en blanco ' ', smbolos diversos '!', '@', '%', etc). En este mismo mbito (el de la programacin), se utilizan normalmente como un tipo de dato predefinido, para palabras, frases o cualquier otra sucesin de caracteres. En este caso, se almacenan en un vector de datos, o matriz de datos de una sola fila (array en ingls). Las cadenas se pueden almacenar fsicamente:

Seguidas. Enlazada letra a letra.

Generalmente son guardados un carcter a continuacin de otro por una cuestin de eficiencia de acceso. Un caso especial de cadena es la que contiene cero caracteres, a esta cadena se la llama cadena vaca. Operaciones con cadenas Al considerar las cadenas como un tipo de datos, hay que definir (o conocer) cuales son las operaciones que podemos hacer con ellas, en principio stas podran ser muchas y llegar a ser muy sofisticadas, aqu se exponen algunas de ellas:

Asignacin: Consiste en asignarle una cadena a otra. Concatenacin: Consiste en unir dos cadenas o ms (o una cadena con un carcter) para formar una cadena de mayor tamao. Bsqueda: Consiste en localizar dentro de una cadena una subcadena ms pequea o un carcter. Extraccin: Se trata de sacar fuera de una cadena una porcin de la misma segn su posicin dentro de ella. Comparacin: Se utiliza para comparar dos cadenas

46

Representacin Una cadena suele ser representada entre comillas dobles superiores ("palabra"), mientras que un carcter de esa cadena (un char en ingls) suele ser representado entre comillas simples ('p'). Por ejemplo, en C: char c = 'a'; char str[5] = "hola"; Generalmente para acceder a un carcter en una posicin determinada se suele usar la forma variable[posicin] como cuando se accede a un vector. Para poder mostrar una comilla (") dentro de la cadena y no tener problemas con las comillas que la delimitan, se usan secuencias de escape. Esto se aplica a otros caracteres reservados o no imprimibles como el retorno de carro. No obstante, las expresiones para producir estas secuencias de escape dependen del lenguaje de programacin que se est usando. Una forma comn, en muchos lenguajes, de escapar un carcter es anteponindole un \ (sin comillas), p. e.: \" (sin comillas). Cadenas dinmicas y estticas Las cadenas pueden ser de naturaleza dinmica (pueden alterar su longitud durante el tiempo de ejecucin), o de naturaleza esttica (su longitud es fija a lo largo del tiempo de ejecucin). En este segundo caso el programador debe prever que al recorrer la cadena los ndices no se vayan de los lmites previstos (C no permite que las cadenas crezcan automticamente de forma explta, mientras que C# s). El final de la cadena se delimita de diferente manera en uno u otro caso:

Mediante un carcter de fin de cadena ("\0" en C) para las cadenas de tipo dinmico. Mediante una propiedad de la cadena que delimite su longitud (Length en C#) para las de tipo esttico.

Ejemplos de algunas operaciones comunes Asignacin: asignarle una cadena a otra char *strcpy(char [], const char[]); # en C cadena1=cadena2; # en C++

47

Concatenacin: unir dos cadenas de caracteres. $pareja = "Joshua"." y "."Lidia" # en Perl y PHP; pareja = "Luisa" & " y " & "Carmen" # en Visual Basic; pareja = "Luisa" + " y " + "Carmen"; # en C++ y Java con la clase String. strcat(cadena1,cadena2); strcat(cadena1, cadena3); # en C (Debe haber suficiente espacio en la primera) N de caracteres de una cadena int strlen(const char[]); # en C Devuelve el n de caracteres sin contar el '\0' cadena.length(); # en C++ Comparacin: Compara dos cadenas en orden lexicogrfico int strcmp(const char[], const char[]); # en C Devuelvee <0 si la 1 es menor, >0 si es mayor y 0 si son iguales cadena1==cadena2; cadena1>cadena2; etc. # en C++ Devuelve un valor de verdad Para leer una cadena de caracteres desde el teclado existe la funcin gets(), y para desplegar una cadena en pantalla se usa la funcin puts(). Los prototipos de ambas funciones se encuentran declarados en el archivo STDIO.H. Por ejemplo, el listado muestra un programa que sirve para leer y desplegar cadenas de caracteres utilizando las funciones gets() y puts(). #include <stdio.h> // Para gets() y puts() #include <conio.h> // Para clrscr() y gotoxy() #include <string.h> // Para strupr() y strlen() void main() { char nombre[31]; // Declara un arreglo de 31 caracteres char saludo1[] = "?? HOLA,"; //Constante de caracteres char saludo2[] = " !!"; clrscr(); gotoxy(20,10); puts(" Cul es tu nombre ? "); //Despliega cadena de car. gotoxy(45,10); gets(nombre); // Lee cadena de caracteres strupr(nombre); // Convierte a maysculas gotoxy(20,12); 48

puts(saludo1); gotoxy(30,12); puts(nombre); gotoxy(30+strlen(nombre),12); // Longitud de la cadena puts(saludo2); }

Adems de las funciones gets() y puts(), existe otro grupo de funciones para el manejo de cadenas de caracteres, como strlen() y strupr() utilizadas en el programa del listado 5.5. Los prototipos de estas funciones se encuentran declarados en el archivo STRING.H En la tabla 5.1 se describen brevemente algunas de las funciones para el manejo de cadenas de caracteres en el C++ de Borland, cuyos prototipos se encuentran declarados en el archivo STRING.H . FUNCIO N stpcpy DESCRIPCION Copia una cadena de caracteres en otra.Se detiene cuando encuentra el terminador nulo.

strcat Aade una cadena de caracteres a otra. strchr Busca, en una cadena, un caracter dado. strcmp Compara dos cadenas. strcmpi Macro que compara dos cadenas sin distinguir entre maysculas y minsculas. Busca segmentos que no contienen un subconjunto de un conjunto especificado de caracteres.

strcpy Copia una cadena. strcspn

strdup Copia una cadena a una nueva localidad. _strerro Genera un mensaje de error definido por el programador. r strerror Retorna el apuntador al mensaje asociado con el valor del error. stricmp Compara dos cadenas sin diferenciar entre maysculas y minsculas

strlen Determina la longitud de una cadena. strlwr Convierte las maysculas de una cadena en minsculas. strncat Aade el contenido de una cadena al final de otra. strncmp Compara parte de una cadena con parte de otra.

49

strncmp Compara parte de una cadena con parte de otra, sin distinguir i entre maysculas y minsculas. strncpy Copia un un nmero de bytes dados, desde una cadena hacia otra.

strnicm Compara parte de una cadena con parte de otra, sin distinguir p entre maysculas y minsculas. strnset strpbrk Hace que un grupo de elementos de una cadena tengan un valor dado. Busca la primera aparicin, en una cadena, de cualquier caracter de un conjunto dado.

strrchr Busca la ltima aparicin de un caracter en una cadena. strrev Invierte el orden de los caracteres de una cadena. strset Hace que los elementos de una cadena tengan un valor dado. strspn Busca en una cadena el primer segmento que es un subconjunto de un conjunto de caracteres dado.

strstr Busca en una cadena la aparicin de una subcadena dada. _strtime Convierte la hora actual a una cadena. strtod Convierte una cadena a un valor double long double. strtol Convierte una cadena a un valor long. strtoul Convierte una cadena a un valor unsigned long. strupr Convierte las minsculas de una cadena a maysculas.

Ejemplo: Este programa obtiene promedio de calificaciones, pero ademas utiliza un arreglo de nombres donde se almacenan los nombres de los alumnos. #include "conio.h" #include "iostream.h" #include "iomanip.h" int i,j,k,x,y,n_est; float prom_as[7],prom_est[50], prom_tot,cal[50][7]; char nombres[50][25]; void main() { clrscr(); gotoxy(15,2); cout<<"Calificaciones del grupo de Prog. I"; gotoxy(1,4);cout<<"Cuantos estudiantes desea capturar:"; cin>>n_est; cout<<"\n Capture los nombres \n"; 50

for(i=0; i<n_est; i++) { cout<<"\n Estudiante "<<i+1<<":"; cin>>nombres [i]; } clrscr(); gotoxy(15,2); cout<<"Calificaciones del grupo de 2 sem. T.V. "; gotoxy(1,4); cout<<" "; gotoxy(1,4); cout<<"Nom. estud."; gotoxy(18,4);cout<<"Alg.lin. Prog. cal. "; cout<<"Paq. Ingles Metod. Meca"; x=18; y=5; for(i=0; i<n_est; i++) { gotoxy(1,y); cout<<nombres[i]; for(j=0; j<7; j++) { gotoxy(x,y); cin>>cal[i][j]; x=x+9; } x=18; y++; } cout<<"\n\nPromedio por"<<"\nmateria\n\n"; float suma; for(i=0; i<n_est; i++) { suma=0.0; for(j=0; j<7; j++) suma+=cal[i][j]; prom_est[i]=suma/7; cout<<"\n"<<nombres [i]<<" Obtuvo: "<<setprecision (1)<<prom_est[i]; cout<<" De promedio"; } float suma1; for(j=0; j<7; j++) { suma1=0.0;

51

for(i=0; i<n_est; i++) suma1+=cal[i][j]; prom_as[j]=suma1/i; gotoxy(x,y+2); cout<<setprecision (1)<<prom_as[j]; x=x+9; } getch(); }

CADENA DE CARACTERES

getline Ejemplo:

incluir espacios en blanco.

#include "string.h" #include "iostream.h" #include "iomanip.h" Int longitud; Char cade[50]; Void main(); { Clrscr(); Cout<<Introduzca la cadena:; cin.getline(cade,50); // cin.get longitud=strlen(cade); cout<<\n la longitude de la cadena es:<<longitud; getch(); }

52

Ejemplo: Programa que lea nombres y los ordena alfabticamente. #include "conio.h" #include "iostream.h" #include "iomanip.h" #include "string.h" #include "stdio.h" int i,j,n; char nombres[50][25]; void main() { clrscr(); gotoxy(15,2); cout<<"Programa que ordena los nombres en orden alfabetico"; gotoxy(1,4); cout<<"\n Cuantos estudiantes desea capturar:"; cin>>n; cout<<"\n Capture los nombres \n"; for(i=0; i<n; i++) { cout<<"\n Nombre - "<<i+1<<":"; gets (nombres [i]); strupr(nombres [i]); } clrscr(); cout<<" Los nombres No ordenados son:\n"; for(i=0; i<n; i++) cout<<"\n"<<nombres[i]; cout<<"\n los nombres ordenados son:\n"; for (i=0; i<n-1 ;i++) { for (j=0 ;j<n-1; j++) { int x= strcmp (nombres[j],nombres[j+1]); if(x>0) { char aux [25]; strcpy(aux, nombres[j]); strcpy(nombres[j], nombres[j+1]); strcpy(nombres [j+1], aux);

53

} } } for (i=0 ; i<n ; i++) { cout<<"\n" << nombres[i]; } getch(); }

V.

FUNCIONES DEFINIDAS POR EL PROGRAMADOR


FUNCIONES QUE DEVUELVEN VALOR

Las funciones permiten al programador dividir un programa en mdulos. Todas las variables definidas de la funcin son variables locales; estas se conocen solo en la funcin en la que se definen. La mayora de las personas tiene una lista de parmetros que proporcionan los medios para comunicar informacin entre funciones. Los parmetros de una funcin son tambin variables locales de esa funcin. Sintaxis: Tipo_de_funcion nombre_de_la_funcion(listas de argumentos separadas por comas). [opcional]

{ ----------------. ---------------. Cuerpo de la funcin. ----------------. ---------------. } Void vacia, no regresa nada. Int regresara valor entero. Void suma(int a, int b)

long int suma(int a , int b) 54

{ Int s; S=a+b. Cout<<s; }

{ return(a+b); }

Ejemplo: Disee un programa que mediante funciones nos permita leer valores enteros y guardarlos en un arreglo de un subndice, posteriormente, imprimir un mensaje si existe o no un elemento dado dentro de ese arreglo. #include "iostream.h" #include "conio.h" enum logico{falso,verdadero}; logico encontrado; void leer_datos(); logico evaluar_elemento(int a[], int elemento); int valores[50],n; void main() { clrscr(); leer_datos(); cout<<"\n\n Que elemento desea buscar:"; int elem; cin>>elem; logico res; res=evaluar_elemento(valores,elem); if(res==falso) cout<<"\n\n el valor no existe en el arreglo"<<endl; else cout<<" El valor si existe en el arreglo"; getch(); } void leer_datos() { cout<<"\n\n Cuantos valores desea?:"; cin>>n; for (int i=0; i<n; i++) {cout<<"\n valor"<<i+1<<":"; cin>>valores[i]; } } logico evaluar_elemento(int a[], int elemento)

55

{ int i=0; logico valor=falso; while(i<n && valor==falso) { if(a[i]==elemento) valor=verdadero; i++; } return (valor); }

FUNCIONES VACIAS (VOID)


En C++, una lista de parmetros vaca se especifica mediante void o con parntesis vacios. El prototipo Void imprime(); Especifica que la funcin imprime no toma argumentos y no devuelve valor alguno. Ejemplo: #include <iostream.h> Void funcion1();//prototipo de la funcin Void funcion2(void);//prototipo de la funcin Int main() { Funcion1();//llama a la funcion1 sin argumentos Funcion2();//llama a la funcion2 sin argumentos Return 0;//indica terminacin exitosa } //la funcion1 utiliza una lista de parmetros vaca para especificar que la funcin //no recibe argumentos

56

Void funcion1(); { Cout<<la funcion1 no toma argumentos<<endl; }//fin de funcion1 //la funcion2 utiliza una lista de parmetros void para especificar que la funcin no //recibe argumentos Void funcion2(void) { Cout<<la funcion2 tampoco toma argumentos<<endl; }//fin de funcion2

Las funciones void dan una forma de emular, lo que en otros lenguajes se conocen como procedimientos (por ejemplo, en PASCAL). Se usan cuando no requiere regresar un valor. Se muestra un ejemplo que imprime los cuadrados de ciertos nmeros. void cuadrados() { int contador; for( contador=1; contador<10; contador++) printf("%d\n",contador*contador); } main() { cuadrados(); } En la funcin cuadrados no esta definido ningn parmetro, y por otra parte tampoco se emplea la sentencia return para regresar de la funcin.

ARGUMENTOS DE UNA FUNCION


No es extrao para un programa invocar una funcin de manera repetida con el mismo valor de argumento para un parmetro en particular. En tales casos, el programador puede especificar que dicho argumento, es un argumento predeterminado, y puede proporcionar un valor predeterminado para dicho argumento. Cuando el programa omite un argumento predeterminado en una llamada de funcin, el compilador rescribe la llamada e inserta el valor 57

predeterminado de dicho argumento para que se pase como un argumento a la llamada de funcin. Los argumentos predeterminados deben estar a la extrema derecha de la lista de parmetros de la funcin. Cuando uno est llamando a la funcin con dos o ms argumentos predeterminados, si un argumento omitido no es el argumento que se encuentra mas a la derecha en la lista de argumentos, entonces se deben omitir todos los argumentos a la derecha de dicho argumento.

VI. PUNTEROS Y TIPOS DE DATOS ESTRUCTURADOS


CARACTERISTICAS DE LOS PUNTEROS
En C++, los punteros tienen gran importancia y son imprescindibles para una programacin rpida y correcta. Los punteros nos otorgarn rapidez y flexibilidad a nuestro programa, logrando cosas que con variables convencionales sera impensable. Un puntero es tipo de variable especial, que se encarga de almacenar direcciones de memoria. Una direccin de memoria especifica dnde se est guardando un registro o variable en la memoria de la mquina. Son registros comnmente de 32bits, al igual que los enteros (aunque estn cambiando a 64bits) y almacenan la memoria de la misma forma que un int guarda un nmero entero. De hecho, un puntero puede almacenar una cifra comprendida entre cero y 2, lo cual le da capacidad para identificar la posicin de una variable en cualquiera de los bytes de 4Gb de RAM. Esto ser as al menos hasta que cambiemos a 64bits.

58

Como dato muy importante, el puntero debe apuntar siempre al mismo tipo de datos. Es decir, si alojamos la direccin de memoria donde est alojada "int a;", el puntero debera contener siempre direcciones de memoria de enteros. 2. Definiendo un puntero Cuando vamos a declarar una nueva variable de tipo de puntero, hemos de saber de antemano a qu tipo de datos va a apuntar. El compilador de C++ es potente y audaz, pero es imposible que sepa qu tipo de dato contiene el puntero si nosotros no lo especificamos. Por tanto, decimos que un puntero es de tipo "int" cuando este tiene que apuntar a enteros. Para crear un puntero para que apunte a enteros, deberemos hacer algo similar a declarar una variable int, slo que precederemos el nombre del puntero con un asterisco * para decirle al compilador que eso es un puntero a int y no un int en s mismo. int A; // variable entera int *pA; // puntero a entero El asterisco no tiene porqu ponerse pegado al nombre de la variable, pero lo solemos hacer as porque se escriba donde se escriba siempre tiene el mismo efecto, se aplica al elemento inmediatamente a su derecha. Es por eso que lo ponemos pegado, para evitar la siguiente confusin: int* pa,pb,pc; Aqu, puede parecer que se est aplicando al tipo de datos, y que todas las variables seran punteros. Pues no, el nico puntero es "pa", y lo dems son enteros comunes. Normalmente nadie escribe as, pero algunos programadores tienen esa costumbre que puede ser un poco liosa. En una funcin se aplica exactamente igual como argumento o como retorno de datos: int* calabaza(int *a, int b, int *c) { . . . }

59

3. Comportamiento de los punteros Los punteros son variables especiales, y no se comportan como las variables comunes en muchos aspectos. Adems, al ejercer funcionalidades tan complejas, suele llevarnos a error en muchos casos en los que funcionan como las variables comunes. Un puntero es una variable que contiene la posicin de otra, nunca su valor. Es muy comn confundir los punteros con variables que tienen el mismo valor que otras. Slo contienen un nmero, que es la direccin de memoria a la que "apuntan". Los punteros no se pueden sumar, restar, multiplicar... de la forma comn. Asimismo, las comparaciones entre ellos pueden llegar a tener comportamientos inesperados para un novato en esta caracterstica. Es muy comn entre los programadores usar como convenio la letra "p" como prefijo de un puntero: esto sirve para identificar el tipo de variable en todo momento y no perderse. Por ejemplo, tener el entero "puntos" y el puntero "pPuntos". A un puntero se le puede referenciar o de-referenciar. Cuando referenciamos una variable, lo que hacemos es extraerle la direccin de memoria para guardarla en el puntero del tipo indicado. Cuando de-referenciamos, lo que hacemos es acceder al valor almacenado en un puntero, y leer la direccin de memoria que indica. Un puntero se puede desplazar hacia adelante y hacia atrs, para que lea una regin de memoria distinta. Ejemplo: pA es un puntero a enteros y apunta a la direccin de memoria 224, si lo desplazamos un registro hacia la derecha, apuntar al siguiente entero, direccin 228. (Recuerda que un entero son 32 bits o 4 bytes) Un puntero se puede comparar con otro, para saber si ambos apuntan a la misma variable. No confundir variable con valor. Que apunten a variables que ambas contengan el mismo nmero, no significa que apunten a la misma variable. 4. Operadores de punteros Los punteros tienen dos operadores especiales, que son & y *. Tcnicamente son los operadores de referencia y de-referencia, respectivamente. Son operadores unitarios, es decir, que slo afecta a una variable y se introduce antes del nombre de tal variable. El ampersand (&), "direccin de memoria de" o operador de referencia, es lo que nos permite recoger la direccin de memoria de cualquier variable de nuestro programa.

60

El asterisco (*), "valor contenido en" o operador de de-referencia, es el que nos permitir leer y escribir los valores de las variables a las que hacamos referencia en los punteros. Cuidado, no se deben confundir estos operadores, con los operadores que se aplican en las definiciones de variables. No tiene nada que ver el & y el * de int &A, *pA; con los operadores que estamos viendo aqu.

DECLARACION E INICIALIZACION DE PUNTEROS


Declaracin e inicializacin Un puntero, como cualquier variable u objeto, adems de ser declarado (para comenzar a existir) necesita ser inicializado (darle un valor de modo controlado), lo cual se realiza mediante el operador de asignacin ('='). Desde que el puntero es declarado almacena un valor, el problema es que se trata de un valor aleatorio, intentar operar con un puntero sin haberlo inicializado es una frecuente causa de problemas. Asignacin errnea: "Cannot assign..." En primer lugar veremos un caso simple de asignacin errnea para comprender el mensaje enviado por el compilador. void main(){ int a; int* b; b = a; //Error } El programa no compila, y recibimos el mensaje de error: "Cannnot assign 'int' to 'int near*' en function main(); Hemos tratado de inicializar el puntero 'b' asignandole un valor equivocado, de otro tipo. El analisis de los mensajes de error siempre es instructivo, profundizar. 1- En primer lugar: Que es un "int near*" ?. Los punteros pueden ser clasificados como 'near' (cercano) o 'far' (lejano) de acuerdo a si la

61

direccin apuntada se encuentra en el mismo segmento que el puntero. Las principales diferencias se exponen en el siguiente cuadro. Tipo de puntero near Caractersticas Cantidad de bytes que utiliza el puntero

La direccin apuntada se encuentra dos - (offset) en el mismo segmento que el puntero Se encuentran en diferente cuatro - (segmento::offset) segmento

far

Si un programa no requiere de una gran cantidad de datos significa que pueden entrar en un solo segmento, y los punteros sern 'near' por defecto, en caso contrario el default sera 'far'. Esto es determinado directamente por el modelo de memoria utilizado por nuestro programa. 2-En segundo lugar, el mensaje nos indica una discordancia de tipos. Uno es 'int', y el otro es 'int near*', si obviamos la caracterstica de 'near' vemos que la expresin "int*" coincide con nuestra declaracin del puntero. Lo mas instructivo de esto es comprender que el asterisco pertenece al tipo (type), no al nombre ('b'). Algunos autores discuten sobre cual de las dos siguientes declaraciones es la mas adecuada para declarar un puntero: int *b; int* b; Ambas son perfectamente validas, la nica diferencia es que el primer caso se sugiere que '*' forma parte de 'b', y en el segundo que '*' forma parte del tipo. Lo recomendable es adoptar la segunda forma, la primera se presta a confundir el operador '*' con el operador de 'indirection', y es muy importante comprender que aqu no hay nada de 'indirection', es solo una declaracin de un identificador (b), ligado a un tipo (int*). Es el mensaje del compilador el que nos indica esta ltima interpretacin. Para que el programa compile sin problemas es necesario utilizar el operador '&' antes del nombre de la variable, el efecto del operador es devolver la direccin en memoria de la variable, la cual se asigna naturalmente a un puntero. void main(){ int a; int* b; 62

b = &a; }

//El puntero 'b' apunta a 'a'.

Una variable individual de tipo 'T' y un array de elementos de tipo 'T' pertenecen a tipos diferentes, no es posible la asignacin entre un entero y un array de enteros. Intentemos sin embargo tal asignacin: void main(){ int a; int b[4]; a = b; //Asignacin errnea, no compila } Lo ms interesante del ejemplo es que el mensaje de error es similar (pero inverso) al de nuestro primer ejemplo fallido: "Cannnot assign 'int near*' to 'int' en function main(); Lo cual puede resultar sorprendente, pues en el ejemplo no hemos declarado ningn puntero, solo un entero y un array de enteros. Lo que esta sucediendo es que el compilador se esta refiriendo al array de enteros como un "int near*", como un puntero. Un array y un puntero no son exactamente lo mismo, hay algunas diferencias, pero la relacin que existe entre ambos es muy estrecha y la sintaxis aplicable a ambas entidades es en gran parte idntica. Esta relacin explica que el siguiente ejemplo compile bien sin ninguna complicacin: void main(){ int a [4]; int* b; b = a; //o bien --> b = &a[0]; } Podra haberse esperado algn problema, puesto que no hemos obtenido la direccin del array con el operador '&', pero no ocurre as, el solo nombre del array es tomado como sinnimo de la direccin de su primer elemento (o puntero a su primer elemento). Opciones de inicializacin Un puntero puede ser inicializado con la direccin de memoria de un objeto, tal objeto debe pertenecer a un tipo acorde al tipo al que apunta el puntero. Puede tratarse de la direccin de un elemento de un array o de una variable individual, el operador '&' antepuesto a un objeto nos devuelve su direccin de memoria. Tambin puede utilizarse un "literal", 63

ya sea numrico, de carcter, o de otro tipo, y puede inicializarse como puntero nulo, en este caso esta permitido usar el 0, el nico entero permitido, por su equivalencia con el valor NULL Si tomamos como ejemplo el tipo "char", siguiendo al cuadro anterior, tenemos las siguientes opciones de inicializacin: Puntero inicializado a Declaracin e partir inicializacin en de: una misma lnea Un elemento char* p = &ch; char ch; Un array char cad[10]; char* p = cad; char* p = &cad[0]; Declaracin e inicializacin desdobladas char* p; p = &ch; char* p; p = cad; char* p; p = &cad[0]; char* p; p = 0; char* p; p = NULL; char* p; p = ptr; char* p; p = "casa";

Valor 0 = puntero nulo char* p = 0; Null=0 (0 es el unico valor entero que puede char* p = NULL; inicializar un puntero) Otro puntero (ya inicializado) char *ptr; Un literal de cadena "casa"; char* p = ptr; char* p = "casa";

Un literal es tratado como constante, esto es lo que permite que una funcin pueda retornar una constante sin temor a que dicho almacenamiento se pierda al salir de la funcin, un literal no es una variable 'local'. No hay obstculos para inicializar un puntero con una variable constante, por lo tanto lo mismo se aplica a literales de cualquier tipo.

Inicializacin a travs de memoria dinmica Esta modalidad se diferencia de todas las enumeradas hasta ahora y puede considerarse como la principal. Todas las formas vistas hasta aqu asignan al puntero la direccin de memoria de otra entidad (elemento, array, puntero, literal) adems del caso especial del valor NULL. Ya se ha mencionado que la declaracin de un puntero no implica la reserva de 64

memoria, salvo 2 bytes para almacenar una direccin, por esa razn podra decirse que el puntero, cuando es inicializado por otro elemento, 'vive' de la memoria que le aporta el objeto al que apunta. La reserva de memoria dinmica requiere el uso obligado de un puntero, el cual apuntara al comienzo de la zona reservada. Lo diferente aqu es que se trata del nico caso donde el puntero no necesita de otro elemento que le aporte memoria necesaria, no necesita apuntar a algn otro objeto. Cuando reservamos dinmicamente 40 bytes para un puntero a char, operaremos con el puntero 'como si' apuntara a un segundo objeto (un array de caracteres), pero tal array no existe. A pesar de no existir propiamente un segundo objeto, sigue siendo esencial, el tipo (type) segn el cual se declara el puntero, pues esto determina el modo en que el puntero nos permitir acceder a tal zona de memoria. No hay un 'objeto apuntado', pero el puntero se conduce igual que si lo hubiera. En C++ la reserva y liberacin de memoria dinmica se realiza a travs de los operadores new y delete, y su sintaxis, para un puntero de nombre 'ptr' es la siguiente: Reserva Elemento individual de tipo 'T' Array de 'n' elementos de tipo 'T' T* ptr = new T; T* ptr = new T[n]; Liberacin delete ptr; delete [] ptr;

A travs del operador new solicitamos una cierta cantidad de memoria dinmica, es posible que no exista suficiente memoria disponible, en tal caso el operador nos devolver un puntero NULL (o apuntando a 0), y es por esta razn que luego de una solicitud es recomendable inspeccionar si el puntero devuelto es nulo. Esta seria la respuesta 'clsica' a una reserva fallida de memoria dinmica, sin embargo existen diferentes compiladores que, ajustndose al standard C++ no devuelven un puntero nulo sino que lanzan una excepcin (bad_alloc). Desreferenciacin ("indirection") Un puntero almacena una direccin de memoria de alguna entidad, esto en si mismo no seria demasiado til si no fuera posible, a travs del puntero, acceder a lo que esta almacenado en esa direccin. Segn el creador de C++: La operacin fundamental de un puntero es desreferenciar, es decir, referir al objeto al que apunta el puntero." (Stroustrup, 1997). La funcin de 'desreferenciar' un puntero es llevada a cabo por el operador '*', que adems cumple otras funciones en C++. Como su papel es complementario a una de las funciones del operador '&' 65

se comenzara estudiando la relacin y diferencia de estos dos operadores. Ambos operadores tienen mas de un sentido dependiendo del contexto en que aparecen, por lo tanto son casos de sobrecarga de operadores. Veamos sus distintos usos: OPERADO R * Multiplicacin int a = 3, b=2,c; c = a * b; Usos Declaracion type puntero int n; int* p = n; Dereferencing (indirection) cout<<*p; & Operacion Bitwise AND char a=0x37; a &=0x0F; Declaracion del type referencia int a; int &b = a; Referencing cout<<&a;

El primer uso de cada operador se distingue claramente de los otros dos, derivan de C y no tienen relacin con el tema punteros. Los que figuran en segundo lugar pertenecen a la sintaxis bsica de declaracin de punteros y referencias. El papel opuesto y complementario del tercer uso de ambos operadores se podra sintetizar as: dadas las siguientes declaraciones: int v = 4; int* p = &v; El puntero 'p' es equivalente a la direccin de memoria a la que apunta. cout<<p saca en pantalla una direccin de memoria (por ej: 0x8f70fff0)

La variable 'v' es equivalente al valor que almacena cout<<v '4' saca en pantalla

Mientras que la expresin '&v' es un Mientras que la expresin '*p' es sinnimo de la direccin de sinnimo del elemento individual que memoria donde se encuentra esa se encuentra en la localidad apuntada variable por el puntero cout<<&v saca en pantalla una cout<<*p saca en pantalla '4' direccin de memoria (Ej.: 0x8f70fff0)

66

Como puede observarse, el efecto de ambos operadores es inverso, en un caso dada una localidad de memoria se accede al elemento almacenado en ella (el caso de '*'), en el otro ('&') dada una variable accedemos a la direccin de memoria donde almacena su valor. El termino usado para este efecto del operador '*' es el de 'indirection' o 'dereferencing' traducido generalmente como 'indireccion' o 'desreferenciacion'. Su sentido mas llano seria: operador que permite referirnos al elemento individual apuntado por el puntero, en lugar de la direccin en que ese elemento se encuentra almacenado. El caso especifico de un puntero a char Dadas las siguientes declaraciones e inicializaciones: char cad[] = "hola"; char* ptr = cad; 'indirection' //Aqu el '*' es un indicador de tipo, no de

El puntero 'ptr' apunta a 'cad', al char inicial de 'cad'. Veamos ahora que saldra en pantalla con 'p' y con '*p', para el caso volveremos a usar la librera "iostream.h" de C++, pues las funciones de C impondrian su formato a la salida. cout<<ptr; cout<<*ptr; //sale en pantalla: "hola" //sale en pantalla: 'h'

Lo que puede desorientar aqu es que 'ptr' no imprima en pantalla una direccin de memoria, que es lo esperable tratndose de un puntero. Se trata de una caracterstica propia de las funciones que tratan con punteros a char, y no de un rasgo diferencial de los punteros a char, estos tienen las mismas caractersticas generales de cualquier puntero. Utilizando una funcin C de "stdio.h", las lneas anteriores son equivalentes a printf("%s", ptr); printf("%c", *ptr); El funcionamiento de printf. Esta funcin, recibe como argumento un puntero a char, algo cuyo tipo es char*, es decir una direccin de memoria. En C o C++ no hay otro modo de pasar un array a una funcin que a travs de una direccin de memoria. El especificador de formato, "%s", le indica a la funcin que interprete esa direccin como siendo el comienzo de una cadena de caracteres (la 's' es de 'string'). Lo que la 67

funcin hace es interpretar los bytes, uno a uno, como indicando caracteres ASCII, y los sacara ordenadamente en pantalla hasta encontrar un '\0', sin importar donde se encuentre ese '\0' o si excede o no la capacidad del array original. En C++, el flujo de salida 'cout' y el operador de insercion '<<', no requieren de un formato especifico para sacar algo en pantalla, esto significa que imponen un formato predeterminado segn el dato enviado como parmetro. En el caso de que este parmetro sea un puntero a char imponen el formato "cadena de caracteres", exactamente igual que printf con formato "%s". Esto no es obvio, dado que se trata de un puntero podran sacarlo en pantalla como una direccin de memoria, pero no ocurre as. Es por esta razn que la idea de 'indirection' se oscurece en relacin a 'punteros a char', pues las funciones standard de impresin en pantalla de C y C++ no tratan a tal puntero como una direccin de memoria mas (aunque lo sea). Siendo 'p' un puntero a tipo char, para las funciones standard de impresin: 'p' es la cadena apuntada, '*p' el carcter individual apuntado. Asignacin de punteros Un puntero puede ser asignado a otro puntero del mismo tipo a travs del operador '='. El significado de tal asignacin es similar al de una asignacin entre variables, el valor almacenado en el elemento de la derecha se copia en el elemento de la izquierda. Solo que en el caso de punteros este valor es una direccin de memoria, y esto puede producir un efecto distinto al esperado. void f (char* cad1, char* cad2) { cad1 = cad2; *cad1 = '3'; //Efecto: modificacin de cadena "dos". //................................. } char uno = "1111"; char dos = "2222"; f(uno, dos);

//Llamado a funcin f();

La funcin 'f()' recibe dos punteros a char desde otra funcin, sigue luego una asignacin de 'cad2' en 'cad1', y una modificacin de un char a travs de Desreferenciacin del puntero. Si la intencin era copiar el contenido de la cadena original "dos" en la cadena "uno", para modificar "uno" sin alterar "dos", estamos ante un error. El carcter '3' se copiara en la cadena original "dos", por la razn de 68

que luego de la asignacin de punteros (cad1=cad2) ambos apuntan a "dos". Hay casos donde puede ser til que dos punteros apunten a una misma direccin, y entonces ser correcto asignar punteros mediante el operador '=', pero si lo que se busca es copiar el contenido de un array, entonces se debe hacer de otro modo, copiando uno a uno los elementos de dicho array. Dados dos punteros ("pt1" y "pt2") a array, que apuntan a direcciones diferentes (son dos arrays diferentes), los efectos de una asignacin de punteros y copia de array son los siguientes: Operacion pt1 = pt2; Efecto Asignacin de punteros. Lo que se copia realmente son los 2 (o 4) bytes de direccin de memoria. El puntero 'pt1' deja de apuntar a al array original, ahora apunta a la misma direccin que 'pt2'.

Copia de array. La copia se realiza elemento por elemento. while (*pt2! Se copian tantos elementos como caracteres tenga el array =0) 'pt2'. En el caso de una cadena de caracteres, podemos *pt1=pt2; confiar en el '\0' para saber cuantos elementos copiar. Es muy importante diferenciar ambas operaciones. Un array no puede ser copiado mediante el operador de asignacin '=', hay que copiar elemento por elemento, un puntero puede ser copiado con tal operador, pero el efecto provocado puede ser distinto al efecto deseado.

PUNTERO A PUNTERO
Un puntero almacena la direccin de un objeto, puesto que ese objeto puede ser otro puntero, es posible declarar un puntero que apunta a puntero. La notacin de puntero a puntero requiere de un doble asterisco, '**', la sola notacin suele generar un efecto de confusin considerable, y es la razn de que Mats Henricson y Erik Nyquist, en Rules and Recommendations on C++, sugieran en lo posible reemplazar punteros a punteros por alguna otra alternativa (una clase con miembro puntero) en su Rec 48. Sin embargo, el concepto en si mismo no es complejo. La relacin entre una variable comun, un puntero y un puntero a puntero se muestra en las siguientes lneas:

69

int a = 4; int* pt1 = &a; int**pt2 = &pt1; Por un lado tenemos el valor que almacena la variable 'a', el puntero 'pt1' almacena la direccin de esa variable, y el puntero 'pt2' almacena la direccin del puntero 'pt1'. Son tres identificadores, cada uno tiene un doble aspecto: la localidad de memoria donde se asienta, y el valor que almacena en esa localidad de memoria. Declaracin Direccin e memoria inicializaci (hipottica) n int a = 4; int**pt2 &pt1; = 0xfff6 0xfff2 int* pt1 = &a; 0xfff4 de Valor que almacena en tal direccin de memoria 4 0xfff6 0xfff4

Es interesante comprobar las diferentes salidas en pantalla de 'pt2' en los siguientes casos: cout<<pt2; //Imprime la direccin del propio puntero 'pt2', aqu: "0xfff2" cout<<*pt2; //Imprime la direccin almacenada en 'pt2', "0xfff4" cout<<**pt2; //Imprime el valor almacenado en '*pt1 = a', "4". El comportamiento de la salida en pantalla es coherente, pues se cumplen las siguientes igualdades: *pt2 == pt1; *(*pt2) == *(pt1); *pt1 == a; **pt2 == a; //Desreferenciacion de 'pt2' //Aplicamos '*' a ambos lados //De esto y la linea previa se deduce... //...esta igualdad

Leanse las anteriores lineas como 'igualdades' (comparaciones que dan 'Verdadero') y no como asignaciones. La estrecha relacin existente entre los conceptos de puntero y array, es la razn de que el asterisco doble (**) pueda ser interpretado indistintamente como puntero a puntero, o bien como un array de punteros.

70

ARREGLOS DE PUNTEROS
En C, los punteros a funciones se utilizan como cualquier otro tipo de punteros; pueden ser pasados como argumentos de otras funciones, usados en arreglos, retornados por funciones, etc. La nica diferencia es que lo que se encuentra al tomar el contenido de (operador *) estos punteros, no es un dato sino un pedazo de cdigo ejecutable. Al igual que en los arreglos estticos, el nombre de una funcin que ya existe puede ser utilizada donde se requiera un puntero a funcin. . Su utilizacin permite implementar funciones genricas que operen sobre otras funciones ( bsqueda de ceros, integracin, etc.). Declaracin: Para declarar un puntero a una funcin se utiliza la siguiente sintaxis: tipo_de_retorno (* nombre_de_puntero) (tipo1 arg1, tipo2 arg2, ...); Los nombres de los argumentos (arg1, arg2, etc) no son necesarios, pero pueden servir para entender cmo se usa la funcin. Ejemplo: double (* f) (double x); /* declara el puntero a funcin f notar que los parentesis son necesarios para distinguir de (double *) f(double) */ f = sin; /* lo inicializa con la direccion de memoria de una funcin double>double */ x = f(3.14); /* utiliza el puntero como si fuera una funcin */ x = (* f)(3.14); /* derreferencia explcitamente el puntero al utilizarlo */ Las dos ltimas sentencias son equivalentes ( de la misma manera que cuando trabajabamos con punteros a arreglos, era indistinto decir p[i] o *(p+i)), la primera forma es ms comoda, pero la segunda muestra explcitamente que p es un puntero.

Como argumentos de funciones Si recordamos que la lista de argumentos de una funcin es tambin la declaracin de cada uno de ellos, podemos comprender que la sintaxis sea: tipo_retorno nombre_funcion ( ..., tipo_retorno (*nombre_puntero) (tipo1 arg1, ...), ...,);

71

En el prototipo no es necesario poner el nombre del puntero, ni tampoco el nombre de los argumentos. Ejemplo: #include <stdio.h> #include <math.h> double suma_cuadrados(double (*)(double), int, int); double inversa ( double x) { return 1.0/x; } int main() { double s; s = suma_cuadrados(sin, 1, 100); printf("suma de 1 a 100 de sin(i)^2 = %lf\n", s); s = suma_cuadrados(inversa,1, 100); printf("suma de 1 a 100 de sin(i)^2 = %lf\n", s); return 0; } double suma_cuadrados ( double (*f)(double x), int i0, int if ) { double s = 0,x; int i; for (i=i0; i<=if; i++) { x = i; s += f(x)*f(x); /* (*f)(x)*(*f)(x) en forma ms explcita */ } return s; }

Arreglos de Punteros a funcin: Para declarar un arreglo de punteros a funcin la sintaxis es: tipo_de_retorno (* nombre_de_puntero[tamao]) (tipo1 arg1, tipo2 arg2, ...);
Por ejemplo:

double (* f[3]) (double); f[0] = sin; f[1] = inversa; f[2] = cos; 72

x = f[0](3.14); /* x = sin(3.14) */ x = f[1](3.14); /* x = ivnersa(3.14) */ x = f[2](3.14); /* x = cos(3.14) */

ARITMETICA DE PUNTEROS
Un puntero apunta a una direccin de memoria. El lenguaje C permite sumar o restar cantidades enteras al puntero, para que apunte a una direccin diferente: aritmtica de punteros . Consideremos un puntero a enteros: int* ptr; ptr apuntar a cierta direccin de memoria: Pero tambin tendrn sentido las expresiones ptr+1, ptr+2, etc. La expresin ptr+k es un puntero que apunta a la direccin de ptr sumndole k veces el espacio ocupado por un elemento del tipo al que apunta (en este caso un int): Ejemplo de aritmtica de punteros int vector [100]; int *ptr; ... ptr = &vector[0]; *ptr = 33; *(ptr+1) = 44; *(ptr+2) = 90; /* un vector de enteros */ /* un puntero a enteros */ /* /* /* /* ptr apunta al principio del vector */ igual que vector[0] = 33 */ igual que vector[1] = 44 */ igual que vector[2] = 90 */

La expresin que se suma al puntero ha de ser entera y no tiene por qu ser constante. Obsrvese que ptr es lo mismo que ptr+0. La expresin sumada NO es el nmero de bytes que se suman a la direccin, es el nmero de elementos del tipo al que apunta el puntero: /* Supongamos que un "char" ocupa 1 byte */ /* y que un "double" ocupa 8 bytes */ char* ptrchar; double* ptrdouble; ...

73

*(ptrchar+3) = 33; /* la direccin es ptrchar + 3 bytes */ *(ptrdouble+3) = 33.0; /* la direccin es ptrdouble + 24 bytes, ya que cada double ocupa 8 bytes */ El compilador "sabe" cmo calcular la direccin segn el tipo. Aritmtica de punteros (ms) A un puntero se le puede aplicar cualquier clase de operacin de suma o resta (incluyendo los incrementos y decrementos). /* Rellenar de unos los elementos del 10 al 20 */ int* ptr; int vector [100]; int i; ptr = &vector[0]; ptr+=10; /* el puntero */ /* el vector */ /* variable contadora */ /* ptr apunta al origen del vector */ /* ptr apunta a vector[10] */

for ( i=0; i<=10; i++ ) { *ptr = 1; /* asigna 1 a la posicin de memoria apuntada por "ptr" */ ptr++; /* ptr pasa al siguiente elemento */

ESTRUCUTURAS
Una estructura es un conjunto de datos, posiblemente de tipos diferentes, agrupadas bajo un mismo nombre, para hacer ms eficiente su manejo. Las estructuras ayudan a organizar datos complicados, particularmente en programas grandes, ya que permiten tratar como una unidad a un conjunto de variables relacionadas, en lugar de tratarlas como entidades independientes. Un buen criterio de uso de estructuras establece que la definicin de una estructura debe ir acompaada por la definicin de un conjunto de funciones que se encargan de realizar la manipulacin directa de la nueva entidad creada. 74

Definicin de estructuras en Lenguaje C Una estructura se define en lenguaje C a travs de la siguiente sintaxis: struct Nombre { tipo1 Campo1; tipo2 Campo2; ... tipoN CampoN; }; La declaracin struct Nombre Var1; Declara una variable del tipo "struct Nombre", esto es, el compilador reserva la cantidad de memoria sufuciente para mantener la estructura ntegra (es decir espacio para almacenar Campo1, Campo2, ..., CampoN). Cuando se hace referencia a la variable Var, se esta haciendo referencia a la estructura ntegra. Inicializacin de estructuras Se puede inicializar una estructura externa o esttica aadiendo a su definicin la lista de inicializadores: struct Fecha { int Dia; char *Mes; int Anio; }; struct Fecha Hoy = {8,"Mayo",1991}, VarFecha; ... VarFecha = Hoy; La asignacin VarFecha = Hoy copia la estructura integra Hoy en VarFecha. Cuando dentro de los campos de una estructura aparecen punteros y uno realiza este tipo de asignacin, se esta copiando tambin los valores de los punteros, de tal manera que se puede estar haciendo referencia a un dato desde dos puntos diferentes lo que puede causar efectos no deseados y un potencial peligro para la aplicacin.

75

Referencia de campos de una estructura Un campo de una estructura se utiliza como una variable ms. Para referenciar un campo de una estructura se emplea el operador ".". Ejemplo: Hoy.Dia = 24; Hoy.Mes = "Agosto"; Hoy.Anio = 1991; Ejemplo para verificar ao bisiesto: Bisiesto = Fecha.Anio % 4 == 0 && Fecha.Anio % 100 != 0 || Fecha.Anio % 400 == 0; Las estructuras se pueden anidar: struct Person { char Name [NAMESIZE]; char Adress[ADRSIZE]; long ZipCode; double Salary; struct Fecha Nacimiento; }; Para referenciar un campo de una estructura interna se utiliza la misma sintxis, referenciando campos interno dentro de campos: struct Person Juan; Juan.Nacimiento.Dia = 14;

Punteros a Estructuras Una vez definida las estructuras, se utilizan en forma anloga a los tipos estndar de datos, por lo tanto se pueden declarar arreglos de estructuras, y tambin punteros a estructuras. Se pueden declarar variables que apunten a estructuras: Struct Fecha *FechaPtr; Struct Fecha Hoy; FechaPtr = &Hoy; 76

La referencia a un campo de una estructura a travs de un puntero se realiza mediante el operador "->". FechaPtr > Dia = 15; FechaPtr -> Mes = "Octubre"; Arreglos de Estructuras En el siguiente ejemplo se observa como se declara un arreglo de estructuras, definidas de manera tal que mantienen la informacin necesaria para describir un intervalo, y la cantidad de cuentas que caen en ese intervalo como para armar un histograma. Ejemplo: /* Programa que imprime la tabla de conversin de Fahrenheit a Celsius para F = 0, 20, 40,..., 300 */ #include <stdio.h> int main() { int Lower, Upper, Step; float Fahr, Celsius; Lower = 0; Upper = 300; Step = 20; Fahr = Lower; while(Fahr <= Upper) { Celsius = (5.0/9.0) * (Fahr - 32.0); printf("%4.0f F -> %6.1f C\n", Fahr, Celsius); Fahr = Fahr + Step; } /* fin del while */ return 0; } /* fin del main */

UNIONES

77

Uniones Las uniones (unions) tienen un cometido parecido a las estructuras, esto es, agrupar en una sola variable varios valores. Sin embargo, al contrario que las estructuras, las uniones slo pueden guardar un valor a la vez. Esto significa que si asignamos valor a uno de los componentes de una variable unin, los dems componentes dejarn de tener un valor asignado. La definicin de una unin es muy similar a la de una estructura:
union nombreUnion { declaracin de variable1; declaracin de variable2; .. declaracin de variableN; }; Para declarar una variable del tipo unin, hacemos lo siguiente: union nombreUnion variableUnion1;

El tamao de una unin es el tamao del miembro ms grande, y la alineacin de memoria utilizada para la unin es la alineacin mxima requerida por los miembros de la unin. La estructura kstat de Solaris define una estructura que contiene una unin que se utiliza en el siguiente ejemplo para ilustrar y observar las uniones de C y D. La estructura kstat se utiliza para exportar un conjunto de contadores con nombre que representan las estadsticas del ncleo, como la utilizacin de la memoria y el rendimiento de E/S. La estructura se utiliza para implementar utilidades como mpstat(1M) e iostat(1M). Esta estructura utiliza struct kstat_named para representar un contador con nombre y su valor y se define de la siguiente manera:
struct kstat_named { char name[KSTAT_STRLEN]; /* name of counter */ uchar_t data_type; /* data type */ union { char c[16]; int32_t i32; uint32_t ui32; long l; ulong_t ul; ... } value; /* value of counter */ };

EJEMPLOS
EJEMPLO: 1 #include "iostream.h" 78

#include "conio.h" int a,b,suma; void main () { clrscr (); gotoxy (10,8); cout<<"Introduzca 2 nmeros enteros:"; cin>>a>>b; suma=a+b; gotoxy (10,20); cout<<"la suma de:"<<a<<"y"<<b<<"es:"<<suma; getch (); } EJEMPLO: 2 DISEE UN PROGRAMA QUE PERMITA LEER 3 NUMEROS Y AL FINAL LOS SUME, LOS RESTE, LOS DIVIDA Y LOS MULTIPLIQUE. #include <iostream.h> #include <conio.h> int a,b,c,d; float S,R,M,N; void main () { cout<<"ingrese el valor de a:"; cin>>a; cout<<"ingrese el valor de b:"; cin>>b; cout<<"ingrese el valor de c:"; cin>>c; cout<<"ingrese el valor de d:"; cin>>d; S=a+b+c; R=a-b-c; M=a*b*c; N=a/b/c; cout<<"El resultado de la suma de los numeros es:"; cout<<S; cout<<"El resultado de la resta de los numeros es:"; cout<<R; cout<<"El resultado de la multiplicacion de los numeros es:"; cout<<M; cout<<"El resultado de la division de los numeros es:"; cout<<N; getch (); } 79

EJEMPLO: 3 ESTRUCTURAS DE CONTROL #include "iostream.h" #include "conio.h" int a,r; void main() { clrscr(); gotoxy(10,5); cout<<"Introduzca un numero:"; cin>>a; r=a%2; if (r==0) { gotoxy(10,10) cout<<"El numero es par"; } else { gotoxy(10,10) cout<<"El numero es impar"; } getch(); }

EJEMPLO: 4 #include "iostream.h" #include "conio.h" int a,b,mayor; void main() { clrscr (); cout<<"Introduzca 2 numeros"; cin>>a>>b; if(a>=b) mayor=a; else mayor=b; cout<<"El mayor de; "<<a<<"y"<<b<<"es:"<<mayor; getch(); }

80

EJEMPLO: 5 #include "iostream.h" #include "conio.h" int a,b,mayor; void main () { clrscr (); cout<<"introduzca 2 numeros"; cin>>a>>b; if (a>=b) mayor=a; else mayor=b; cout<<"El mayor de;"<<a<<"y"<<b<<"es:"<<mayor; getch (); } EJEMPLO:6 #include "iostream.h" #include "conio.h" int a,b,c,mayor; void main () { clrscr(); cout<<"Introduzca 3 numeros:"; cin>>a>>b>>c; if (a==b && a==c) cout<<"Todos son iguales"; else { if(a>=b) mayor=a; else mayor=c; cout<<"El mayor de;"<<a<<","<<b<<"y"<<c<<"es:"<<mayor; } getch(); }

81

EJEMPLO: 7 DISEE UN PROGRAMA QUE PERMITA LEER UN NUMERO QUE EQUIVALE AL SUELDO DE UN TRABAJADOR EN FORMA MENSUAL, SI EL NUMERO ES MENOR QUE MIL AUMENTARLE EL 5%, SI ES DE DOS MIL O MAS PERO MENOR QUE TRES MIL, AUMENTARLE EL 3% Y SI ES DE TRES MIL O MAS AUMENTARLE SOLO EL 2%. AL FINAL DEBE MOSTRAR COMO RESULTADO EL SUELDO ACTUAL, EL AUMENTO, Y EL NUEVO SUELDO. #include <conio.h> #include <iostream.h> float sueldo, n, sueldon; void main() { cout<< "introduce tu sueldo"; cin>>sueldo; if(sueldo<1000 && sueldo <=1999) n=sueldo* 0.08; if(sueldo>=2000 && sueldo <=2999) n=sueldo* 0.03; if(sueldo>=3000) n=sueldo* 0.02; sueldon= sueldo+n; cout<<" su sueldo es:"<< sueldo << endl; cout<<" su incrementon fue:"<< n << endl; cout<<" su sueldo neto es:"<< sueldon << endl; getch();

82

EJEMPLO: 8 DISELE UN PROGRAMA QUE PERMITA LEER UN CARCTER DEL TECLADO, LO GUARDE EN UNA VARIABLE DE TIPO char Y POSTERIORMENTE DETECTAR SI SE PULSO UNA VOCAL (PARA C/VOCAL, IMPRIMIR CUAL FUE LA VOCAL QUE SE PULSO). #include "iostream.h" #include "conio.h" char caracter; void main () { clrscr (); cout<<"Pulse un caracter:"; caracter=getch(); switch (caracter) { case 'a': case 'A':cout<<"\n\n pulso la letra A"; break; case 'e': case 'E':cout<<endl<<endl<<"pulso la letra E"; break; case 'i': case 'I':cout<<"\n\n pulso la letra I"; break; case 'o': case 'O':cout<<"\n\n pulso la letra O"; break; case 'u': case 'U':cout<<"\n\n pulso la letra U"; break; default:cout<<"\n\n la letra que pulso no es vocal"; } getch (); }

83

EJEMPLO: 9 (PARA QUE ACEPTE MAYUSCULAS) #include "iostream.h" #include "conio.h" #include "ctype.h" char caracter; void main () { clrscr (); cout<<"Pulse un caracter:"; caracter=toupper (getch()); switch (caracter) { case 'A':cout<<"\n\n pulso la letra A"; break; case 'E':cout<<endl<<endl<<"pulso la letra E"; break; case 'I':cout<<"\n\n pulso la letra I"; break; case 'O':cout<<"\n\n pulso la letra O"; break; case 'U':cout<<"\n\n pulso la letra U"; break; default:cout<<"\n\n la letra que pulso no es vocal"; } getch (); }

84

EJEMPLO: 10 ASTER2 (Permite mover u n asterisco por toda la pantalla, dependiendo de la opcin dada) #include <iostream.h> #include <conio.h> int x=40, y=25; char opci; void main() { clrscr(); gotoxy(x,y); cout<<"*"; gotoxy(5,49); cout<<"Mueva el *, usando las flechas. [End(Fin)] para terminar"; for(;;) { opci=getch(); if(opci==0) opci=getch(); switch (opci) { case 72:gotoxy(x,y); cout<<" "; y--; if(y==0) y=48; gotoxy(x,y); cout<<"*"; break; case 80:gotoxy(x,y); cout<<" "; 85

y++; if(y==49) y=1; gotoxy(x,y); cout<<"*"; break; case 75:gotoxy(x,y); cout<<" "; x--; if(x==0) x=79; gotoxy(x,y); cout<<"*"; break; case 77:gotoxy(x,y); cout<<" "; x++; if(x==80) x=1; gotoxy(x,y); cout<<"*"; break; }//fin switch if(opci==79) break; } }//fin main

EJEMPLO: 11 DISEE UN PROGRAMA QUE IMPRIMA 10 NUMEROS INCREMENTADOS DE 2 EN 2, EMPEZANDO POR EL NUMERO 2.(SE PUEDE HACER COMO EL EJEMPLO 12 Y 13). #include "iostream.h" #include "conio.h" #include "iomanip.h" void main() { clrscr(); 86

cout<<"Programa que imprime los numeros pares entre el 1 y 20:\n\n"; for(int i=1,p=2;i<=10;i++,p=p+2) cout<<setw(5)<<p; getch; }

EJEMPLO: 12 #include "iostream.h" #include "conio.h" #include "iomanip.h" void main() { clrscr(); cout<<"Programa que imprime los numeros pares entre el 1 y 20:\n\n"; for(int i=1,p=2; i<=10;i++) { cout<<setw(5)<<p; p=p+2; } getch; }

EJEMPLO: 13 #include "iostream.h" #include "conio.h" #include "iomanip.h" void main() { clrscr(); 87

cout<<"Programa que imprime los numeros pares entre el 1 y 20:\n\n"; for(int i=2; i<=20; i=i+2) cout<<i; getch; } EJEMPLO:14 DISEE UN PROGRAMA QUE IMPRIMA UN TRIANGULO RECTANGULO FORMADO POR ASTERISCOS. SE DEBE PREGUNTAR EL TAMAO DEL TRIANGULO .PARA N=3 Y N=5. #include <conio.h> #include <iostream.h> #include <iomanip.h> int n; void main() { cout<<"De que tamao desea el cuadrado:"; cin>>n; for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) cout<<"* "; cout<<endl; } getch; } EJEMPLO: 15 (PARA HACER EL TRIANGULO RECTANGULO). #include <conio.h> #include <iostream.h> #include <iomanip.h> int n; void main() { cout<<"De que tamao desea el cuadrado:"; cin>>n; for(int i=1;i<=n;i++) { for(int j=1;j<=i;j++) cout<<"* "; cout<<endl; } getch; } 88

EJEMPLO: 16 (PARA HACER EL TRIANGULO RECTANGULO CON NUMEROS). #include <conio.h> #include <iostream.h> #include <iomanip.h> int n,num=1; void main() { cout<<"De que tamao desea el triangulo:"; cin>>n; for(int i=1;i<=n;i++) { for(int j=1;j<=i;j++) cout<<setw(5)<<num++; cout<<endl; } getch(); } EJEMPLO 17: ESTRUCUTRA WHILE. #include "iostream.h" #include "conio.h" void main() { int i=2; clrscr(); while(i<=20) { cout<<i<<" "; i=i+2; } getch(); }

EJEMPLO 18: ESTRUCUTRA DO WHILE

89

#include "iostream.h" #include "conio.h" void main() { int i=0; clrscr(); do{ i=i+2; cout<<i<<" "; }while(i<20); getch(); }

EJEMPLO 19: ARREGLOS DE UNA DIMENSION. #include "iostream.h" #include "conio.h" int n,i,mayor,num[100]; void main() { clrscr(); cout<<"\n De que tamao desea el arreglo:"; cin>>n; for(i=0;i<n;i++) { cout<<"\n Introduzca el numero "<<i+1<<":"; cin>>num[i]; } mayor=num[0]; for(i=0;i<n;i++) 90

if(num[i]>mayor) mayor=num[i]; cout<<endl<<endl; cout<<"El mayor es:"<<mayor; getch(); }

EJEMPLO 20: CICLOS ANIDADOS, DISEE UN PROGRAMA QUE REALICE LA SUMA DE MATRICES. #include "iostream.h" #include "conio.h" int A[max][max],B[max][max],C[max][max],max=10; int i,j,m,n,num=1; void main() { clrscr(); cout<<"De que orden desea las matrices:"; cin>>m>>n; cout<<"\n\n matriz A:\n"; for(i=0;i<m;i++); for(j=0;j<n;j++); 91

{ cout<<"A["<<i+1<<"]["<<j+1<<"]:"; cin>>A[i][j]; } cout<<"\n\n matriz B:\n"; for(i=0;i<m;i++); for(j=0;j<n;j++); { cout<<"B["<<i+1<<"]["<<j+1<<"]:"; cin>>B[i][j]; } for(i=0;i<m;i++); for(j=0;j<n;j++); C[i][j]=A[i][j]+B[i][j]; clrscr(); cout<<"La matriz resultante es:"; int col=5, ren=2; for(i=0;i<m;i++); { for(j=0;j<n;j++); { gotoxy(col,ren); cout<<C[i][j]; col=col+5; } ren++; col=5; } getch(); }

EJEMPLO 21: DISEE UN PROGRAMA QUE PERMITA MANIPULAR UN ARREGLO CON NUMEROS FLOTANTES, LOS CUALES VAN A REPRESENTAR CALIFICACIONES.

92

EL ARREGLO DEBE CONTENER 7 COLUMNAS PARA REPRESENTAR LAS ASIGNATURAS Y n RENGLONES QUE REPRESENTE A UN NUMERO DETERMINADO DE ALUMNOS. EL PROGRAMA DEBE MOSTRAR EL PROMEDIO POR ALUMNO Y POR ASIGNATURA . #include "iostream.h" #include "conio.h" #include "iomanip.h" int i,j,k,x,y,n_est; float prom_as[7],prom_est[50], prom_tot,cal[50][7]; char nombres[50][25]; void main() { clrscr(); gotoxy(15,2); cout<<"Calificaciones del grupo de Prog. I"; gotoxy(1,4);cout<<"Cuantos estudiantes desea capturar:"; cin>>n_est; cout<<"\n Capture los nombres \n"; for(i=0; i<n_est; i++) { cout<<"\n Estudiante "<<i+1<<":"; cin>>nombres [i]; } clrscr(); gotoxy(15,2); cout<<"Calificaciones del grupo de 2 sem. T.V. "; gotoxy(1,4); cout<<" "; gotoxy(1,4); cout<<"Nom. estud."; gotoxy(18,4);cout<<"Alg.lin. Prog. Cal. "; cout<<"Paq. Ingles Metod. Meca"; x=18; y=5; for(i=0; i<n_est; i++) { gotoxy(1,y); cout<<nombres[i]; for(j=0; j<7; j++) { gotoxy(x,y); cin>>cal[i][j]; 93

x=x+9; } x=18; y++; } cout<<"\n\n Promedio por"<<"\n materia \n\n"; float suma; for(i=0; i<n_est; i++) { suma=0.0; for(j=0; j<7; j++) suma+=cal[i][j]; prom_est[i]=suma/7; cout<<"\n"<<nombres [i]<<" Obtuvo: "<<setprecision (1)<<prom_est[i]; cout<<" De promedio"; } getch(); }

EJEMPLO 22: EN ESTE ALGORITMO SE UTILIZA LA FUNCION strlen PARA CONTAR LOS CARACTERES. #include "conio.h" #include "iostream.h" #include "string.h" int longitud; char cade[50]; void main() { clrscr(); cout<<"Introduzca la cadena:"; cin.getline(cade,50); longitud= strlen(cade); cout<<"\n\n La longitud de la cadena es:"<<longitud; getch(); }

94

EJEMPLO 23: LEER UNA SERIE DE NOMBRES COMPLETOS, ORDENARLOS ALFABETICAMENTE. #include #include #include #include #include "conio.h" "iostream.h" "iomanip.h" "stdio.h" "string.h"

int i,j,n; char nombres[50][25]; void main () { clrscr(); gotoxy(15,2); cout<<"Nombres de personas"; gotoxy(1,4); cout<<"Cuantos nombres desea capturar:"; cin>>n; cout<<"\n Capture los nombres \n"; for(i=0; i<n; i++) { cout<<"\n Nombre ["<<i+1<<"]:"; gets(nombres[i]); strupr(nombres[i]); } clrscr(); cout<<"Los nombres no ordenados son:\n"; for(i=0; i<n; i++) cout<<"\n"<<nombres[i]; cout<<"\n\n Los nombres ordenados son:\n"; for(i=0; i<n-1; i++) { for(j=0; j<n-1; j++) { int x=strcmp(nombres[j], nombres[j+1]); if(x>0) { char aux[25]; 95

strcpy(aux, nombres[j]); strcpy(nombres[j],nombres[j+1]); strcpy(nombres[j+1],aux); } } } for(i=0; i<n; i++) cout<<"\n"<<nombres[i]; getch(); }

Clasificacin por Seleccin Directa


La idea bsica de este algoritmo consiste en buscar el menor elemento en el arreglo y colocarlo en primera posicin. Luego se busca el segundo elemento ms pequeo del arreglo y se lo coloca en segunda posicin. El proceso continua hasta que todos los elementos del arreglo hayan sido ordenados. El mtodo se basa en los siguientes principios: 1. Seleccionar el menor elemento del arreglo. 2. Intercambiar dicho elemento con el primero. 3. Repetir los pasos anteriores con los (n-1), (n-2 ) elementos y as sucesivamente hasta que slo quede el elemento mayor. Ejemplo: Supongase que se desea ordenar las siguientes claves del arreglo A: 15 67 08 44 27 12 35 void seleccion_directa(int n) { int i,j,min,k; int cambio; for(i=0;i<n;i++) { min=arr[i]; k=0; cambio=0; for(j=i+1;j<n;j++) { if (arr[j]<min) { 96

min=arr[j]; k=j; cambio=1;} } if (cambio ) { arr[k]=arr[i]; arr[i]=min; } } }

EJEMPLO: ARREGLO UNIDIMENSIONAL, DISEE UN PROGRAMA QUE PERMITA MANIPULAR UN ARREGLO DE ENTEROS DE UNA DIMENSIN, QUE HAGA LAS SIGUIENTES OPERACIONES: *CREAR EL ARREGLO CON n NUMEROS, MEDIANTE UN CICLO do-while *OBTENER EL MAYOR DEL ARREGLO *OBTENER EL MENOR DEL ARREGLO *OBTENER EL PROMEDIO *SALIR #include "iostream.h" #include "conio.h" #include "iomanip.h" void main() { clrscr(); int n,j,mayor,menor,i,A[100], k,suma; float prom; char opcion; do{ cout<<"Introduce el tamao de tu arreglo:"; cin>>n; i=0; do{ cout<<"Introduce dato("<<i+1<<"):\n"; cin>>A[i]; i++; }while(i<n);

97

clrscr(); j=0; mayor=A[j]; do{ if(A[j]>mayor) mayor=A[j]; j++; }while(j<n); cout<<"\n El mayor es:"<<setw(3)<<mayor; i=0; menor=A[i]; do{ if(A[i]<menor) menor=A[i]; i++; }while(i<n); cout<<"\n\n El menor es: "<<setw(3)<<menor; k=0; prom=0; suma=0; do{ suma=suma+A[k]; k++; }while(k<n); prom=suma/n; cout<<"\n\n El promedio es: "<<setw(3)<<prom; cout<<"\n\n Desea repetir (s/n)"; cin>>opcion; }while(opcion== 's'||opcion== 'S'); getch(); }

98

EJEMPLO: FUNCION DEFINIDA POR EL PROGRAMADOR: REALICE UN PROGRAMA QUE MEDIANTE FUNCIONES NOS PERMITA LEER VALORES ENTEROS Y GUARDARLOS EN UN ARREGLO DE UN SUBINDICE, POSTERIORMENTE IMPRIMIR UN MENSAJE SI EXISTE O NO UN ELEMENTO DADO DENTRO DE UN ARREGLO. #include "iostream.h" #include "conio.h" #include "iomanip.h" enum logico {falso,verdadero}; logico encontrado; void leer_datos(); logico evaluar_elemento(int a[], int elemento); int n, valores[50]; void main() { clrscr(); leer_datos(); cout<<"\n\n Que elemento desea buscar:"; int elem; cin>>elem; logico res; res= evaluar_elemento(valores, elem); if(res==falso) cout<<"\n\n El valor no existe en el arreglo;"; else cout<<"\n\n El valor si existe en el arreglo;"; getch(); } void leer_datos() { cout<<"\n\n Cuantos valores desea:"; cin>>n; 99

for(int i=0; i<n; i++) { cout<<"\n valor"<<i+1<<":"; cin>>valores[i]; } } logico evaluar_elemento(int a[], int elemento) { int i=0; logico valor=falso; while(i<n && valor==falso) { if(a[i]==elemento) valor=verdadero; i++; } return(valor); }

EJEMPLO DE PUNTEROS: #include "iostream.h" #include "conio.h" int a, x, *p, *q; void main() { clrscr(); a=10; x=20; p= &a; cout<<"\n El valor apuntado por p es:"<<*p; q=p; cout<<"\n El valor apuntador por q es: " <<*q; *q=50; cout<<"\n El valor de a es : "<<a; 100

getch (); }

EJEMPLO: #include #include #include #include "iostream.h" "conio.h" "iomanip.h" "stdio.h"

int longitud(char * p); void main() { char cade [30]; clrscr(); cout<<"Introduzca la cadena:"; gets(cade); int tamanio= longitud(cade); cout<<"\n\n El tamao de la cadena es;" <<tamanio; getch; } int longitud(char *p) { int cont=0; while(*p) { cont ++; p++; } return (cont); }

101

BIBLIOGRAFA:
1. Curso de programacin con Turbo C++. Luis Joyanes Aguilar. Mc Graw-Hill. 2. C++. Un Enfoque Orientado a Objetos. Luis Joyanes Aguilar. Mc Graw-Hill. 3.Manual de Borland C++. Chris H. Pappas y William H. Murray. Mc Graw-Hill. 4. Programacin En C Y C++. Deitel y Deitel. Pearson Prentice Hall 5. Programacin en Turbo C++. Herbert Schildt. Mc. Graw-Hill. 6. Manual y Ayuda en lnea de C y de C++.

102