C Programming

julio 28, 2011

Greetings fellows. I propouse to myself to make a simple and powerfull guide for advanced C programming, focousing on memory management issues and then, explain a way to make rich abstractions and to practice my poor english too :) .

Saludos amigos. Me propongo a hacer una guia simple y poderosa para programación en C avanzada, enfocandome en problemas del manejo de memoria y entonces explicar una manera de conseguir abstracciones ricas en C.

Google indexa flash

julio 1, 2008

Hoy me desayune la grata noticia de que google ya sabe crawlear paginas hechas con flash. Cae una de las barreras mas importantes de flex y flash en general.

http://googleblog.blogspot.com/2008/06/google-learns-to-crawl-flash.html

Parece ser entonces que lo que hicieron para explorar los swf los muchachos de google es usar los controles de usuario. Sacando conjeturas, supongo que habran hecho bots capaces de reconocer los controles y sabiendo usarlos.

Lo que mejor indexa el google de los sitios y widgets flash es el texto que ve el usuario (despues de todo la indexación esta basada en el escaneo de la interface).

Lo que todavía no indexa (02/07/2008 dd/mm/aaaa) son las imagenes incluidas en dentro de los swf.

Una piedra importante sale del camino de las aplicaciones RIA.

Orientación a Objetos v1.0

Como vimos antes, los paradigmas son lineas de pensamiento que nos dan herramientas y abstracciones / formas de asbtraccion para poder plantear / estudiar / resolver un problema de cierto tipo en cierto entorno.
De los paradigmas imperativos, el paradigma de objetos es un de los mas conocidos: el mas hablado y el menos usado. Esto se debe, a mi juicio, a la falta de conocimiento del paradigma de objetos: es muy facil programar en java, lo complicado es programar pensando en objetos.

En el caso de la orientación a objetos (OO en adelante), el paradigma nos ofrece dos elementos sobre los que se basan todos los cimientos: Objetos y mensajes.

La nocion de programa en OO es un ambiente en el que conviven objetos, con responsabilidades conocidas y definidas que representan entes de la realidad y se relacionan y comunican entre ellos a travez de mensajes para lograr la solución a traves del trabajo cooperativo.

Asi entonces se puede decir que cada objeto tiene un comportamiento y un estado asociado y se espera que responda y trabaje en equipo con los demas.

La forma de enfocar la resolución de problemas con este paradigmas entonces es tan sencilla y tan complicada como la concepcion de objetos que representen distintos entes y conceptos reales y la adjudicación de reponsabilidades, lo que termina determinando la forma de interrelación entre los objetos.

Una vez modelada la solucion en función de los objetos protagonistas, se pasa a pensar en las clases o en los prototipos de los objetos.

Algunas de las caracteristicas principales del paradigma orientado a objetos son:

    • Objetos

Abstracciones computacionales de entes reales

    • Mensajes

Pedidos que le puedo hacer a un objeto para poder
interactuar con el

    • Polimorfismo

Permitir que dos objetos puedan ser tratados
de la misma manera por un tercero.

    • Herencia

Capacidad de definir objetos extendiendo el
comportamiento de objetos existentes, algo asi como una
evolución natural.

    • Encapsulamiento

Un objeto solo conoce su implementación y no conoce
la implementación de los demas, solo necesita saber
de los demas los mensajes que les puede enviar.

Mas adelante vamos a adentrarnos en estas y otras caracteristicas e ir macheandolas
con ejemplos en distintos lenguajes.

Algunas analogías normales a la forma de pensamiento sistematica modularizada del paradigma OO pueden ser:

Cuerpo Humano:
En el cuerpo humano cada organo hace su trabajo, y comunican necesidades a traves de encimas y otros químicos, trabajando en equipo
y haciendo que el cuerpo funcione.

Empresa:
Una empresa tiene departamentos, conformados por personas con responsabilidades. A su vez, existen canales formales para comunicar
las necesidades y dar a conocer estados.

Algunos lenguajes que dan soporte a orientación a objetos de manera nativa son:

Smalltalk
C++
Objective-C
Python
PHP
Java
Ruby
C#
ASP
Action Script
Java Script
Perl
Delphi
ABAP

Nota: Este texto supone que se sabe que es una estructura de datos recursivas (nodos de listas, colas, pilas, árboles, etc.) y como se la programa en C e intenta darle una vuelta de rosca a ese conocimiento.

El lenguaje C es uno de los lenguajes de más bajo nivel (relativo) que existe. En este lenguaje la memoria se estructura de manera plana, que es en definitiva lo que es la memoria, un espacio plano de almacenamiento temporal.

Así entonces un nodo de estructura dinámica como el siguiente:

struct empleado{
int idEmpleado;
char* nombre;
char codigoPostal[6];
int idDepto;
struct empleado* sgte;
}

No es una estructura dimensional, sino un manojo de bytes ordenados:

(
Suponiendo arquitectura intel x86 32bits
int = >4 bytes
Dirección de memoria => 4bytes
char x 6 => 6 bytes
)

id nombre Codigo depto siguiente
[][][][] [][][][] [][][][][][] [][][][] [][][][]

Los cuales son interpretados cada uno como entero, puntero a caracter, entero, entero, entero.
En otras palabras, puede ser claramente un vector de bytes, donde a cada subconjunto de bytes se los interpreta como un tipo de datos nativo según la información de la definición de la estructura.

Bien, ahora supongamos que tenemos esta otra estructura bastante distinta:

struct empresa{
char* idEmpresa;
char* razonSocial;
long int cuit;
char* direccion;
char codigoPostal[6];
struct empresa* sgte;
};

Cuando hacemos funciones de acceso a cola (por ejemplo) siempre tenemos la maldita sensación de estar haciendo las mismas cosas miles de veces, puesto que si bien no es lo mismo un empleado y una empresa,
¡¡Las colas son todas iguales!!
¡¡El mecanismo si es el mismo, agrego al final, saco del principio!!

¿Cómo hacer para separar el “¿Qué?” del “¿Cómo?”?

Con el conocimiento que tenemos ahora de la memoria y la estructuración en memoria de las estructuras, existe al menos una forma de hacerlo.

¿Qué tienen en común todos los nodos de una estructura de datos dinámica / recursiva?
Rta.: El puntero al siguiente nodo.

¿Qué tienen en común todos los punteros en una misma arquitectura hardware / sistema operativo?
Rta.: El puntero es un tipo de datos, no importa lo que apunte, siempre pesa lo mismo.

Si planteamos la siguiente estructura:

Struct Nodo {
Struct Nodo* sgte;
};

Tenemos una estructura que el primer valor es un puntero un siguiente nodo, no tenemos variable “contenedor”, y no la necesitamos, puesto que ahora no nos importa el contenido de información, sino el puntero siguiente.

Un programa hecho en C, interpreta los datos según el tipo del mismo en el instante de ejecución dado.

Si yo modificase las estructuras anteriores y pusiese el elemento siguiente primero en la lista, quedaría esto:

struct empleado{
struct empleado* sgte;
int idEmpleado;
char* nombre;
char codigoPostal[6];
int idDepto;
}

struct empresa{
struct empresa* sgte;
char* idEmpresa;
char* razonSocial;
long int cuit;
char* direccion;
char codigoPostal[6];
};

Ahora, la última pregunta a hacernos es:
¿Qué tienen en común nuestras tres estructuras?
Rta.: Las tres empiezan con un puntero conceptualmente igual, el puntero al siguiente elemento.

Como se dan todas estas relaciones, entonces, gracias a la existencia del “casteo”, que hace que el programa interprete un dato como otro, sin afectarlo en el proceso, entonces, podemos definir todas las funciones para manejo de Colas para la estructura mas chica.

#define null NULL
#include
#include

typedef struct Nodo {
struct Nodo* sgte;
}Nodo;

typedef struct Cola {
Nodo* head;
Nodo* tail;
}Cola;

typedef struct Empleado{
struct Empleado* sgte;
int idEmpleado;
char* nombre;
char codigoPostal[6];
int idDepto;
} Empleado;

void inicializarCola (Cola* unaCola) {
unaCola->head = null;
unaCola->tail = null;
}

void agregarNodo (Cola* unaCola, Nodo* unNodo){
unNodo->sgte = null;

if ( unaCola->tail != null) {
unaCola->tail->sgte = unNodo;
}
unaCola->tail = unNodo;

if (unaCola->head == null) {
unaCola->head = unNodo;
}

}

Nodo* obtenerNodo (Cola* unaCola) {
Nodo* retorno;
retorno = unaCola->head;
if ( unaCola->head != null ) {
unaCola->head = unaCola->head->sgte;
}
return retorno;
}

int main (void) {

Cola unaCola;
Empleado* unEmpleado;
int i;
inicializarCola(&unaCola);

for (i = 0; i codigoPostal), ”, 6);
unEmpleado->idDepto = i;
unEmpleado->idEmpleado = i * 2;
unEmpleado->nombre = null;
agregarNodo(&unaCola, (Nodo*)unEmpleado);

}

while ((unEmpleado = (Empleado*) obtenerNodo(&unaCola)) != null) {
printf (” Id Empleado: %d \tId Depto: %d \n”, unEmpleado->idEmpleado, unEmpleado->idDepto);
}

return 0;
}

/*
Nota: Ejemplo probado con GCC y MinGW. No incluye el manejo de cadenas y la creación de empleados por una función dedicada por cuestiones de tiempo.
*/

Y con esto, tenemos el algoritmo de inserción y obtención de colas para cualquier nodo que tenga como primer dato de estructura el puntero al siguiente valor.

Como se puede ver a simple vista, esto de poder usar la misma función para distintos tipos de datos en los parámetros tiene cierto potencial.
Esta posibilidad de, por medio de casteo a estructuras menores de igual forma es una forma de emular el llamado Polimorfismo paramétrico (que no es el polimorfismo de objetos, sino, el de funcional)

Paradigmas v1.0

Antes de hablar de programación y de las distintas formas que hay para resolver un problema, esta bueno ir un poco más allá y pensar en:

“¿Qué es una forma de resolver un problema?”

Como en todas las ramas del conocimiento, en la programación existe la noción de Paradigma.

Un paradigma, en general, plantea una forma de encarar los estudios y / o problemas, ejemplos claros son los paradigmas de psicología, que existen las distintas escuelas, que van desde la gestalt a el psicoanálisis, postulando formas de estudiar el comportamiento humano completamente distintas, pese a buscar siempre el mismo fin.

Entonces, los paradigmas, son herramientas conceptuales que se encuentran completamente en el mundo de los pensamientos que dan al programador las nociones y formas de abstracción que sirven para resolver problemas.

Algunos de los paradigmas hoy vigentes se clasifican de esta manera:

· Imperativos

o Estructurado – Procedural

o Orientado a Objetos

o Aspectos

o Orientado a procesos (concurrencia)

· Declarativos

o Orientados a lógica

o Orientados a funciones (del tipo matemáticas)

o Orientados a Consulta / Almacenamiento

Este texto contempla solo las dos grandes clasificaciones: Imperativos y Declarativos.

Paradigmas Imperativos

Estos paradigmas se caracterizan principalmente por el hecho de preocuparse por el problema a resolver (“que”) y por “como” resolverlo.

Cuando un piensa en la resolución de un problema, tiene que pensar en todos los pasos a dar para resolverlo. Luego, a la hora de programar, cada uno de esos pasos se transforma en una instrucción o mejor dicho, un mandato (de ahí la calificación de imperativo).

Paradigmas Declarativos

Estos paradigmas se caracterizan, principalmente, por preocuparse de el problema (“que”) y no del “como” resolverlo. En general, los lenguajes que soportan este tipo de paradigmas, tienen un motor que se encarga de interpretar el “que” y transformarlo en una solución.

Cuando uno piensa en la resolución de un problema en este tipo de paradigmas, tiene que modelar el problema en el marco del paradigma concreto y expresar al motor la necesidad asociada para que el lo resuelva.

Ejemplo

Problema:

Necesitamos conseguir una entrada para el recital de Iron Maiden.

Solución 1:

Sabiendo que estamos en un living en un 7mo piso, y a 3 cuadras a la izquierda y dos adelante (tomando como referencia la puerta del edificio) del lugar de venta, y que tenemos la plata en la mesita de luz:

· caminamos hasta el cuarto

· abrimos la mesita de luz

· agarramos la cantidad de plata necesaria

· vamos hasta la puerta

· llamamos el ascensor

· entramos en el ascensor

· apretamos el botón a planta baja

· salimos del ascensor

· salimos del edificio

· caminamos 3 cuadras a la izquierda

· doblamos a la derecha

· caminamos 2 cuadras

· entramos en el local

· compramos la entrada

Solución 2:

Sabiendo que existe el service chart, que tenemos tarjeta de crédito y tenemos teléfono:

· Llamamos al service chart

· Pedimos que nos envíen la entrada

· Damos el código de tarjeta

· Esperamos la entrada J

Puntos en común:

· Ambas formas requieren recursos

· Ambas formas resuelven el problema

Puntos distintos

· La primer forma es mas económica en plata

· La segunda forma es mas económica en tiempo de la persona

· La primer forma solo sirve si estoy siempre en el mismo lugar

· La segunda forma sirve siempre, el service chart es el que se encarga de saber “como”, a mi solo me importa el “que”

Después de ahondar más en los distintos paradigmas voy a volver sobre esta calificación, para poder generalizar los features, que son en definitiva los que hacen que exista la calificación “Imperativo” y “Declarativo”

Seguir

Get every new post delivered to your Inbox.