viernes, 6 de julio de 2007

Primeros pasos del proyecto Frikicoder

Tengo algunas noticias para los virtuales futuros lectores de este blog. Hace poco he creado una cuenta en sourceforge.net y estoy planeando iniciar un proyecto para diseñar las librerías para TAD's basadas en el código que he venido usando desde hace un par de meses.

Estas librerías pretenden ser completamente orientadas a objetos y más sencillas de usar que las librerías estándar de C++. En este blog se publicará la documentación necesaria para su uso, y los que quieran animarse a unirse al grupo de desarrollo de sourceforge son bienvenidos. Este será mi primer proyecto formal así que están invitados a participar todos los que tengan la voluntad, sin importar la experiencia ni los conocimientos que tengan.

Les tendré informados de más avances y pronto iniciaré una campaña de marketing y promoción del blog, así que si eres visitante y te ha gustado el sitio te invito a que dejes tus comentarios (o críticas) y si tienes la voluntad de promocionarlo tu ayuda sera bien recibida.

Sin más que agregar por el momento, se despide su blogmaster, Odin.

domingo, 1 de julio de 2007

Operadores New y Delete

Los programas pequeños no suelen ocupar demasiado espacio en memoria, por lo que no es común preocuparse por esta y se declaran al inicio del programa todas las variables que se usaran en su ejecución. Pero cuando se trabaja con una aplicación demasiado grande y pesada esto se vuelve ineficiente porque se cargan en memoria muchos datos que no se utilizaran a menos que sea en tareas específicas.

El gasto de memoria en la ejecución de un programa puede ser controlado de muchas maneras, y una de las herramientas más útiles para un programador son los operadores new y delete. Aunque pueden ser muy confusos porque su uso se combina con punteros es posible utilizarlos de la manera adecuada si se comprende su funcionamiento y se trabaja ordenadamente. El uso de new y delete es realemente importante al trabajar con Tipos Abstractos de Datos (TAD) y permite un mejor manejo de objetos además de la creación de arreglos de diferentes tamaños en tiempo de ejecución.

Al crear variables dinámicamente la única forma de referenciarlas es por medio de su puntero, ya que no poseen un nombre de variable, y no se destruyen automáticamente al finalizar el programa. En C++ hay que borrar estos datos por medio del operador delete al finalizar su uso, aunque existen otros lenguajes que se encargan automáticamente por medio de un sistema de "recolección de basura". En un programa corto es sencillo controlar los objetos que se desecharan, pero en programas largos que implementan TAD's es fácil perder el rastro de un objeto debido a que los punteros cambian de objetivo constantemente. Para evitar estas fugas de memoria es importante organizar adecuadamente el programa y asegurarse que cada parte de su funcionamiento este debidamente aislada y documentada.

La separación adecuada de los distintos procesos de una aplicación es una práctica muy recomendable para una utilización más óptima de la memoria. Es mucho mejor utilizar las variables en el entorno de función en lugar de las variables globales, incluso es recomendable que las variables declaradas en main sean solamente las necesarias para la ejecución básica del programa, y que las funciones específicas manejen sus propias variables. Esto también da mayor robustez al código y evita que los datos se sobreescriban inesperadamente
provocando pérdida de información.

Variables y Tipos de Datos

Las variables son útiles cuando necesitamos trabajar con datos y queremos que no sean volátiles; es decir, que se conserven por un tiempo determinado, por ejemplo, mientras ejecutamos el programa.

Como programadores escribiremos varios programas para distintas situaciones, por lo tanto necesitaremos distintos tipos de datos. Muchos lenguajes de programación no necesitan definir los tipos de datos, pero siempre es mejor hacerlo porque de esa manera se sabe con lo que se esta trabajando. En C++ siempre es necesario definir el tipo de dato.

Los datos básicos se podrían definir como numéricos y alfanuméricos, pero debido a que cada variable utiliza una porción de la memoria de la computadora es importante controlar el tamaño de las variables, sobre todo las numéricas.

Los tipos de datos numéricos pueden ser específicamente para cantidades enteras o contener valores decimales. Los valores enteros simples generalmente son los que ocupan menos memoria, mientras que los datos decimales dobles o los enteros largos generalemente son los más pesados.

Los caracteres alfanumericos se almacenan solamente uno por datos, para almacenar palabras sería necesario utilizar arreglos que se verán más adelante, algunos lenguajes de programación tambien soportan tipos de datos para almacenar palabras y oraciones directamente, pero C++ no cuenta con esta función.

Finalmente existe un tipo de dato especial que solamente admite valores de verdadero o falso (0 ó 1 en su defecto) que es el tipo booleano, o también conocido como bool.

Punteros

Usualmente cuando trabajamos con una variable hacemos referencia directa al espacio de memoria reservado por medio del nombre de la variable. Esto es eficiente con variables pequeñas que se trabajaran dentro de un fragmento de código determinado, por ejemplo: la función main u otra función definida por el usuario.

Pero hay ciertas ocasiones en las que es más adecuado hacer referencia a una variable por medio de un puntero, debido a que de esta manera se pueden realizar operaciones más complejas. Un puntero es una variable especial que almacena la direccion de memoria de otra varialbe específica.

El uso de punteros puede llegar a ser muy complejo, y es el martirio de muchos programadores, pero es posible llegar a manejarlos si se comprende su funcionamiento interno. Al manejar un dato por medio de un puntero el sistema utiliza dos variables en lugar de una sola, en espacios de memoria distintos. Una es la que contiene el dato y la otra, que es el puntero, contiene la dirección de memoria de la primera; el valor del puntero puede cambiar y apuntar hacia una nueva variable sin que eso afecte en lo absoluto al dato de la primera variable.

Funciones

Hay ocasiones en las que un fragmento de código se utiliza varias veces a lo largo de un programa. Para mayor comodidad del programador se crearon las funciones, cuya principal utilidad es reutilizar fragmentos de código que se usaran varias veces o también un mayor orden en el programa.

Las funciones pueden dividirse en dos: las funciones, que retornan un valor, y los procedimientos, que no retornan nada. Aunque en la práctica resultan ser muy similares sus aplicaciones pueden ser muy distintas.

En C++ las funciones se trabajan a partir de un prototipo definido por el usuario. Ahi se define el nombre de la función que servira para llamarla en otras partes del código, los argumentos que recibirá y el tipo de dato que retornará. Es importante que el dato de retorno sea del mismo tipo que el especificado en el prototipo. Los tipos de datos también pueden ser datos definidos por el usuario.

Cuando una función no devolverá ningun dato (procedimiento) su tipo de dato se escribe como void. Estos procedimientos se utilizan sobre todo para operaciones rutinarias como imprimir en pantalla un mensaje; una función, en cambio, puede ser muchas veces parte necesaria de un algoritmo.

Arreglos

Un arreglo es una serie de variables anidadas con el mismo tipo de dato, se utilizan para manejar grupos de datos similares sin tener que declararlos uno por uno, ahorrando espacio en el código y tiempo para el programador.

Al declarar un arreglo se reserva todo el espacio en memoria necesario para esa cantidad de variables, todo en un solo bloque dividido en celdas. La variable que ha sido declarada como arreglo designa a todo ese espacio reservado, y si se quisiera accesar a una celda en especifico se tien que especificar mediante un operador, que generalmente es [].

Para recorrer el arreglo se utilizan ciclos de repeticion como for. Las cadenas de caracteres son casos especiales de arreglos que pueden ser manejados directamente en muchos casos, pero siempre es posible accesar a un caracter en especifico.