esta es una prueba de subir archivos

Page 1

¿QUÉ ES UNA COMPUTADORA? Una computadora es un dispositivo capaz de realizar cálculos y tomar decisiones lógicas a velocidades hasta miles de millones de veces más rápidas que las alcanzables por los seres humanos. Por ejemplo, muchas de las computadoras personales actuales pueden realizar decenas de millones de sumas por segundo, y los más sorprendente es que puede hacer todo eso sin cometer errores, se imaginan a una persona provista de una calculadora cuánto tiempo le tomaría realizar el mismo cálculo

Componentes de una computadora Una computadora de cualquier forma que se vea tiene dos tipos de componentes: El Hardware (Parte Física) y el Software (Parte Lógica).

Hardware Llamamos Hardware a la parte física de la computadora, pues vienen a ser las partes que podamos percibir con el sentido del tacto. El hardware que compone a una computadora es muy complejo, pues una pequeña pieza puede contener millones de transistores. Ejemplo de Hardware podría ser la Tarjeta Madre, Memoria Principal, CPU, etc.

Partes del Hardware de una computadora El Hardware esta compuesto por seis unidades o secciones básicas y son las siguientes: 1. Unidad de entrada. Que es la sección de recepción de la computadora: obtiene información (datos y programas de computadora) y lo coloca a disposición de las demás unidades para que sea procesada. La información se introduce por medio del teclado o del Mouse (ratón). Otros dispositivos pueden ser los escáneres, los lápices ópticos, las pantallas touch screen, cámaras, etc.


2. Unidad de salida. La computadora muestra las respuestas a través de esta unidad, estas respuestas son el resultado del procesamiento que realiza la computadora con los datos que hemos introducido. Por ejemplo mediante un dispositivo de entrada como el teclado, podemos escribir palabras la cuales las podremos observar por un dispositivo de salida como el monitor o la pantalla. Otros dispositivos de salida son también la impresora, los parlantes, tarjetas de video.

3. Unidad de memoria. También se la conoce como memoria RAM, es el almacén primario de la computadora por lo que es relativamente de baja capacidad. Esta memoria es la más importante de la computadora, porque guarda información necesaria para que la computadora pueda arrancar y funcionar, en otras palabras guarda información de todos los programas que se ejecutan en una computadora incluyendo al Sistema Operativo.

4. Unidad aritmética y lógica (ALU). Esta es la parte de la computadora en donde se realizan los cálculos. sumas o restas. Aquí están también los mecanismos de decisión que permiten a la computadora, por ejemplo, comparar dos elementos de la unidad de memoria para determinar si son iguales o no. 5. Unidad central de procesamiento (CPU). Es el cerebro de la computadora, pues es el coordinador de la máquina y la parte encargada de supervisar el funcionamiento de las otras secciones. La CPU le dice a la unidad de entrada cuándo debe leerse información para introducirla en la unidad de memoria, le dice a la ALU cuando la información de la unidad de memoria debe utilizarse en los cálculos y le dice la unidad de salida cuando debe enviar la información que está es la unidad de memoria a ciertos dispositivos de salida. 6. Unidad de almacenamiento secundario. Esta es el almacén de largo plazo y de alta capacidad de la computadora. Los programas y datos que nos están siendo utilizados por las otras unidades normalmente se colocan en dispositivos de almacenamiento secundario hasta que necesiten, posiblemente horas, días, meses o incluso años después. El acceso es más lento comparado con el de la memoria primaria o memoria RAM.

Software Nos referimos con software a la parte lógica de la computadora a los procedimientos que el hardware realiza inducidos por el software y este a su vez por nosotros. El software es como un traductor que hace que nuestras órdenes se conviertan en realidad, manipulando el hardware o la parte física. El software esta compuesto por programas de computadora.

Programa


Un programa es un conjunto de instrucciones lógicas que le dicen a la computadora que debe hacer, además un programa debe satisfacer la necesidades de los usuarios utilizando eficientemente los recursos disponibles. Los programas de tratan con mayor profundidad en el Tema 3. Los programas que escribiremos más adelante serán utilizando un lenguaje de programación muy popular como lo es el C++.

Código Fuente Le daremos el nombre de código fuente a los programas que escribamos en un determinado lenguaje de programación, que simplemente estará compuesto por instrucciones escritas por un programador. El código fuente no constituye software propiamente dicho pero es una instancia mediante la cual se llega al Software

Sistema Operativo Es el programa más importante que se ejecuta en una computadora. Cualquier computadora de propósito general debe operar con un sistema operativo para lograr ejecutar otros programas. El sistema operativo ejecuta las tareas básicas, como de reconocer entradas desde el teclado, enviar mensajes a pantalla, manteniendo rastro de los archivos y directorios en el disco, y controlar los dispositivos periféricos como las impresoras. Para grandes sistemas, el sistema operativo tiene una gran responsabilidad y cualidades. Es como un policía de transito, quien se asegura de que los diferentes programas que se ejecutan al mismo tiempo no interfieran unos con otros. También es responsable de la seguridad, asegurando que usuarios no autorizados accedan al sistema. El sistema operativo provee de una plataforma de software por encima de la cual otros programas, llamados aplicaciones, pueden ejecutarse. Los programas de aplicación tienen que crearse de acuerdo a la plataforma en donde se van a ejecutar. La elección de sistema operativo, entonces, determina el tipo de uso que se le va ha dar a la PC como también el tipo de aplicaciones que se puedan ejecutar. Para las PCs (computadoras personales) los más populares sistemas operativos son el DOS, OS/2, y Windows, además de otros de libre distribución como el Linux.

Lenguajes de alto nivel y lenguajes de bajo nivel Los programadores escriben instrucciones en diversos lenguajes de programación. La computadora puede entender directamente algunos de ellos, pero otros requieren pasos de traducción intermedios. Hoy día se utilizan cientos de lenguajes de computadora, los cuales pueden dividirse en tres tipos generales:


1. Lenguaje máquina Una computadora sólo puede entender el lenguaje máquina. El lenguaje de máquina ordena a la computadora realizar sus operaciones fundamentales una por una. Dicho lenguaje es difícil de usar para lar persona porque trabajar con números no es muy cómodo además estos números están en formato binario.

2. Lenguajes de bajo nivel (ensamblador) Para facilitar y agilizar su labor a los programadores, se buscaron nuevos lenguajes. El lenguaje ensamblador consiste en pequeñas abreviaturas de palabras en ingles. Se crearon los programar traductores para convertir los programas escritos en lenguaje ensamblador a lenguaje máquina a velocidades de computadora. Estos lenguajes aun requerían muchas instrucciones para realizar simples operaciones.

3. Lenguajes de alto nivel Para acelerar, aún más, el proceso de programación se desarrollan los lenguajes de alto nivel en los que se podía escribir un enunciado para realizar tareas sustanciales. Los lenguajes de alto nivel permiten a los programadores escribir instrucciones que asemejan el ingles cotidiano y contiene notaciones matemáticas de uso común.

Ambientes de Programación Los programadores necesitan un ambiente de programación, es decir, una lugar en donde puedan plasmar sus ideas, un lugar en donde puedan escribir sus programas, en otras palabras donde puedan programar. Los ambientes de programación vienen a ser los diferentes leguajes de programación que existen, son muy variados, con muchas cualidades propias pero se puede realizar una misma tarea, muchas veces, con cualquiera de ellos. Existen lenguajes de programación de Alto y Bajo nivel; entre los más conocidos de Alto nivel podemos mencionar a C, C++, JAVA, Fortran, T. Pascal, etc.

Traductor de lenguajes de programación Los traductores son programas que traducen los programas en código fuente, escritos en lenguajes de alto nivel, a programas escritos en lenguaje máquina. Los traductores pueden ser de dos tipos: compiladores e interpretes

Compilador Un compilador es un programa que lee el código escrito en un lenguaje (lenguaje origen), y lo traduce o traduce en un programa equivalente escrito en otro lenguaje (lenguaje objetivo). Como una parte fundamental de este proceso de traducción, el compilador le hace notar al usuario la presencia de errores en el código fuente del programa. Vea la figura de abajo.


El C++ es un lenguaje que utiliza un compilador y su trabajo es el de llevar el código fuente escrito en C++ a un programa escrito en lenguaje máquina.

Entrando en más detalle un programa en código fuente es compilado obteniendo un archivo parcial (un objeto) que tiene extensión obj luego el compilador invoca al linker que convierte al archivo objeto en un ejecutable con extensión exe que como ya sabemos es un archivo que esta en formato binario (ceros y unos) y que puede funcionar por si solo. Además el compilador de C++ al realizar su tarea realiza una comprobación de errores en el programa, es decir, revisa que todo este en orden por ejemplo variables y funciones bien definidas, revisa todo lo referente a cuestiones sintácticas, esta fuera del alcance del compilador que por ejemplo el algoritmo utilizado en el problema funcione bien. La siguiente figura muestra los pasos para tener un programa ejecutable desde el código fuente:

Interprete Los interpretes en lugar de producir un Lenguaje objetivo, como en los compiladores, lo que hacen es realizar la operación que debería realizar el Lenguaje origen. Un interprete lee el código como esta escrito y luego lo convierte en acciones, es decir, lo ejecuta en ese instante. Existen lenguajes que utilizan un Interprete, como por ejemplo JAVA, y su interprete traduce en el instante mismo de lectura, el código en lenguaje máquina para que pueda ser ejecutado. La siguiente figura muestra el funcionamiento de un interprete.


Diferencia entre Compilador e Interprete Los compiladores difieren de los interpretes en varios aspectos: Un programa que ha sido compilado puede correr por si solo, pues en el proceso de compilación se lo transformo en otro lenguaje (lenguaje máquina). Un interprete traduce el programa cuando lo lee, convirtiendo el código del programa directamente en acciones. La ventaja del interprete es que dado cualquier programa se puede interpretarlo en cualquier plataforma (sistema operativo), en cambio el archivo generado por el compilador solo funciona en la plataforma en donde se lo ha creado. Pero por otro lado un archivo compilado puede ser distribuido fácilmente conociendo la plataforma, mientras que un archivo interpretado no funciona si no se tiene el interprete. Hablando de la velocidad de ejecución una archivo compilado es de 10 a 20 veces más rápido que un archivo interpretado.

Parte II Algoritmos


Un algoritmo es un procedimiento a seguir, para resolver un problema en términos de: 1. Las acciones por ejecutar y el 2. El orden en que dichas acciones deben ejecutarse Un algoritmo nace en respuesta a la aparición de un determinado problema. Una algoritmo esta compuesto de una serie finita de pasos que convergen en la solución de un problema, pero además estos pasos tienen un orden específico. Entenderemos como problema a cualquier acción o evento que necesite cierto grado de análisis, desde la simpleza de cepillarse los dientes hasta la complejidad del ensamblado de un automóvil. En general, cualquier problema puede ser solucionado utilizando un algoritmo, en este sentido podemos utilizar los algoritmos para resolver problemas de computo. Un algoritmo para un programador es una herramienta que le permite resaltar los aspectos más importantes de una situación y descartar los menos relevantes. Todo problema de cómputo se puede resolver ejecutando una serie de acciones en un orden específico. Por ejemplo considere el algoritmo que se elaboraría para el problema o situación de levantarse todas las mañanas para ir al trabajo: 1. 2. 3. 4. 5. 6.

Salir de la cama quitarse el pijama ducharse vestirse desayunar arrancar el automóvil para ir al trabajo o tomar transporte.

Nótese que en el algoritmo anterior se ha llegado a la solución del problema en 6 pasos, y no se resaltan aspectos como: colocarse los zapatos después de salir de la cama, o abrir la llave de la regadera antes de ducharse. Estos aspectos han sido descartados, pues no tienen mayor trascendencia, en otras palabras los estamos suponiendo, en cambio existen aspectos que no podemos obviarlos o suponerlos, de lo contrario nuestro algoritmo perdería lógica, un buen programador deberá reconocer esos aspectos importantes y tratar de simplificar al mínimo su problema. Es importante recalcar que los pasos de un algoritmo no son conmutativos pues, no daría solución al mismo problema a tratar.

ROBUSTEZ DE UN ALGORITMO Quiere decir que un algoritmo debe contemplar todas las posibles facetas del problema que queremos resolver, al elaborar un algoritmo no se nos debe escapar ningún detalle que provoque un funcionamiento malo nuestro algoritmo. Si logramos construir un algoritmo robusto, cualquier giro inesperado del problema será controlado por el algoritmo, es decir, debe ser flexible a cambios.

CORRECTITUD DE UN ALGORITMO Es correcto cuando da una solución al problema a tratar y cumple con todos lo requerimientos especificados tal que cumplamos con los objetivos planteados.


COMPLETITUD DE UN ALGORITMO Cuando un algoritmo cuenta con todos los recursos para poder llegar a una solución satisfactoria

EFICIENCIA Y EFICACIA DE UN ALGORITMO Un algoritmo es eficiente cuando logra llegar a sus objetivos planteados utilizando la menor cantidad de recursos posibles, es decir, minimizando el uso memoria, de pasos y de esfuerzo humano. Un algoritmo es eficaz cuando alcanza el objetivo primordial, el análisis de resolución del problema se lo realiza prioritariamente. Puede darse el caso de que exista un algoritmo eficaz pero no eficiente, en lo posible debemos de manejar estos dos conceptos conjuntamente.

Resolución de Problemas Para lograr resolver cualquier problema se deben seguir básicamente los siguientes pasos: Análisis del Problema. en este paso se define el problema, se lo comprende y se lo analiza con todo detalle. Diseño del Algoritmo. se debe elaborar una algoritmo que refleje paso a paso la resolución del problema. Resolución del Algoritmo en la computadora. se debe codificar el algoritmo.

RESOLUCIÓN DE PROBLEMAS UTILIZANDO ALGORITMOS Ejemplo 2.1 Una universidad ofrece un curso que prepara a los estudiantes para el examen de obtención de licencia de corredor de bienes raíces. El año anterior, varios de los estudiantes que completaron el curso presentaron el examen para obtener la licencia. Naturalmente la Universidad desea saber que resultados obtuvieron sus estudiantes en el examen. Se nos ha pedido escribir un programa que resuma los resultados recibidos de una lista de 10 estudiantes. Junto a cada nombre se anoto un 1 si el estudiante aprobó el examen y un 2 si reprobó. Exhiba un resumen de los resultados de la prueba indicando el número de estudiantes que aprobaron y el número de estudiantes que reprobaron . Si más de Ocho estudiantes aprueban el examen la Universidad será capaz de aumentar la colegiatura.


Exhibir el mensaje "Teclee resultado" en la pantalla cada vez que el programa solicite otro resultado de examen. Solución Algoritmo A grandes rasgos: Analizar los resultados del examen y decidir si se debe aumentar o no la colegiatura. Se puede refinar como sigue: Inicializar variables Introducir las primeras 10 calificaciones y contar los aprobados y los reprobados. Imprimir un resumen de los resultados de exámenes y decidir si se debe aumentar o no la colegiatura.

Pseudocódigo Pseudocódigo Es un lenguaje artificial e informal que ayuda a los programadores a desarrollar algoritmos. El Pseudocódigo es similar al lenguaje cotidiano; es cómodo y amable con el usuario, aunque no es realmente in verdadero lenguaje de computadora. No se ejecutan en las computadoras mas bien sirven para ayudar al programadora razonar un programa antes de intentar escribirlo en algún lenguaje. Un programa ejecutado en Pseudocódigo puede ser fácilmente convertido en un programa en C++, si es que esta bien elaborado. Por ejemplo supongamos que la nota para aprobar un examen es de 60. El enunciado en Pseudocódigo sería: Si calificación >= 60 entonces Mostrar "Aprobado" FinSi El mismo enunciado se puede escribir en C++ como: if ( calif >= 60 ) cout << "Aprobado"; Nótese que la operación de trasladar el Pseudocódigo a código fuente, se lo realiza con el mínimo esfuerzo, no se necesita de un mayor análisis. Llevando el Ejemlo2.1 a Pseudocódigo. Se puede refinar más aun el algoritmo: Inicializar variables. Inicializar los aprobados (aprobados) en 0 Inicializar los reprobados (reprobados) en 0 Inicializar el número de estudiantes (estudiantes) en 0 Introducir las primeras 10 calificaciones y contar los aprobados y los reprobados. Mientras (while) el contador estuantes es menor o igual que 10 entonces Introducir el siguiente resultado de examen Si el estudiante aprobó Sumar 1 a aprobados Si no Sumar 1 a reprobados


FinSi Sumar 1 al contador estudiantes FinMientras Imprimir un resumen de los resultados de exámenes y decidir si se debe aumentar o no la colegiatura. Imprimir el número de aprobados Imprimir el número de reprobados Si estudiantes es más 8 entonces Imprimir "Aumentar la colegiatura". FinSi Simplificando el problema queda escrito en Pseudocódigo de la siguiente forma:

El problema anterior escrito en C++

Diagramas de flujo Un diagrama de flujo es una representación gráfica de un algoritmo o de una parte del mismo. Los diagramas de flujo ayudan en la comprensión de la operación de las estructuras de control (Si, Mientras). La ventaja de utilizar un algoritmo es que se lo puede construir independiente mente de un lenguaje de programación, pues al momento de llevarlo a código se lo puede hacer en cualquier lenguaje. Dichos diagramas se construyen utilizando ciertos símbolos de uso especial como son rectángulos, diamantes, óvalos, y pequeños círculos, estos símbolos están conectados entre sí por flechas, conocidas como líneas de flujo. A continuación se detallarán estos símbolos.


Terminal. Representa el inicio y fin de un programa. Proceso. Son acciones que el programa tiene que realizar

Decisión. Indica operaciones lógicas o de comparación, así como expresiones

Entrada / Salida. Nos permite ingresar datos, de un periférico, así como mostrarlos

Salida. Es usado para mostrar datos o resultados Conector. Se coloca al principio y fin de un pedazo de programa, enlaza dos partes cualquiera de un programa Línea de flujo o indicador de dirección. Representaremos el correspondiente diagrama de flujo del ejemplo 2.1


PARTE III


Programa Un programa de computadora es una serie de instrucciones, órdenes a la máquina, que producirán la ejecución de una determinada tarea. Es un medio para satisfacer una necesidad o cumplir un objetivo de una manera automatizada. Comúnmente, la palabra programa es usada de dos maneras: para describir instrucciones individuales, código fuente, creado por el programador y también describe una pieza entera de software ejecutable. Esta distinción puede causar confusión, por lo que vamos a tratar de distinguir entre el código fuente por un lado y un ejecutable por otro. Para tener un programa ejecutable primero tenemos que tener su código fuente, es decir, del código fuente se deriva el programa ejecutable. El Código fuente puede ser convertido en un programa ejecutable de dos formas: Interpretes convierten el código fuente en instrucciones de computadora (lenguaje máquina), y la computadora actúa con esas instrucciones inmediatamente. El JAVA es un lenguaje interpretado. Alternativamente, los compiladores trasladan el código fuente en programas, los cuales pueden ejecutarse tiempo después. A pesar de que se puede trabajar fácilmente con los intérpretes, la mayor parte de la programación es hecha con compiladores porque el código compilado se ejecuta más rápido. C++ es un lenguaje de compilación.

Estructura de un Programa Un programa esta formado por la cabecera y el cuerpo del programa.

Cabecera En la cabecera se incluyen a nuestro programa algunas rutinas predefinidas que hacen a la programación más sencilla, pues no tenemos que crear todo desde cero o "tratar de inventar la rueda", es muy bueno que conozcamos la mayor cantidad de librerías disponibles para que tengamos un trabajo más que sencillo y estandarizado. Un programa puede no tener cabecera pero sería demasiado simple, he aquí un ejemplo de una cabecera para un programa sencillo. #include <iostream.h>

Cuerpo


El cuerpo del programa contiene la función principal, las funciones adicionales y las clases que se necesiten en el programa. La mejor forma de aprender un lenguaje es programando con él. El programa más sencillo que se puede escribir en C++ es el siguiente: void main() { } Como nos podemos imaginar, este programa no hace nada, pero contiene la parte más importante de cualquier programa C++ y además, es el más pequeño que se puede escribir y que se compile correctamente. En el se define la función void main, que es la que ejecuta el sistema operativo al llamar a un programa C++. La función principal (void main) o cualquier otra función siempre va seguida de paréntesis. La definición del cuerpo de la función está formada por un bloque de sentencias o instrucciones, que esta encerrado entre llaves {}. Un programa C++ puede estar formado por diferentes módulos de código fuente. Es conveniente mantener los código fuente de un tamaño no muy grande, para que la compilación sea rápida. También, al dividirse un programa en partes, puede facilitar la legibilidad del programa y su estructuración. Los diferentes códigos fuentes son compilados de forma separada, únicamente el código fuente que han sido modificados desde la última compilación, y después combinados con las librerías necesarias para formar el programa en su versión ejecutable.

Mecanismos de Salida Los mecanismos de Salida son aquellos mensajes que el programa utiliza para comunicarse con el mundo exterior o con el usuario. Por ejemplo yo quiero un programa que me salude cordialmente: 1: 2: 3: 4: 5:

#include <stdio.h> void main() { printf("Hola amigo!\n") ; }

El mismo resultado se obtiene con: 1: 2: 3: 4: 5:

#include <iostream.h> void main() { cout<<" Hola amigo! \n" ; }

Con el visualizamos el mensaje Hola amigo! en la ventana del MS­DOS. Analizando el segundo ejemplo, en la primera línea 1 se indica que se tengan en cuenta las funciones y tipos definidos en la librería iostream (standard input/output) que es la cabecera. Estas definiciones se encuentran en el archivo iostream.h. Ahora, en la función main se incluye una única sentencia que llama a la función cout en la línea 4. La funcion cout es usada para desplegar flujos de


salida de datos, en pocas palabras, muestra lo que queramos por pantalla, pueden ser datos, nombre, resultados, etc. Para usar cout se debe colocar esta palabra seguida del operador < que se lo coloca dos veces, luego entre comillas dobles "" se coloca el texto que se quiere mostrar por pantalla. El símbolo \n, colocado al final del texto, indica un cambio de línea.

Caracteres especiales ASCII Hay un grupo de símbolos, que son tratados como caracteres individuales, que especifican algunos caracteres especiales del código ASCII. Los más importantes son: \a \b \f \n \r \t \v \\ \' \" \OOO \xHHH

alerta backspace Suministro de Papel cambio de línea carácter de regreso tabulación horizontal tabulación vertical barra inversa comilla simple comilla doble visualiza un carácter cuyo código ASCII es OOO en octal. visualiza un carácter cuyo código ASCII es HHH en hexadecimal.

Las funciones de entrada y salida y los formatos utilizados los explicaremos con más detalle en otro capítulo.

Mecanismos de Entrada Los mecanismos de Entrada nos permiten interacción entre el mundo exterior (Usuarios) y el programa, así el programa puede recabar información necesaria para cumplir con su meta. Ejemplo: Un ejemplo sencillo sería que el programa nos pregunte nuestra edad: 1: 2: 3: 4: 5: 6: 7: 8:

#include <iostream.h> void main() { int edad; cout<<" ¿Qué edad tienes? \n" ; cin>>edad; cout<<"Tienes "<<edad<<" años"; }

En este ejemplo estamos usando la función cin que pertenece a la librería iostream.h, cuya función es crear un flujo de entrada de datos. Puede leer enteros, cadenas, etc. En nuestro ejemplo en la línea 4 se declara una variable de tipo entero nombrada edad.


En la línea 5 se muestra el mensaje: ¿Qué edad tienes?. En la línea 6 se espera recibir un flujo de entrada, es decir, que el usuario escriba un valor (en este caso su edad) y al presionar ENTER este valor se almacenará en la variable edad. Finalmente en la línea 7 el programa muestra un mensaje: tienes x años. En donde x es la edad que se introdujo desde teclado.

en donde se almacena el dato ingresado por teclado.

Variables Un programa necesita un medio de grabar los datos que usa. Las variables y Constantes ofrecen varias maneras para representar y manipular los datos.

Definición de variable Una variable es un espacio para guardar información. Entrando más a detalle una variable es una ubicación en la memoria de la computadora en la cual se puede grabar un valor y por la cual se puede recuperar ese valor más tarde. La memoria RAM de la computadora puede ser vista como una serie de pequeñas casillas, cada una de las casillas esta numerada secuencialmente, este número que se le asigna representa su dirección de memoria y su objetivo es identificarla. Una variable reserva uno o más casillas en las cuales es posible grabar datos.

Los nombres de las variables (por ejemplo, myVariable) es una etiqueta en una sola casilla, para que se pueda encontrarla fácilmente sin saber su actual dirección de memoria. RAM es la memoria de acceso aleatorio. Una programa cuando es ejecutado o esta corriendo, es grabado temporalmente en la memoria RAM. Todas las variables, son también, creadas en la memoria RAM. Cuando los programadores hablan de memoria, generalmente se están refiriendo a la memoria RAM.

Reservando Memoria Se reserva memoria en el momento de definición de las variables, en este momento es donde se debe de especificar al compilador que clase de variable es: un entero (int), un caracter (char), etc. Esta información le dice al compilador cuanto de espacio debe separar o reservar, y que tipo de valor se va ha guardar en la variable. Cada casilla de memoria tiene un byte de capacidad. Si el tipo de variable que se crea es de dos bytes te tamaño, este necesita de dos bytes de memoria, o de dos casillas. El tipo de variable (por ejemplo, entero) le dice al compilador cuanta memoria (o cuantas casillas) tiene que reservar para la variable. Porque las computadores usan los bits y los bytes para representar los valores, y porque la memoria es medida en bytes, es importante entender y sentirse cómodo con este concepto.


Definir una Variable Para crear una variable es preciso definirla. En la definición de una variable se manifestando su tipo, seguida de uno o más espacios, luego se escribe el nombre de la variable y para finalizar punto y coma. El nombre de la variable puede ser cualquier combinación de letras, claro que sin espacios. Nombres de variables aceptadas son: x, jap007, miedad. Importante. Los nombre buenos de variables nos dice para que la variable es utilizada, usando buenos nombres se nos hace más fácil la compresión del programa. La siguiente sentencia define una variable entera llamada miedad. int miedad; Como practica general de programación, se debe evitar los nombres horroríficos como j23qrs o xxx y restringir los nombres de variables de una sola letra como x ó y, para valores que sean de uso rápido y no perduren en todo el programa. Se debe tratar de usar nombres extensos como miedad o contador. Algunos nombres son fáciles de entender tres semanas después en lugar de romperse la cabeza imaginándose que significan nombres cortos.

Inicializar una variable Una vez definida una variable se debe proceder a darle un valor, es cierto que este valor puede cambiar a lo largo del programa, pero es bueno acostumbrarse a dar siempre un valor inicial a nuestras variables. Por ejemplo: miedad = 0; notaFinal = 0;

Asignación de un Valor Se le puede asignar valores a una variable cuantas veces se quiera durante el programa, se le asigna un valor utilizando el operador de igualdad “=”.

Palabras Reservadas o Claves Existen en todos los lenguajes nombres o palabras que ya están siendo usadas, y por eso se les da el nombre de palabras reservadas o claves. Por ejemplo en el caso de C++ palabras reservadas son: int, if, const, main ...., etc. No podemos nombrar por ejemplo una variable definida por nosotros con ninguna palabra reservada porque el compilador encontraría un error.

Constantes


Las constantes son variables que contienen un valor que no cambia durante todo el programa. Una constante simbólica al igual que cualquier variable tiene un tipo y un nombre. Existen dos formas de declarar constantes en C++. La primera es utilizando una instrucción, generalmente en la cabecera, que es como sigue: #define Estudiantes 50 Es la forma tradicional de definir constantes, pero nótese que Estudiantes no tiene un tipo de dato. Lo que hace #define es simplemente sustituir 50 en todas las ocurrencias del programa donde aparezca Estudiantes. La segunda forma es mucho más específica y mucho más útil y es así: const int Estudiantes = 50; Esta forma es mucho más ventajosa porque la constante Estudiantes tiene un tipo de dato lo que hace al código mucho más mantenible y lo previene de errores.

Expresiones Una expresión es todo aquello que se evalúa y devuelve un valor. Existen varios tipos de expresiones de acuerdo lo que contienen.

Las expresiones aritméticas consisten de una secuencia de operadores y operandos que especifican una operación determinada. Los operandos pueden ser variables, constantes y los operadores aritméticos son (+ ­ * / %). Es más sencillo pensar que una expresión aritmética es como una ecuación o una fórmula matemática. Una expresión aritmética sencilla es: area = base * altura ; En la anterior línea de código, el resultado de la expresión base * altura se guarda en area. Las expresiones lógicas también conocidas como expresiones booleanas. Están compuestas por operadores y operandos, los operadores en este caso son operadores relacionales y operadores lógicos. Este tipo de expresiones es evaluado y devuelve un valor, la diferencia esta en que este valor sólo puede ser verdadero o falso.

Los operadores relacionales son(< > == <= >= ...). Los operadores lógicos son (&& || & |).

Un ejemplo de expresiones lógicas es el siguiente: if ( (nota > 70) && (nota < 90) )


En la anterior instrucción el segmento (nota > 70) && (nota < 90) devolverá 1 (verdadero) ó 0 (falso).

PARTE IV Estructuras de Control


Existen tres clases de estructuras de control:

1. Secuenciales 2. Condicionales 3. Iterativas Los programas que escribamos pueden definirse en base a las tres estructuras de control ya mencionadas. Las estructuras condicionales que C++ nos ofrece son: if, if / else, switch. Las estructuras iterativas son: for, while, Do / while.

Partes de una estructura de Control Diferenciaremos dos partes en una estructura de control: 1. La definición de dicha estructura 2. El cuerpo de la estructura. En la definición es donde se coloca el nombre de la estructura que se va ha utilizar y en el cuerpo de la misma se ubican todas las sentencias o instrucciones que pertenecen o hacen referencia a dicha estructura. Si es cuerpo de tiene más de una instrucción va entre llaves ( {} ).

Sentencias o Instrucciones Una sentencia es la unidad ejecutable más pequeña de un programa en C++, en otras palabras una línea de código escrita es una sentencia. Las sentencias controlan el flujo y orden de ejecución. Una sentencia de C++ consta de palabras clave o reservadas como (for, while, if ... else,etc.), expresiones, declaraciones, o llamadas a funciones. Toda sentencia simple termina con un punto y coma (;). Dos o más sentencias pueden aparecer en una sola línea separadas por el punto y coma. Una sentencia nula es simplemente un punto y coma.

PARTE V Estructuras de Selección La Estructura de Selección if La sentencia if se la conoce como estructura de selección simple y su función es realizar o no una determinada acción o sentencia, basándose en el resultado de la evaluación de una expresión (verdadero o falso), en caso de ser verdadero se ejecuta la sentencia.


Fig. 5.1 La estructura de selección if (que se muestra en la figura 5.1) trabaja de la siguiente manera: si la evaluación de la expresión o expresiones es verdadera ( 1 ) entonces se ejecuta la sentencia a la cual se refiere la estructura de control if. Si fueran varias sentencias a las que se refiere la estructura if (como se muestra en la figura 5.2) se tiene que encerrar todas las sentencias entre llaves ( { } ) y si la evaluación de la expresión es correcta entonces se ejecuta todas las sentencias contenidas entre las llaves.

Fig. 5.2 Si la evaluación de la expresión o expresiones resultaría falsa (0), entonces no se ejecuta las sentencias. Por ejemplo si dada la edad de una persona quiero dar un mensaje de que es o no mayor de edad, suponiendo que una persona mayor de edad tiene por lo menos 21 años, el procedimiento será el siguiente. #include <iostream.h> void main() { cout<<"¿Qué edad tienes? \n"; cin>>edad if ( edad > 20 ) cout<<"Eres mayor de edad" ;

} #include <iostream.h> void main() { cout<<"¿Qué edad tienes? \n"; cin>>edad if ( edad > 20 ) { cout<<"Eres mayor de edad"; cout<<"Te estas volviendo viejo "; } }

En Pseudocódigo el anterior ejemplo se vería de la siguiente forma: Inicio Mostrar “¿Qué edad tienes?” Leer edad


Si Edad > 20 Entonces Mostrar “Eres mayor de Edad” Fin Si Fin

El diagrama de flujo de la estructura if se muestra en la Fig. 5.3, este diagrama contiene el símbolo diamante que es llamado el símbolo de decisión, que indica que decisión se debe tomar. El símbolo de decisión contiene una expresión, y la evaluación de ésta será verdadera o falsa. Las flechas nos indican los dos posibles caminos que se pueden tomar.

fig 5.3 El anterior diagrama de flujo funciona de la siguiente manera: 1. Si Edad es mayor que 20 (verdadero) entonces se muestra “Eres mayor de Edad” 2. Si no entonces no hace nada Importante. Para mantener el código legible es bueno dejar espacios o sangrías en todas las líneas de código que están dentro de una estructura if / else o if, estas instrucciones se las alinean un poco más a la derecha y así podemos notar claramente que forman parte de las sentencias que componen a la estructura if. Esta práctica se puede aplicar a cualquier estructura de control.

Estructura de Selección if / else La estructura if / else lo que hace es ejecutar una acción si el resultado de la evaluación de la expresión es verdadera y otra acción si el resultado de la evaluación es falsa. La diferencia con utilizar sólo la estructura if es que si la expresión evaluada es verdadera sólo en ese caso se ejecuta una acción de otro modo se pasa de largo. En cambio en la estructura if / else si la expresión es falsa entonces se ejecuta otra acción.


Fig. 5.4 En síntesis lo que hace esta estructura es realizar una acción si la expresión es verdadera y otra si es falsa. Aquí tenemos un ejemplo para ilustrar la estructura if / else. #include <iostream.h> void main() { if ( edad > 20 ) cout<<"Eres mayor de edad" ; else cout<<"No eres mayor de edad"; } El diagrama de flujo correspondiente a esta estructura es el siguiente:

fig. 5.5 El anterior diagrama de flujo funciona de la siguiente manera: 1. Si Edad es mayor que 20 (verdadero) entonces se muestra: “Eres mayor de Edad”. 2. Si no entonces se muestra: “NO eres mayor de Edad”.

Estructuras Condicionales Anidadas Existe el caso de estructuras if, if/else anidadas, que no es más que una estructura if o if/else dentro de otra. Por ejemplo se desea conocer cuál es el mayor de tres números A, B ,C. 1: #include <iostream.h> 2: void main() 3: { 4: int A=0, B=0, C=0; 5: cout<<"Ingrese 3 números"; 6: cin>>A>>B>>C; //Lectura de valores por teclado 7: if ( A > B ) 8: { if (A > C ) 9: cout<<"A es el número mayor";


10: else 11: cout<<"C es el número mayor"; 12: } 13: else 14: { if ( B > C ) 15: cout<<"B es el número mayor"; 16: else 17: cout<<"C es el número mayor"; 18: } 19: } Para explicar el funcionamiento del problema anterior se han enumerado todas las líneas de tal programa. Suponiendo que los valores ingresados por teclado fueran: A=2, B=1, C=5. El programa actuaría de la siguiente manera. El programa se ejecuta secuencialmente hasta la línea 7 donde encuentra una expresión. Cuando se evalúe la expresión (A > B) línea 7, el resultado es verdadero (2 > 1), por lo tanto el programa ejecuta la línea 8, en dicha línea encuentra otra expresión (A > C) y el resultado de evaluar dicha expresión es falso (2 > 5) por lo que el programa salta hasta la línea 11 y muestra "C es el número mayor". Luego va a la línea 12 y verifica el cierre de llaves y finalmente salta hasta la línea 19 siendo la última línea de ejecución.

PARTE VII Estructura de repetición while Dicha estructura repite una serie de acciones mientras se cumpla una condición.

while ( expresión ) { sentencia (s); } La estructura while trabaja de la siguiente manera: 1. Evalúa la expresión o condición 2. Si el resultado de esta evaluación es verdadero la sentencia o sentencias se ejecutan, es decir, se ejecuta el cuerpo de la estructura. Luego se vuelve a evaluar la expresión 3. Si el resultado de esta evaluación es falso no se ejecuta la sentencia o sentencias y sale del ciclo while.


Por ejemplo tengo que apagar 10 velas cuando cumpla 10 años, es decir, tengo que soplar 10 veces, entonces el problema escrito en Pseudocódigo sería:

Inicio edad <- 0 mientras edad != 10 años soplar vela edad = edad + 1 Fin Mientras Fin

Ejemplo 6.1 Otro ejemplo que nos demostrará iteraciones con límite conocido es: Tengo que mostrar la tabla de multiplicar del 9 por pantalla #include <iostream.h> void main() { int nro=1; while(nro <= 10 ) { cout<<"9 * "<<nro<<" = "<<nro*9; nro++; } } Este programa nos mostrará lo siguiente: 9 * 1 = 9 9 * 2 = 18 9 * 3 = 27 9 * 4 = 36 9 * 5 = 45 9 * 6 = 54 9 * 7 = 63 9 * 8 = 72 9 * 9 = 81 9 * 10 = 90 Se dice que tiene un límite conocido porque nunca irá más allá del 10, realizará exactamente 10 iteraciones.

Ejemplo 6.2 Un ejemplo con límite desconocido sería invertir un número entero ingresado por teclado. #include <iostream.h> void main() { int nro=0, aux=0, rpta=0; cout<<"Ingrese un numero entero"; cin>>nro; while(nro > 0)


{ aux = nro % 10; nro = nro / 10; rpta = (rpta * 10) + aux; } cout<<"El numero invertido es: "<<rpta; } Este problema tiene un límite desconocido porque no puedo decir con exactitud el número de iteraciones que hará, eso depende del número de cifras que tenga el número ingresado por teclado. Si el número ingresado tiene 3 cifras se harán 3 iteraciones y si tiene 6 se harán 6 iteraciones. En otras palabras el límite depende de la expresión que se evalúa.

La Estructura de Repetición for Esta estructura de repetición es más utilizada cuando sabemos el número de repeticiones que deseamos ejecutar, es parecido al caso de la estructura while en el caso de límite conocido. La notación de esta estructura es sencilla y se detalla a continuación for ( condición de inicio ; expresión ; acción después de cada iteración )

{ sentencia (s); }

La condición de inicio quiere decir que podemos inicializar una variable que vayamos a utilizar dentro el cuerpo de la estructura for. La expresión nos indica que se seguirá iterando mientras la condición sea verdadera. La acción después de cada iteración viene a ser lo que queremos hacer variar después de cada iteración, esta variación podría ser un incremento en la variable definida en la condición de inicio. Al igual que las demás estructuras de control el cuerpo de la estructura for lleva llaves si este contiene más de una sentencia o instrucción.

Ejemplo 6.3 Un ejemplo sencillo puede ser que quiero cantar 10 veces la canción del elefante, el código sería algo así: #include <iostream.h> void main() { int i; for( i = 1 ; i<=10 ; i++) { cout<<i<<" elefante(s) se balanceaba sobre la tela de una araña\n”; cout<<”como veía(n) que resistía fueron a llamar a otro elefante\n "; } }

El código anterior emitirá por pantalla 10 veces el mensaje de 1 elefante ....... hasta 10 elefantes...... El ejemplo anterior es muy sencillo pero nos muestra el funcionamiento de la estructura for.


Un ejemplo algo más complejo sería el siguiente problema. mas ejercicios.

Estructura de repetición do while Esta estructura de control es muy parecida a la estructura while lo que la hace diferente es que siempre ejecuta por lo menos una ves el cuerpo de la estructura, por eso el do, y luego valida una expresión y en función a este resultado vuelve a iterar o no. La notación de esta estructura es como sigue: do { sentencias o instrucciones } while ( expresión ); Las estructura do/while lleva punto y coma a diferencia de la estructura while.

Ejemplo 6.4 Un ejemplo para este caso es el siguiente: Se desea ingresar por lo menos un nombre de un estudiante por teclado hasta que el usuario presione '0' para salir o cualquier otro número para continuar. #include <iostream.h> void main() { char nom[20]; //Cadena que puede contener 20 caracteres int rpta=0; do {

cout<<"Ingrese el nombre de un estudiante \n"; cin>>nom; cout<<"Desea continuar ingresando nombres: para salir '0'";

cin>>rpta; }

while(rpta != 0); }


PARTE VIII Estructuras de Datos Una estructura de datos es un colección de datos que se caracterizan por su forma de organización y las operaciones que se pueden definir de dicha estructura. Nosotros ya estamos familiarizados con los datos simples, como enteros (int), caracteres (char), etc. Una estructura de datos es una colección de datos simples, como por ejemplo un vector o arreglo. La clasificación de las estructuras de datos se la puede hacer de la siguiente forma:

Arreglo Un arreglo es un conjunto o colección finita de datos de un mismo tipo. Los elementos de un arreglo pueden ser accedidos por medio de un subíndice i. Podemos considerar a un arreglo desde el punto de vista matemático como un vector, y a un arreglo bidimensional una matriz.

DECLARACIÓN DE UN ARREGLO Un arreglo se define indicando el tipo de arreglo, es decir, el tipo de datos de todos los elementos del arreglo, luego se le da un nombre al arreglo y finalmente se le da un tamaño. <tipo> nombreArreglo[Tamamaño] Por ejemplo tengo un arreglo de números enteros: int arreglo[4];


En el caso anterior el tipo del arreglo es entero (int). Se le da una dimensión al arreglo que va entre los caracteres '[' y ']' , en el caso anterior la dimensión es 4, esto quiere decir que en la memoria se reservaron 4 posiciones para almacenar 4 valores enteros.

INICIALIZAR UN ARREGLO Existen varias maneras de inicializar un arreglo, una manera muy sencilla es poner entre llaves ({ }), los elementos del arreglo separados por comas. arreglo = {51, 60, 70, 95}; También podemos utilizar la estructura de control for para inicializar los elementos del arreglo como se ve en el Ejemplo 7.1

ACCESO A LOS ELEMENTOS DE UN ARREGLO Puedo acceder a un elemento por medio de un subíndice, por ejemplo si yo quiero acceder al primer elemento tendré que hacerlo de esta manera int nro = arreglo[0]; En la variable nro se almacenara el valor de 51, para acceder al segundo valor: nro = arreglo[1]; En la variable nro se almacenará el valor de 60, y así sucesivamente con los demás elementos. arreglo[0] arreglo[1] arreglo[2] arreglo[3]

51 60 70 95

Si nos damos cuenta tener un arreglo es mucho más ventajoso que tener definidas 4 variables. Desventajas. En ocasiones, no podemos predecir con precisión el tamaño que un arreglo tendrá por lo que podemos definir un arreglo muy grande, lo que nos lleva a desperdiciar memoria, por ejemplo si defino un arreglo de 100 elemento (arreglo[100]), y sólo utilizo 5 posiciones de memoria, las demás 95 estarán desperdiciadas, la solución a este problema la veremos más adelante en lo que se denomina punteros.

EJEMPLO 7.1 Se desea ingresar las notas finales de 10 alumnos de la materia de Introducción a la programación, para luego emitir un reporte del promedio de todas las notas. #include <iostream.h> void main() { const int TAM = 10; int i, promedio=0; int arreglo[TAM]; for(i=0; i < TAM ; i++) {


cout<<"Ingrese la nota del estudiante #"<<i+1<<" :\n"; cin>>arreglo[i]; } for(i=0; i < TAM ; i++) promedio = promedio + arreglo[i]; promedio = promedio / TAM ; cout<<"El promedio de las notas es: "<<promedio;

}

No hubiera sido muy práctico manejar 10 variables diferentes para guardar las notas de los 10 alumnos, utilizando un arreglo se nos simplifican mucho las cosas. Nota: Se puede declarar un arreglo dándole la dimensión o tamaño por un valor constante const int TAM=10; int arreglo[TAM]; si TAM no fuera constante el programa devolvería mensaje de error.

Métodos de Ordenamiento 1. Ordenación por lección Este método es muy sencillo y se trata de buscar el elemento más pequeño del arreglo y llevarlo a la primera posición, luego se avanza a la siguiente posición, segunda, y se coloca el elemento más pequeño del arreglo y así sucesivamente. solución 2. Ordenación por Inserción Este método es capaz de mantener un arreglo ordenado insertando elementos en su correspondiente posición, por ejemplo si mi arreglo contiene los valores {1,3,4} y quiero insertar un nuevo elemento 2, el arreglo quedará de esta forma {1,2,3,4}. solución 3. Ordenación de Burbuja Este es un método de ordenación elemental, que hace todas las comparaciones necesarias para colocar un elemento en la posición que le corresponde. solución 4. Ordenación Shell 5. Ordenación Quicksort

Métodos de Búsqueda 1. Búsqueda Secuencial


Esta búsqueda realiza un recorrido lineal (uno por uno) por todos los elementos de un arreglo. Es útil cuando el tamaño del arreglo no es grande y no tiene a crecer su número de elementos. solución 2. Búsqueda Binaria Dicha búsqueda es aplicable en arreglos ordenados, pues su funcionamiento depende de este hecho.

PARTE IX Estructuras de Datos Una estructura de datos es un colección de datos que se caracterizan por su forma de organización y las operaciones que se pueden definir de dicha estructura. Nosotros ya estamos familiarizados con los datos simples, como enteros (int), caracteres (char), etc. Una estructura de datos es una colección de datos simples, como por ejemplo un vector o arreglo. La clasificación de las estructuras de datos se la puede hacer de la siguiente forma:

Arreglo Un arreglo es un conjunto o colección finita de datos de un mismo tipo. Los elementos de un arreglo pueden ser accedidos por medio de un subíndice i. Podemos considerar a un arreglo desde el punto de vista matemático como un vector, y a un arreglo bidimensional una matriz.

DECLARACIÓN DE UN ARREGLO Un arreglo se define indicando el tipo de arreglo, es decir, el tipo de datos de todos los elementos del arreglo, luego se le da un nombre al arreglo y finalmente se le da un tamaño.


<tipo> nombreArreglo[Tamamaño] Por ejemplo tengo un arreglo de números enteros: int arreglo[4]; En el caso anterior el tipo del arreglo es entero (int). Se le da una dimensión al arreglo que va entre los caracteres '[' y ']' , en el caso anterior la dimensión es 4, esto quiere decir que en la memoria se reservaron 4 posiciones para almacenar 4 valores enteros.

INICIALIZAR UN ARREGLO Existen varias maneras de inicializar un arreglo, una manera muy sencilla es poner entre llaves ({ }), los elementos del arreglo separados por comas. arreglo = {51, 60, 70, 95}; También podemos utilizar la estructura de control for para inicializar los elementos del arreglo como se ve en el Ejemplo 7.1

ACCESO A LOS ELEMENTOS DE UN ARREGLO Puedo acceder a un elemento por medio de un subíndice, por ejemplo si yo quiero acceder al primer elemento tendré que hacerlo de esta manera int nro = arreglo[0]; En la variable nro se almacenara el valor de 51, para acceder al segundo valor: nro = arreglo[1]; En la variable nro se almacenará el valor de 60, y así sucesivamente con los demás elementos. arreglo[0] arreglo[1] arreglo[2] arreglo[3]

51 60 70 95

Si nos damos cuenta tener un arreglo es mucho más ventajoso que tener definidas 4 variables. Desventajas. En ocasiones, no podemos predecir con precisión el tamaño que un arreglo tendrá por lo que podemos definir un arreglo muy grande, lo que nos lleva a desperdiciar memoria, por ejemplo si defino un arreglo de 100 elemento (arreglo[100]), y sólo utilizo 5 posiciones de memoria, las demás 95 estarán desperdiciadas, la solución a este problema la veremos más adelante en lo que se denomina punteros.

EJEMPLO 7.1 Se desea ingresar las notas finales de 10 alumnos de la materia de Introducción a la programación, para luego emitir un reporte del promedio de todas las notas. #include <iostream.h> void main()


{ const int TAM = 10; int i, promedio=0; int arreglo[TAM]; for(i=0; i < TAM ; i++) { cout<<"Ingrese la nota del estudiante #"<<i+1<<" :\n"; cin>>arreglo[i]; } for(i=0; i < TAM ; i++) promedio = promedio + arreglo[i]; promedio = promedio / TAM ; cout<<"El promedio de las notas es: "<<promedio;

}

No hubiera sido muy práctico manejar 10 variables diferentes para guardar las notas de los 10 alumnos, utilizando un arreglo se nos simplifican mucho las cosas. Nota: Se puede declarar un arreglo dándole la dimensión o tamaño por un valor constante const int TAM=10; int arreglo[TAM]; si TAM no fuera constante el programa devolvería mensaje de error.

Métodos de Ordenamiento 1. Ordenación por lección Este método es muy sencillo y se trata de buscar el elemento más pequeño del arreglo y llevarlo a la primera posición, luego se avanza a la siguiente posición, segunda, y se coloca el elemento más pequeño del arreglo y así sucesivamente. solución 2. Ordenación por Inserción Este método es capaz de mantener un arreglo ordenado insertando elementos en su correspondiente posición, por ejemplo si mi arreglo contiene los valores {1,3,4} y quiero insertar un nuevo elemento 2, el arreglo quedará de esta forma {1,2,3,4}. solución 3. Ordenación de Burbuja Este es un método de ordenación elemental, que hace todas las comparaciones necesarias para colocar un elemento en la posición que le corresponde. solución 4. Ordenación Shell 5. Ordenación Quicksort


Métodos de Búsqueda 1. Búsqueda Secuencial Esta búsqueda realiza un recorrido lineal (uno por uno) por todos los elementos de un arreglo. Es útil cuando el tamaño del arreglo no es grande y no tiene a crecer su número de elementos. solución 2. Búsqueda Binaria Dicha búsqueda es aplicable en arreglos ordenados, pues su funcionamiento depende de este hecho.

PARTE X Arreglos Bidimensionales


Un arreglos bidimensional esta compuesto, por un conjunto de elementos homogéneos y se puede acceder a los datos utilizando dos subíndices, este tipo de arreglo es también conocido como matriz.

DECLARACIÓN Un arreglo bidimensional se define así: int arreglo[10][10]; float matriz[10][10]; también podemos utilizar constantes para definir la dimensión del arreglo de dos dimensiones: const int N = 10; int arreglo[N][N];

INICIALIZACIÓN Una matriz o arreglo bidimensional se puede inicializar de este modo: int matriz[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; Con la anterior asignación se crea en memoria una matriz igual a la de abajo

0 1 2

0 1 4 7

1 2 5 8

2 3 6 9

Fig. 8.1 También podemos utilizar una estructura for dentro de otra estructura for para inicializar los valores de un arreglo de dos dimensiones como se muestra a continuación:

EJEMPLO 8.1 Leer desde teclado una matriz de números enteros de dimensión 3x3. #include <iostream.h> void main() { const int TAM=3; int matriz[TAM][TAM]; for( int i=0; i<TAM ; i++) { for( int j=0; j<TAM; j++) { cout<<”Ingrese el elemento [“<<i<<”,“<<j<<”] “; cin>>matriz[I][j]; } } }


ACCESO A LOS ELEMENTOS DE UN ARREGLO BIDIMENSIONAL En un arreglo de dos dimensiones necesitamos también dos índices para acceder a sus elementos. Si utilizamos: matriz[i][j], entonces i se refiere a la fila y j a la columna.

Para acceder al elemento de la segunda fila y segunda columna de la matriz de la Fig. 8.1 hacemos: int nro = matriz[1][1]; En la variable nro se guardara el número 5. Las matrices o arreglos bidimensionales se suelen utilizar en cálculos matemáticos, operaciones con matrices, recorridos por matrices, y cualquier uso que nosotros le podamos dar. Se pueden definir arreglos de más de 2 dimensiones, pero su manejo se dificultaría enormemente.

EJEMPLO 8.2 (MULTIPLICACIÓN DE MATRICES) Se requiere un programa que realice la multiplicación de dos matrices, para tal efecto se deben ingresar las dos matrices por teclado teniendo el cuidado de controlar que la primera matriz tenga una dimensión de N*M y la segunda de M*N para que se pueda realizar la multiplicación. Solucion...

EJEMPLO 8.3 Los alumnos de primer semestre de la carrera de Licenciatura en Química de la Universidad Mayor de San Simon son 20. Todos los alumnos toman inicialmente 5 materias lo que quiere decir que al final del semestre tendrán 5 notas cada alumno. Escribir un programa que pida las 5 notas de los 20 alumnos y luego devuelva el promedio de todas las notas. Solución...

EJEMPLO 8.4 (CUADRADO PERFECTO) Se debe imprimir un cuadrado mágico de tamaño N, donde N es un número impar comprendido entre 3 y 11. Un cuadrado mágico esta compuesto de números enteros entre 1 y N, con las siguientes características: la sumas de las filas, columnas, diagonales son iguales, como se ve en el siguiente ejemplo: 8 16 3 57


4 92 El método de generación del cuadrado mágico consiste en situar el número 1 en la casilla del centro de la primera fila, el siguiente número se debe situar en la casilla ubicada en la fila anterior (por encima) y en la columna de la derecha. Este proceso se repite hasta colocar los N números. Es importante saber que el cuadrado mágico es cíclico, es decir, la fila anterior (encima) de la primera fila es la última fila y la columna a la derecha de la última es la primera columna. En caso de que un número se debe colocar en una casilla que ya esta ocupada, entonces se elige la casilla que se encuentra debajo (en la siguiente fila, la misma columna) del número que acabamos de ubicar.

PARTE XI Carácter Un carácter es el átomo de los programas de computadora, un carácter es un símbolo que puede ser una letra del alfabeto o un carácter especial.


Un carácter ocupa 8 bits en memoria, y existen 256 caracteres diferentes. Cada carácter se lo codifica en un número entero, es decir, que cada carácter tiene su correspondiente representación entera, el código ASCII es precisamente esto. Por ejemplo el carácter ‘a’ tiene como código ASCII el entero 97. Para ver todos códigos ASCII véase el anexo A.

Cadenas Una cadena o cadena de caracteres nos es más que una serie de caracteres manipulados como una unidad. Si asemejamos una cadena al lenguaje castellano sería como una palabra, que es un conjunto de sílabas y vocales en donde cada una de estas viene a ser una carácter. Visto desde otro punto vendría a ser un arreglo de caracteres. Una cadena puede contener cualquier carácter, puede almacenar un nombre propio una dirección, es decir, lo que nosotros precisemos.

DECLARACIÓN Una cadena se la define de la siguiente manera char cadena[20]; La cadena anterior puede contener un máximo de 20 caracteres.

INICIALIZACIÓN Se puede inicializar una cadena de la siguiente manera: cadena = "Hola" ; Cualquier valor que se le asigne a una cadena va entre comillas dobles " ", como en el ejemplo anterior "Hola" esta entre comillas dobles. Una cadena siempre finaliza con el carácter de fin de cadena ‘\0’, que siempre se añade al final automáticamente, en el ejemplo anterior se añade al final de “Hola” el carácter de fin de cadena. También podemos considerar a una cadena como un arreglo de caracteres, y se puede inicializar de la siguiente manera: cadena = { ‘H’, ‘o’, ‘l’, ‘a’ } ; El arreglo de caracteres se vería de esta forma: ‘H’

‘o’

‘l’

‘a’

‘\0’

0

1

2

3

4

Nótese que en la posición 4 se aumenta el fin de cadena

EJEMPLO 9.1


Se desea tener un programa que sea amable con el usuario, el programa deberá conocer el nombre del usuario y responderle con un mensaje amigable. #include <iostream.h> void main() { char nombre[30]; cout<<"¿Cuál es tu nombre?"; cin>>nombre; cout<<"Que tengas un buen día "<<nombre; }

En el ejemplo anterior el mensaje "¿Cuál es tu nombre?" es una cadena pues esta entre comillas. También es una cadena la variable nombre que recibirá un valor desde teclado.

Operaciones con Cadenas Existen muchas operaciones que se pueden realizar utilizando cadenas, la mayoría de la operación que podemos requerir se encuentran ya a nuestra disposición dentro de la librería string.h

LONGITUD La longitud de una cadena la podemos conocer utilizando la función strlen.

Sintaxis strlen( cadena ) ;

Ejemplo 9.2 #include <iostream.h>#include <string.h> void main() { char nombre[30]; int tamano;

cout<<"¿Cuál es tu nombre?\n"; cin>>nombre; tamano = strlen( nombre ); cout<<"Tu nombre tiene "<<tamano<<”letras”; }

COMPARACIÓN Para saber si dos cadenas son exactamente iguales utilizamos la función strcmp.

Sintaxis strcmp ( cadena1, cadena2 );


Esta función devuelve un valor de acuerdo al resultado de la comparación. Devuelve: 0

iguales

si la dos cadenas son exactamente

Mayor a 0

si la cadena1 es mayor a la cadena2

Menor a 0

si la cadena1 es menor que la

cadena2

Ejemplo 9.3 #include <iostream.h> #include <string.h> void main() {

char contrasena[30], reContrasena[30]; int resultado; cout<<"Escribe tu contraseña\n"; cin>>contrasena; cout<<"Re escribe tu contraseña\n"; cin>>reContrasena; resultado = strcmp(contrasena, reContrasena); if ( resultado == 0 ) cout<<"La contraseña es aceptada"; else cout<<"La contraseña no coincide"; }

COPIA Podemos reflejar todo el contenido de una cadena a otra, en otras palabras la copiamos tal cual, para esto utilizamos la función strcpy.

Sintaxis strcpy( cadenaDestino, cadenaOrigen ); Todo el contenido de la cadenaOrigen se copia a la cadenaDestino, si esta última tuviera algún valor este se borra.

Ejemplo 9.4 #include <iostream.h> #include <string.h> void main() { char nombre[30], apellido[30];


cout<<"¿Cuál es tu nombre? \n"; cin>>nombre; cout<<”¿Cuál es tu apellido paterno\n”; cin>>apellido; strcat(nombre, “ “); //Se le añade un espacio en blanco strcat(nombre, apellido); cout<<”Tu nombre completo es “<<nombre; }

CONCATENACIÓN Podemos juntar o concatenar dos cadenas una a continuación de la otra. Utilizamos la función strcat.

Sintaxis strcat( cadenaDestino, cadenaOrigen ); Todo el contenido de la cadenaOrigen se añade a continuación de la cadenaDestino, si esta última contiene algo entonces al final contendrá lo que contenía más el contenido de la cadenaOrigen.

Ejemplo 9.5 #include <iostream.h> #include <string.h> void main() {

char origen[30], copia[30]; cout<<"¿Qué día es hoy? \n"; cin>>origen; strcpy(copia, origen); cout<<”Hoy es “<<copia; }

EJEMPLO 9.6 Escriba una función que permita conocer la longitud de una cadena. La función deberá llamarse longitud #include <iostream.h> #include <string.h> int longitud(char cadena[])

{

int acum = 0; while( cadena[acum] != '\0' ) de cadena

return acum; }

acum++;

//mientras no sea fin


void main() {

char nombre[30]; cout<<"¿Cuál es tu nombre?\n"; cin>>nombre; cout<<"Tu nombre tiene "<<longitud(nombre)<<" letras"; }

PARTE XII Definición de Puntero Los punteros son variables que contienen una dirección que hacen referencia a un valor. Una variable común contiene o almacena un valor, mientras que un puntero almacena la dirección que hace referencia a este valor. Para tener un mejor entendimiento de un puntero tenemos que saber que es la memoria, a la que podemos considerar como una colección de casillas en las cuales se puede guardar información, cada casilla esta enumera o tiene una dirección. Podríamos imaginarnos a la memoria como una gran biblioteca, la cual consta de varios estantes, supongamos que están divididos en casillas, en donde cada una puede contener a un libro. En este ejemplo un puntero sería uno de los registros que se encuentren en el catálogo de la biblioteca, en donde cada registro contiene información de la ubicación (dirección) del libro dentro de los estantes de la biblioteca. De esta manera es más fácil buscar directamente en el catálogo que estante por estante, su manejo es más cómodo; lo mismo ocurre con los punteros. Una variable seria directamente la porción de estante o la casilla que contiene al libro.


Declaración de un Puntero Un puntero puede ser de cualquier tipo y su declaración es de la siguiente forma: <tipo> * nombrePuntero ; Esto quiere decir que un puntero tiene que tener un tipo de dato, luego le sigue el operador de indirección (*) y luego un nombre cualquiera, el que le daremos al puntero. Ejemplos de declaración de punteros son: int *puntero ; // es un puntero a un tipo de dato entero char *nombre ; //es un puntero a una cadena de caracteres float *promedio; //es un puntero a un tipo de dato real

Inicialización Para inicializar un puntero debemos de hacerlo de acuerdo al tipo de dato al que pertenece el puntero.

EJEMPLO 10.1 (PUNTERO A UN ARREGLO DE ENTEROS) 1: #include <iostream.h> 2: 3: void main() 4: { 5: int arreglo[] = {3, 2, 1}; 6: int *puntero; 7: puntero = arreglo; 8: cout<<*puntero; 9: cout<<*(puntero+0); 10: cout<<puntero[0]; 11: }

En el anterior ejemplo en la línea 7 cuando se asigna puntero el arreglo, lo que se guarda en realidad en el puntero es la dirección del primer elemento del arreglo, conociendo esta dirección podemos conocer los demás elementos. Entrando más en detalle las tres siguientes sentencias son iguales: cout<<*puntero; cout<<*(puntero+0); cout<<puntero[0]; Todas las anteriores sentencias muestran el primer elemento del arreglo al que apunta el puntero y es 3. Para acceder a los demás elementos se pude hacer de la siguiente manera:


cout<<*(puntero+1); cout<<puntero[1]; Las anteriores sentencias muestran el segundo elemento del puntero, y de esta manera se pueden mostrar todos los elementos siguientes colocando en vez de 1; 2, 3, 4.... o sino utilizando un ciclo. Existe una forma más de recorrer a los elementos del arreglo: cout<<puntero[0] puntero++; cout<<puntero[0]; En el primer cout se muestra el primer elemento del arreglo, es decir 3, luego se encuentra la instrucción puntero++; la cual no hace incrementar en 1 el valor del puntero sino mas bien hace incrementar en 1 la posición a la que apunta el puntero. Entonces ahora el puntero apunta al segundo elemento. Entonces el segundo cout mostrará 2.

EJEMPLO 10.2 (PUNTERO A UNA CADENA) 1: 2: 3: 4: 5: 6: 7:

#include <iostream.h> void main() { char *cadena = “Universidad Mayor de San Simón”; cout<<cadena; }

Dirección y Valor de un puntero Como habíamos mencionado que un puntero contiene una dirección que señala a un valor, entonces como podríamos hacer para ver la dirección o para ver solamente el valor. Existen dos operadores que nos permiten realizar estas operaciones, para ver solamente la dirección de un puntero se utiliza el operador &. Para obtener el valor que apunta nuestra variable se debe utilizar el operador *. Por ejemplo:

EJEMPLO 10.3 1: 2: 3: 4: 5: 6: 7: 8:

#include <iostream.h> void main() { int aux = 4 ; int *puntero = &aux ; cout<<"La direccion de memoria es: "<<&puntero<<endl; cout<<"El valor es: "<<*puntero; } Respuesta:


La dirección de memoria es: 0xfff2 El valor es: 4

En el ejemplo anterior en la línea 5 después de declarar un puntero se le asigna una dirección, para ser más específicos la dirección de la variable aux, esto se logra precediendo el operador de dirección & a la variable. En la línea 6 se muestra primero la dirección del puntero y luego su valor.

Punteros Vs Arreglos Es posible utilizar punteros para reemplazar a los arreglos normales, veremos como podemos utilizar un puntero para reemplazar un arreglo de enteros y una arreglo de caracteres (cadena).

ARREGLOS DE ENTEROS Esta parte la explicaremos utilizando un ejemplo escrito primero con arreglos y luego con punteros.

Programa resuelto utilizando un arreglo de enteros

EJEMPLO 10.4 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:

#include <iostream.h> void main() { int notas[4]; int i; for(i=0 ; i<4; i++) cin>>notas[i]; for(i=0; i<4; i++) cout<<[i]; }

Programa resuelto utilizando un puntero a enteros

EJEMPLO 10.5 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:

#include <iostream.h> void main() { int *notas; int i; for(i=0 ; i<4; i++) cin>>*(notas+i); for(i=0; i<4; i++) cout<<*(notas+i); }

Esencialmente la diferencia en los ejemplos 10.4 y 10.5 esta en inicialmente en la línea 4 donde se declara es arreglo con tamaño 4 en el ejemplo 10.4 y en el ejemplo 10.5 en la línea 4


se declara un puntero a un entero y no se especifica tamaño alguno. Luego la forma de acceder a los datos en el ejemplo 10.4 en la línea 7 es por medio del subíndice y corchetes "notas[i]" en el caso del ejemplo 10.5 en la línea 7, para acceder al valor de una dato se lo hace de la siguiente manera: "*(notas+i)". Nota.­ Es posible reemplazar en el ejemplo 10.5 la manera de acceder a un dato de la forma: "*(notas+i)" a la "notas[i]".

ARREGLOS DE CARACTERES (CADENAS) Como habíamos visto en capítulos anteriores una cadena es un arreglo de caracteres, por lo tanto podemos utilizar punteros para representar cadenas. El siguiente ejemplo muestra como definir e inicializar un puntero a una cadena.

EJEMPLO 10.6 1: 2: 3: 4: 5: 6: 7: 8: 9: 10:

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

char *nombre; cout<<"Ingresa Tu Nombre Completo\n"; cin>>nombre; cout<<"Tu nombre es:"<<nombre; }

Porque es mejor usar un puntero a una cadena que solamente una cadena pues, porque con el puntero no nos limita el tamaño que vaya a tomar la cadena.

EJEMPLO 10.7 En este ejemplo se hará lo mismo que en el ejemplo 9.6 utilizando un puntero a una cadena. Se escribirá una función que permita conocer la longitud de una cadena. 1: 2: 3: 4: 5: 6: 7:

int longitud(char *cadena) { char *ptr = cadena; while( ptr[0] != '\0' ) //mientras no sea fin de cadena ptr++; return (int)(ptr-cadena); }

En la función anterior en la línea 2 se declara un puntero adicional ptr el cuál nos servirá para realizar el cálculo. En la línea tres encontramos la siguiente expresión dentro de la estructura while: ptr[0]!=’\0’ Esta expresión quiere decir que cuando la posición inicial del puntero sea fin de cadena ‘\0’ entonces el ciclo termina. En la línea 4 se encuentra la instrucción ptr++; Lo que hace es que el puntero recorra un índice a la derecha, es decir apuntará al


siguiente carácter de la cadena, de esta manera el ciclo recorrerá todas las posiciones de la cadena hasta encontrar el fin de cadena. Bien ahora la función tiene que devolver la longitud de la cadena, en la líne 5 podemos ver lo siguiente: (ptr-cadena) esto quiere decir que se restará la última posición de la cadena menos la primera, dándonos la longitud de la cadena. Además en la línea 5 se muestra (int) que es un casting, es decir que convierte en entero a las instrucciones que precede en este caso a la instrucción (ptr-cadena).

¿Por qué NO trabajar con punteros? El error más común es que cuando trabajamos con punteros vamos apuntando a diferentes valores de memoria, y cuando los dejamos de utilizar un error muy común es de no liberar el espacio de memoria a cual están apuntando lo que nos ocasionará una sobrecarga en la memoria cuando nuestros programas sean grandes. También por medio de los punteros es que se pueden tener acceso a valores privados, y podemos modificar valores haciendo que nuestros programas caigan. Este hecho es muy común en los crackers de programas, porque se valen de los punteros para cambiar valores en los programas y utilizarlos según su conveniencia. Una posibilidad que tenemos para reemplazar a los punteros es utilizar referencias.

¿Por qué trabajar con punteros? Más de una vez hemos puesto en duda el uso de punteros, pues ya que trabajamos con direcciones de memoria nos pueden provocar errores más de una vez si no tenemos cuidado, además si tengo una variable y puedo obtener directamente su valor un puntero sería redundante. Bueno, de lo que tenemos que estar seguros es donde utilizar punteros, y estos son usados con mayor frecuencia en: ­ Asignación de Memoria Dinámica ­ Paso de variables por referencia en funciones ­ Para acceder a los atributos de una clase y a sus funciones

Asignación Dinámica de Memoria Asignar dinámicamente memoria significa que personalicemos el espacio que ocuparán nuestras variables en memoria. Cuando reservamos memoria, esta permanece allí hasta que


nosotros la liberemos. Reservar o asignar memoria es una buena técnica para no desperdiciar memoria inútilmente, pues sólo reservaremos el espacio necesario, este detalle será muy significante en aplicaciones o programas grandes. Para reservar memoria utilizamos el operador new seguido del tipo de dato del cual queremos reservar memoria. Por ejemplo: int *apuntador = new int ; La anterior instrucción reservará para el puntero apuntador 2 bytes que es el tamaño de un tipo de dato int char *nombre; nombre = new char[10]; La anterior instrucción reservar para el puntero a una cadena nombre 10 caracteres Como habiamos mencionado cuando reservamos memoria permenece allí hasta que la liberemos, esta operación la realizamos con el operador delete.

delete apuntador; delete nombre;

EJEMPLO 10.8 Ingresar un nombre sin desperdicio de memoria #include <iostream.h> #include <string.h> void main() {

char *nombre; char aux[30]; cout<<"Ingrese Su Nombre\n"; cin>>aux; nombre = new char[strlen(aux)+1]; strcpy(nombre, aux); cout<<nombre<<endl; //Le doy otros usos a mi puntero nombre delete nombre; //finalmente libero el espacio de memoria }


PARTE XIII Concepto de una Función Una función es un conjunto de instrucciones independientes cuyo objetivo es el de minimizar la complejidad de un problema, descomponiéndolo en subproblemas más fáciles de resolver. Una función debe realizar una tarea específica si le damos a una función más de una puede que no estemos analizando del todo el problema. Como resultado del conjunto de instrucciones de una función, se han tenido que realizar operaciones y talvez modificación de los datos que la función tenía a disposición, generalmente este resultado se devuelve en forma de valor. Estábamos familiarizados con el uso de la función principal void main(), que siempre debe de estar en cualquier programa, pero resulta que podemos crear las funciones que nos parezcan necesarias para resolver de un manera más sencilla el problema que estemos tratando.

¿CUÁNDO UTILIZAR FUNCIONES? Para saber que tareas tenemos que tratarlas como funciones se darán unas pautas a continuación, pero las experiencia en programación será la pauta más exacta. ­ Cuando veamos que secciones o bloques de código se repiten varias veces podemos llevar esta tarea a una función, lo que nos ahora esfuerzo y evita líneas de código repetidas. ­ Cuando necesitemos realizar una operación sobre algún tipo de dato y producto de ello necesitemos un valor de respuesta. Como por ejemplo calcular el cuadrado de un número entero.

DEFINICIÓN DE FUNCIONES Una función tiene la siguiente sintaxis: <tipo> nombreF (parámetros) {


cuerpo return <expresión> }

<tipo> Es el tipo de Dato que devuelve la función. Si se coloca main la función no devuelve ningún valor. nombreF Es el nombre que le damos a nuestra función puede ser el que

queramos menos la palabras reservadas del lenguaje.

Parámetros Es un conjunto de variables, las cuales se escriben con su tipo de

dato y su nombre, separadas por comas, que vienen a constituir los argumentos de la función.

Cuerpo Es todo lo que se encuentra entre las llaves {} y contiene un

conjunto de sentencias. return Esta sentencia se usa si el tipo de dato de retorno no es void.

Return devuelve una expresión. Se pueden colocar varios returns a lo largo de un programa y cuando la función encuentra a cualquiera termina.

EJEMPLO 11.1 En el siguiente ejemplo se definirá una función para que calcule el área de un triángulo

1: #include <iostream.h> 2: int areaTriangulo( int base, int altura) 3: { 4: int area; 5: area = base * altura / 2; 6: return area; 7: } 8: 9: void main() 10: { 11: int baseT = 3, alturaT = 4; 12: cout<<"El area del triángolo es: 13: "<<areaTriangulo(baseT,alturaT); 14: } En la línea 3 podemos ver que el tipo de dato que devolverá la función es un entero (int) que el nombre de la función es areaTriangulo y tienen dos parámetros de tipo entero base y altura. El cuerpo de la función comprende todas las líneas de código desde la línea 4 hasta la línea 8.

CUERPO DE UNA FUNCIÓN


El cuerpo de una función contiene todas las instrucciones que le permiten realizar su tarea, podemos definir variables cuyo ámbito o vida tendrá duración sólo en el cuerpo de la función (variables locales). También se puede hacer llamada a otras funciones o declarar tipos de datos definidos por el usuario, en síntesis se puede trabajar en el cuerpo de una función con todas las ventajas que el lenguaje nos ofrece pero orientado a la resolución de un problema específico.

VALOR DE RETORNO Una función después de haber realizado operaciones con los datos que se le proporciona debe de devolver algo, ya sea en forma de un valor o sino haber efectuado alguna modificación con los datos o sino mostrar algo por pantalla. El valor que devuelve la función se fija con la instrucción return, cuando la función encuentra esa palabra acaba e inmediatamente devuelve el valor que se indica. En el ejemplo 11.1 en la línea 7 se devuelve el valor que contiene la variable area. Existen funciones que no devuelven ningún valor, estas llevan como tipo de dato de retorno void, pero no significan que no hacen nada, pueden realizar cálculos o simplemente mostrar algo por pantalla.

Ejemplo 11.2 #include <iostream.h> 1: 2: void mostrar(char nombre[]) 3: 4: 5: { 6: cout<<nombre; 7: 8: 9: 10: 11:

} void main() { mostrar(“UMSS”); }

ÁMBITO DE LA VARIABLES Variables locales Todas la variables que se crean dentro de el cuerpo de una función tienen ámbito o vida sólo en el cuerpo mismo de la función, estas variables son llamadas locales. Esto quiere decir que podemos utilizar estas variables sólo en la función pues al terminar esta las variables se destruyen. En el ejemplo 11.1 en la línea 5 se define la variable area, esta variable tiene


ámbito sólo en el cuerpo de la función, no podríamos acceder a esta variable desde la función principal o cualquier otra parte del programa.

Variables globales Las variables globales son definidas fuera de cualquier función, están definidas de un manera parecida a las librerías, de estas forma estas variables tienen un alcance global a todo el programa, esto quiere decir que pueden ser accedidas de cualquier parte del programa, es decir, de cualquier función. Más información

Llamada o Invocación a una función Una vez escrita la función, podemos utilizarla escribiendo su nombre y luego dándole los parámetros correspondientes: Sintaxis

NombreFuncion( parámetros ) En el ejemplo 11.1 en la línea 13 se llama a la función areaTriangulo para que el valor de retorno se muestre directamente por pantalla. En el ejemplo 11.2 se llama a la función mostrar en la línea 10. El valor que nos retorna una función podemos utilizarlo directamente o sino almacenarlo en alguna variable eso dependerá de nuestros requerimientos o simplemente de nuestra preferencia.

¿Cómo trabaja una función? Una función es un conjunto de sentencias independientes que se ejecutan cada vez que se llama o invoca a una función. Cada vez que se encuentra una llamada a una función el control del programa se pasa a la función, es decir, la ejecuta y cuando esta acaba entonces el control vuelve a la sección del programa desde donde se hizo la llamada. En cuanto a los parámetros, en el caso que utilicemos variables, no se debe de pensar de que existe alguna relación entre las variables que se pasan y las que están definidas como parámetros en la función, a menos que las referenciemos. En el ejemplo 11.1 cuando se hace la llamada a la función areaTriangulo se utiliza dos variables baseT y alturaT, estas dos variables nada tienen que ver con las variables que se definieron como parámetros de la función en la línea 13 base y altura, lo que ocurre es que baseT es correspondiente a base al igual que alturaT y altura. Lo que es importante es que las variables que se pasen sean del mismo tipo que de los parámetros definidos en la función.

Los parámetros de una función Una función puede tener de 0 a n parámetros y lo más común es que utilice los valores que guardan los parámetros para realizar operación y luego devolver un resultado, este el caso del


ejemplo 11.1 en el que la función areaTriangulo tiene dos parámetros enteros base y altura, estas variables contienen los valores a partir de los cuales se calculará el área del triángulo. Debemos tener en cuenta que los parámetros son variables locales, sólo las podemos utilizar dentro de la función.

PASO DE PARÁMETROS POR VALOR Esto significa que cuando hacemos la llamada a la función como parámetros le damos valores, si es que colocamos variables como parámetros la función solo toma los valores. En el ejemplo 11.1 en la línea 13 se llama a la función areaTriangulo así: areaTriangulo(baseT,alturaT)

Cuando el paso de parámetros es por valor viene a ser como si sólo los valores de las variables baseT y alturaT se pasarán como parámetros a la función así: areaTriangulo(3,4)

En conclusión lo más importante de esto es que después de que se ejecute la función las variables que se le han pasado no sufren ningún cambio. En el ejemplo 11.1 después de la línea 13, cuando se ha hecho la llamada a la función las variables baseT y alturaT no habrán cambiado en nada.

PASA DE PARÁMETROS POR REFERENCIA En este caso existe un forma de las variables después de haberlas pasado como parámetros en una función sufran cambios, producto de las operaciones que se realizan dentro de la función, para mostrar como funciona esta parte se resolverá el mismo problema que en el ejemplo 11.1 utilizando paso de parámetros por referencia.

Ejemplo11.3 1: 2: 3: 4: 5: 6:

#include <iostream.h>

7:

base= base * altura / 2;

8:

}

9:

void main()

void areaTriangulo( int &base, int altura) {

10: { 11: int baseT = 3, alturaT = 4; 12: areaTriangulo(baseT,alturaT); 13: cout<<"El area del triángolo es: "<<baseT;


}

Para que los cambios de un parámetro se reflejen se debe de utilizar el operador de referencia &, en el ejemplo anterior en la línea 3 en la definición de la función se utiliza el operador & que va delante de la variable base, esto quiere decir que lodos los cambios que se hagan sobre esta variable en la función, tendrán efecto en la variable que se utilice al hacer la llamada, baseT en el anterior ejemplo. En la línea 11, se llama a la función: areaTriangulo(baseT,alturaT);

En este caso la variable baseT es la correspondiente a la variable base de la función areaTriangulo todos los cambios que se realicen en la variable base afectarán a la variable baseT. Después de la línea 11 la variable baseT habrá cambiado conteniendo el área del triángulo. ¿Por qué ocurre esto?. Porque ya no se pasan simplemente valores sino de pasa un dirección de memoria.

EJEMPLO 11.4 Escribir una función que calcule los primeros 10 números primos. #include <iostream.h> int esPrimo( int nro) { for(int i=2; i<= nro/2 ; i++) if (nro % i == 0) return 0; return 1; }

1: 2: 3: 4: 5: 6: 7: 8: 9: 10: void main() 11: { 12: int nroPrimo = 0, contador = 1; 13: while( nroPrimo < 10) 14: { 15: if (esPrimo(contador)) 16: { 17: nroPrimo++; 18: cout<<"El "<<nroPrimo<<"º número primo es: 19: 20: "<<contador<<endl; 21: } 22: contador++; 23: }

}


PARTE XIV Programación Orientada a Objetos (POO) La programación orientada a objetos es un técnica utilizada por los programadores para adaptar el trabajo de programar a la Psicología y Filosofía humana. Es una forma humana de programar y plasmar en programas de computadora objetos de la vida real, por ejemplo puedo modelar en un programa de computadora un mamífero como un gato, suena algo complicado pero más adelante veremos que no es así.

En la realidad podemos considerar a un objeto como todo aquello que ocupa un espacio, tiene volumen y además podemos percibirlo por nuestros sentidos, ya sea animado o inanimado. Un objeto puede ser una casa, un animal, una silla, etc. Para hacer un programa orientado a objetos debemos primero identificar que objetos vamos a necesitar para resolver el problema que estemos tratando, para hacer esto nos guiaremos en como un objeto es en la vida real. Una vez que hagamos este análisis estaremos listos crear primero las clases y luego los objetos en nuestro programa. Ahora entrando en más detalles de las características de la Programación Orientada a Objetos, esta encapsula datos (atributos) y funciones (comportamientos) en objetos, los datos y funciones están íntimamente relacionados entre sí. Los objetos tienen la propiedad de ocultamiento de información, esto significa que si bien saben como comunicarse entre si a través de interfaces bien definidas, normalmente no se permite que un objeto sepa como están implementados otros objetos.

POR QUE UTILIZAR PROGRAMACIÓN ORIENTADA A OBJETOS Porque podemos hacer que el trabajo de programar sea más sencillo, nuestros programas será serán más claros y ordenados. Por ejemplo si quiero almacenar la edad de una persona, tengo que hacerlo en una variable de tipo entero (int), si quiero almacenar su nombre tendré que


utilizar una cadena, y si quiero otros datos de la persona tendré que seguir creando variables. Porque no crear una variable de tipo persona directamente que de una sola vez contenga todo lo que quiero saber de una persona, como su nombre, edad, sexo, etc. Esto es posible, precisamente es lo que nos permite hacer la programación orientada a objetos, podemos crear una variable persona que contenga muchos datos de una sola vez, pero no le llamaremos variable sino clase, podemos crear clases en un programa y después las podemos utilizar. CONCEPTO DE CLASE Una clase es una agrupación de datos (atributos), generalmente contenidos en variables, y de funciones, (comportamientos) que operan sobre esos datos.

DEFINICIÓN DE UNA CLASE Sintaxis class {

nombreClase

datos funciones

};

nombreClase Es cualquier nombre que elija para darle a mi clase, menos palabras reservadas del lenguaje. datos Son los datos o atributos que tendrá mi clase, como son generalmente variables, se debe definir las variables en esta parte. funciones Se debe escribir la definición de las funciones Una clase se la crea inspirada en un objeto de la vida real, por ejemplo quiero modelar un gato en un programa entonces tengo que escribir una clase que se llame gato. Como sigue: class gato { };

Al anterior ejemplo todavía no contiene ningún atributo ni tampoco ninguna función pero la iremos refinando poco a poco. También podemos crear clases que en la realidad no se consideren como un objeto por ejemplo una clase hora.

ABSTRACCIÓN


Abstracción significa considerar aisladamente las cualidades de un objeto, consiste en rescatar las características más importantes de algo y representarlo de una manera más simplificada. En el ejemplo de la construcción de nuestra clase gato se debe de abstraer las cualidades más importantes de un gato y de esta forma podremos representarlo en un programa de computadora. class gato { char color[20]; //atributo int vidas; //atributo void miau() //comportamiento

{

cout<<”Miiaaauu!!!“;

};

}

Ahora la clase gato esta más completa porque se han identificado las cualidades más importante de un gato, en este caso hemos dicho que un gato tiene un color y tiene vidas como atributos y además de ello dice miau que es una forma de comportase, esta es un forma muy simplificada de describir a un gato pero nos basta para crear la clase gato. A los datos dentro de una clase se les llama variables miembro y a las funciones se les llama funciones miembro.

ENCAPSULACIÓN La encapsulación es una característica de la POO que trata de mantener unidos los datos y los comportamientos de una entidad u objeto. Una clase encapsula atributos y funciones lo que hace posible el ocultamiento de información, que quiere decir que cuando yo quiera usar una determinada clase, creando objetos de ella, no necesito conocer los detalles de su implementación. Si nuestra clase gato la utilizaría un extraño cuando utiliza la función miau() sólo tiene que saber que con esa función el gato maulla pero no como es que esta hecha la función.

CONTROL DE ACCESO A LOS MIEMBROS Entendemos por miembros a todos los atributos y funciones, para controlar el acceso a los miembros de una clase se utilizan tres tipos de controladores: public (público), private (privado) y protected (protegido). Con estos controladores le damos ciertas restricciones de acceso a los miembros de nuestra clase. Todos los miembros, tanto atributos como funciones, que sean declarados como privados sólo pueden ser accedidos desde funciones pertenecientes a la clase. Los miembros que sean declarados públicos pueden ser accedidos desde cualquier parte del programa. Refinando más nuestra clase gato quedaría de la siguiente manera:


class gato { private: char color[20]; //atributo int vidas; //atributo public: void miau() //comportamiento

{ cout<<”Miiaaauu!!!“; } };

Generalmente los datos o atributos son privados porque no queremos que nadie los conozca y no tengan acceso a ellos. Las funciones en cambio son publicas para que puedan ser accedidas y de esta manera manipular la clase.

ACCESO A LOS MIEMBROS DE UNA CLASE Para tener acceso a los miembros de una clase podemos hacerlo desde dos partes del programa: ­ Desde dentro de la clase, accedemos a cualquier miembro directamente por el nombre, si es una variable por el nombre que le dimos a la variable y si es una función de igual manera por su nombre. ­ Desde fuera de la clase, podría ser desde la función principal o cualquier otra sección del programa que no pertenezca a la clase. Para acceder a un miembro lo hacemos de la siguiente manera NombreObjeto.miembro Utilizamos un punto entre el nombre del Objeto, que pertenece a una clase, y el miembro.

Concepto de Objeto Un objeto es un elemento declarado de una clase este se denomina objeto de la clase. Una vez definida e implementada una clase, es posible declarar o crear elementos de esta clase de modo similar a como se declaran las variables del lenguaje (int, double, char, …). De una única clase se pueden declarar o crear numerosos objetos. La clase es lo genérico: es el patrón o modelo para crear objetos.


DEFINICIÓN DE UN OBJETO Sintaxis

nombreClase nombreObjeto; nombreClase Es el nombre de la clase que hemos creado y de la cual queremos crear un objeto o una instancia. nombreObjeto Cualquier nombre que queramos menos palabras reservadas. Ahora vamos a crear objetos de nuestra clase gato en la función principal: void main() { gato Tom, Gardfield; Tom.miau(); Gardfield.miau(); }

Cada objeto tiene sus propias copias de los miembros de la clase, con sus propios valores, en general distintos de los demás objetos de la clase. Para tener acceso a los miembros de un objeto desde fuera de la clase, se utiliza el punto entre el nombre del objeto y el nombre del miembro, como se muestra en el ejemplo anterior.

CLASES VS OBJETOS La relación entre clases y objetos en los programas de computadora es muy similar al de las variables por ejemplo si tengo int nota;

gato Tom; gato es a Tom como int es a nota, int es un tipo de dato, gato es un tipo de dato definido por el usuario, ambos son tipos de datos, nota es el nombre de la variable, y Tom es el nombre del objeto. nota es una variable entera en donde se almacenan sólo un dato entero. Tom es un objeto que puede almacenar varios tipos de datos y además tiene funciones propias de su clase.


Inicialización de Objetos de Clase (CONSTRUCTORES)

Cuando se crea un objeto de alguna manera tenemos que inicializar los valores de sus atributos para que no contengan un valor disparado o queramos fijarlos a un determinado valor inicial. La inicialización de los atributos lo podemos hacer mediante el constructor de la clase. El constructor es una función que no tiene tipo y se llama de la misma forma que la clase, y es invocada cada vez que se crea un objeto de la clase automáticamente. En nuestro ejemplo de la clase gato sería así: class gato { private: char color[20]; //atributo int vidas; //atributo public: gato(char c[]) //constructor { strcpy(color,c); vidas = 9; } void miau() //comportamiento

{ cout<<"Miiaaauu!!!"; } }; void main() { gato Tom("blanco"), Gardfield("negro"); }


Como dijimos que nuestro constructor es una función entonces puede tener parámetros o no, depende de nuestros requerimientos, el constructor de la clase gato recibe un parámetro que es el color, lo que quiere decir que al momento de crear un objeto le daremos el color del que quiero que sea mi gato. Además en el constructor se inicializa el número de vidas en 9, es decir, que cada objeto de la clase gato que se cree tendrá 9 vidas.

Obtener atributos de una Clase Habíamos mencionado que cuando un atributo es privado no se puede acceder desde fuera de la clase, entonces para poder obtener el valor de este atributo tenemos que crear una función que nos haga este trabajo, y si quisiéramos cambiar este valor también tendríamos que crear una función para este propósito. Veamos como podemos hacer esto en nuestra clase gato: class gato { private: char color[20]; //atributo int vidas; //atributo public: gato(char c[]) //constructor { strcpy(color,c); vidas = 9; } void miau() //comportamiento

{ cout<<"Miiaaauu!!!"; } int devVidas() //función miembro { return vidas; } };


void main() { gato Tom("blanco"), Gardfield("negro"); cout<<”Tom tiene ”<<Tom.devVidas()<<” vidas”; }

La función devVidas devuelve el valor de la variable vida que esta encapsulada dentro de la clase gato. Si hubiéramos utilizado en la función principal directamente la siguiente función: cout<<”Tom tiene ”<<Tom.vidas<<”vidas”; Existiría un error porque estamos violando los controles de acceso a las variables, vidas es un variable privada. Si vida fuera publica la anterior sentencia estaría correcta.

Modificar atributos de una clase Para cambiar el valor de un atributo fuera de la clase debemos de construir una función que nos realice este trabajo. En la clase gato si queremos modificar el valor del atributo vidas será de la siguiente manera: class gato { private: char color[20]; //atributo int vidas; //atributo public: gato(char c[]) //constructor { strcpy(color,c); vidas = 9; } void miau() //comportamiento

{


cout<<"Miiaaauu!!!"; } int devVidas() //función miembro { return vidas; } void modVidas(int v) //función miembro { vidas = v; } }; void main() { gato Tom("blanco"), Gardfield("negro"); cout<<"Tom tiene "<<Tom.devVidas()<<" vidas"; Tom.modVidas( Tom.devVidas() - 1 ); cout<<"Tom tiene "<<Tom.devVidas()<<" vidas"; }

La función modVidas recibe un parámetro que es el nuevo valor que contendrá la variables vidas. Con la sentencia: Tom.modVidas( Tom.devVidas() - 1 ); se disminuye en 1 el valor del atributo vidas. Podemos ver que dentro de la función modVidas para acceder a la variable vidas se lo hace directamente, esto es porque lo estoy haciendo desde una función de la misma clase.

Implementación de una función fuera de la clase Es posible declarar una función dentro de la clase, e implementarla fuera de ella como se muestra a continuación:

class gato { private:


char color[20]; //atributo int vidas; //atributo public:

gato(char[]); //declaración del constructor void miau(); //declaración de la función }; gato::gato(char c[])//implementación del constructor {

strcpy(color,c); vidas

= 9;

} void gato::miau()//implementación de la función {

cout<<"Miiaaauu!!!"; }

Para implementar una función fuera de la clase se debe de declararla tan solo dentro de la clase, y para implementarla fuera de la misma se debe de colocar primero el tipo de la función luego la clase a la que pertenece junto se colocan 4 puntos (::) y el nombre de la función, luego se deben de declarar todos los parámetros que tiene la función. En la declaración de la función dentro de la clase no es necesario darle un nombre a las parámetros basta con el tipo, el nombre se les dará cuando se implemente la función.

Ejemplo 12.1 Simular la pelea de dos gatos, crear dos objetos gato e implementar una función que le permita a un gato arañar a otro gato, cada arañazo que recibe un gato le quita una vida. El programa debe de decidir de forma aleatoria que gato es arañado, todo esto mientras ninguno de los gatos tengan 0 vidas. Al final del programa deberá de decir que gato ganó. #include <iostream.h> #include <string.h> #include <stdlib.h>


class gato { private: char color[20]; //atributo int vidas; //atributo public: gato(char c[]) //constructor { strcpy(color,c); vidas = 9; } void miau() //comportamiento

{ cout<<"Miiaaauu!!!\n"; } int devVidas() //función miembro { return vidas; } void modVidas(int v) //función miembro { vidas = v; } void arania(gato &otroGato) {

otroGato.modVidas( otroGato.devVidas() ­ 1 ); otroGato.miau(); }


}; void main() { gato Tom("blanco"), Gardfield("negro"); int quienArania; randomize(); //para que se generen nros randomicos distintos while( Tom.devVidas() > 0 || Gardfield.devVidas() > 0 )

{ quienArania = random( 2 ); if ( quienArania ) Tom.arania( Gardfield ); else Gardfield.arania( Tom ); } if(Tom.devVidas() == 0)

cout<<"Ganó Gardfield"; else

cout<<"Ganó Tom"; }

Ejemplo 12.2 Construir un tipo de dato que nos permita manejar fracciones, es decir, que este tipo de dato tenga información del numerador y denominador. Cuando se cree un objeto de esta clase deberá tener valores iniciales de 0, tanto en el numerador como en el denominador, y además debe de poder realizar las siguientes funciones:

mostrar. Muestra un quebrado


llenar. Llena los datos del quebrado

sumar. Suma de dos quebrados multiplicación. Multiplica dos quebrados simplificar. Simplifica un quebrado #include <iostream.h> class fraccion { private:

int nume; int deno; public: fraccion() //constructor { nume=0; deno=0; } //muestra la fracción por pantalla void mostrar(); //llena con datos las variables de la fraccion void llenar(int,int); //la función sumar recibe como parámetro un tipo de dato fraccion // y devuelve el resultado como un tipo de dato fraccion fraccion sumar(fraccion); //la función multiplicar recibe como parámetro un tipo de dato fraccion // y devuelve el resultado como un tipo de dato fraccion. fraccion multiplicar(fraccion);


//simplifica una fraccion void simplificar(); //la funcion euclides calcular el mínimo común divisor de dos nros int euclides(int,int); }; void fraccion::mostrar() {

/* Si la fraccion tiene denominador 1 se mostrara solo el numerador ó Si la fraccion tiene como numerador 0 se mostrara sólo 0 */ if((deno == 1) || (nume == 0)) cout<<nume<<"\t"; //Sino se muestra toda la fraccion else cout<<nume<<"/"<<deno<<"\t"; } void fraccion::llenar(int n, int d) {

nume=n; deno=d; } int fraccion::euclides(int nro1, int nro2) {


int aux; while( nro1 > 0 ) { if(nro1 < nro2) { aux = nro1; nro1 = nro2; nro2 = aux; } nro1 = nro1 ­ nro2; } return nro2; } void fraccion::simplificar()

{ int mcd; mcd = euclides(nume, deno); nume /= mcd; deno /= mcd; } fraccion fraccion::sumar(fraccion otraFracc) {

fraccion aux; int mcm = deno * otraFracc.deno; aux.nume=(mcm/deno)*nume + (mcm/otraFracc.deno)*otraFracc.nume;


aux.deno=mcm; return aux; } fraccion fraccion::multiplicar(fraccion otraFracc) {

fraccion aux; aux.nume=nume * otraFracc.nume; aux.deno=deno * otraFracc.deno; return aux; }

En el anterior ejemplo se muestra como esta implementada la clase fracción, ahora veamos cómo se usa: void main() { fraccion A,B,C; A.llenar(1,2); B.llenar(2,2); A.mostrar(); B.mostrar(); C = A.sumar(B); C.simplificar(); C.mostrar(); C = A.multiplicar(B); C.simplificar(); C.mostrar(); }



Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.