Publicado el Deja un comentario

Programando en C: Refactorización

Capítulo 12: Re factor izada Cion

En las 2 U anteriores, de manera más o menos consciente, menos hemos preocupado tanto de implementar nuevas funcionalidades, como de reestructurar y mantener el código limpio, mantenía ble, y entendible.

Éstas operaciones forman parte de un proceso más amplio llamado refacturación.

Lo importante en este caso es entender la utilidad de la refacturación y la necesidad de, cada poco tiempo, pararse por un momento y preguntarse si el código tiene una forma óptima, o podríamos reestructurarlo para hacerlo más fácil  de trabajar

En el día a día del desarrollo de programas informáticos, es muy común que, aunque se parta desde una planificación, finalmente se acaben implementando características sobre la marcha, en base a las necesidades que van surgiendo, y que desgraciadamente, muchas veces no pueden ser tenidas en cuenta en la planificación inicial.

esto provoca que, por muy ordenado y estructurado que pretendemos tener el código al principio de un proyecto, es totalmente común y normal que el código acabe ensuciándose, y que acabe adoptando una forma nada clara ni mantenimle.

El objetivo de la refacturación es detenerse cada poco tiempo y preguntarse de qué manera el código, manteniendo por supuesto su funcionalidad, podría ser más entendible para el ser humano, y estar estructurado de manera que, mantenerlo y ampliarlo, no resulte un esfuerzo titánico después de la realidad de cómo queda el código Al desarrollarlo poco a poco cada día.

Sin pretender entrar en esta publicación en demasiada profundidad con los principios y las técnicas de la refacturación, técnicamente, lo que hemos realizado en las 2 U anteriores, son dos técnicas bastante conocidas de esta filosofía de trabajo.

En primer lugar, la primera estrategia consiste en en capsular.

En cápsula amos porciones de códigos que tienen sed sentido como 1 U. Es decir, a lo largo del desarrollo de un programa, finalmente podemos ver fácilmente como hay porciones de código del programa que tienen sentido dentro de esa porción, y que podrían ser independientes del resto de la aplicación.

Por otra parte, como hemos comentado anteriormente, otra necesidad fundamental de crear funciones es cuando tenemos código que se repite.

Así que, el encapsulamiento de código en funciones, es una técnica de reorganización y reestructuración del código.

Antes de esta primera aplicación, generalmente, solemos tener un programa estructurado, es decir, un programa que puede perfectamente ocupar 500, 1000,2 1000 líneas de código, que va a lanzando instrucciones desde la primera hasta la última línea del programa. Fácil de entender, fácil de escribir, pero difícil de mantener, ya que cada vez que buscamos una porción del programa, tenemos que hacer Scroll a lo largo del código a través de miles y miles de líneas.

Al finalizar la refacturación que consiste en aislar segmentos en funciones, lo que acabamos teniendo es básicamente las mismas líneas de código, esos 500, 1000, o 2000 líneas de código, o quizás a veces mucho más, pero organizadas en burbujas, organizados en una serie de funciones, que anteceden a la función principal.

El código es más óptimo, pero la longitud del archivo no varía, así que acaba siendo aproximadamente igual de molesto tener que hacer Scroll a lo largo de miles de líneas cada vez que buscamos un segmento para modificar o cada vez que queremos implementar una nueva funcionalidad. Éste es verdaderamente uno de los problemas de la mantenía Billy dad de aplicaciones informáticas, que provoca que muchas veces tengamos que reescribir aplicaciones, simplemente porque nos cuesta menos Riesco reescribirlas, que mantenerlas, cuando el código se ha ensuciado demasiado. Evidentemente, lo que pretendemos es no tener que llegar a este.

es por esto que otra estrategia consiste en lo que hemos visto en la unidad anterior, básicamente extraer las funciones a archivos externos, incluirlas, en el caso del lenguaje que nos ocupa en esta publicación en las cabeceras.

Al hacer esto, el código podría pasar a tener aproximadamente esta forma:

tenemos un archivo principal que contiene la mínima expresión del código posible, y que, con suerte, puede verse todo en una sola pantalla, sin necesidad de hacer Scroll, o haciendo una cantidad mínima de Scroll a lo largo de las líneas.

Además, se visualiza la ejecución de las funciones, con lo cual, tenemos una idea muy aproximada mente de lo que hace el programa, aunque no necesariamente tenemos que estar viendo el código que contiene cada una de las funciones.

luego, por otra parte, si en un momento dado queremos profundizar en el código de alguna función concreta, simplemente tenemos que abrir la carpeta que contiene las funciones.

De un vistazo, podemos ver las funciones que contiene la carpeta, y si las hemos nombrado correctamente, podemos averiguar de un vistazo cuál es el archivo que tenemos que abrir para evitar.

cuando abrimos el archivo, estamos accediendo únicamente a la porción de código que nos interesa, y por tanto, estamos obviando todo ese código del resto de funciones que no nos interesa para implementar una nueva función concreta, o para retocar una parte de una función.

esta manera de trabajar, que solo nos ha exigido realizar dos operaciones de Rafa actualización, es totalmente conveniente, ya que nos permite aumentar enormemente nuestra productividad, trabajando más rápido, trabajando más cómodos, y en definitiva, permitiendo que, en un momento dado, el programa sea más fácil de extender, de hacer más grande, y de evolucionar

Publicado el 2 comentarios

¿Cual es el mejor lenguaje de programación para inteligencia artificial?

 

Frecuentemente recibo la pregunta acerca de cuál es el mejor lenguaje de programación para crear aplicaciones de inteligencia artificial. Otras veces, directamente la pregunta es si lenguajes como Python o bibliotecas como TensorFlow son los adecuados para crear este tipo de aplicaciones.

Así que el objetivo de este artículo es aclarar algunos conceptos para poder elegir un lenguaje de programación u otro para desarrollar aplicaciones que hagan uso de la IA.

¿Qué es la IA?

Este concepto no es fácil de explicar. La inteligencia artificial no es un conjunto de instrucciones, ni un nuevo tipo de datos. Consiste en una serie de metodologías en las cuales podemos dotar a nuestros desarrollos de comportamientos percibidos como inteligentes. En definitiva, son metodologías, y no instrucciones.

Es por esto que, a priori, cualquier lenguaje de programación es válido para realizar aplicaciones de inteligencia artificial.

¿Qué lenguajes de programación existen?

Haciendo referencia al listado TIOBE, que muestra los lenguajes de programación más utilizados en el mercado, el listado para enero de 2019 muestra los siguientes datos:

https://www.tiobe.com/tiobe-index/

Jan 2019

Jan 2018

Change

Programming Language

Ratings

Change

1

1

 

Java

16.904%

+2.69%

2

2

 

C

13.337%

+2.30%

3

4

 

Python

8.294%

+3.62%

4

3

 

C++

8.158%

+2.55%

5

7

 

Visual Basic .NET

6.459%

+3.20%

6

6

 

JavaScript

3.302%

-0.16%

7

5

 

C#

3.284%

-0.47%

8

9

 

PHP

2.680%

+0.15%

9

 

SQL

2.277%

+2.28%

10

16

 

Objective-C

1.781%

-0.08%

Cualquiera de los lenguajes de programación de esta lista podría ser perfectamente válido para desarrollar aplicaciones de IA, a excepción probablemente del lenguaje SQL, que está orientado a consultas en bases de datos, en lugar de a desarrollo de aplicaciones.

Poríamos clasificar estos lenguajes en tres grandes grupos:

-Lenguajes de bajo nivel, que son aquellos que tienen mejor rendimiento, pero en los que el programador debe tomar muchas decisiones, de forma que puede optimizar la ejecución del programa, pero la probabilidad de cometer fallos es mayor. Ejemplos de estos lenguajes son C, C++ y Objective-C

-Lenguajes de alto nivel, que son aquellos que ofrecen una serie de abstracciones, de forma que el propio compilador toma algunas decisiones, liberando al desarrollador de tomarlas. De esta forma, estos lenguajes suelen ser menos eficientes en la ejecución, ya que las decisiones que se toman automáticamente por el compilador no suelen ser tan inteligentes como las que toma un ser humano. Sin embargo, dado que el desarrollador tiene que tomar menos decisiones, las probabilidades de fallo son menores. Ejemplos de estos lenguajes son Python y Javascript

-Lenguajes de nivel intermedio: Encontramos dentro de este grupo aquellos lenguajes que buscan un balance óptimo entre rendimiento y dificultad. De esta forma, ponen muchas decisiones en manos del usuario programador, pero a la vez ofrecen una serie de facilidades y herramientas para prevenir y arreglar los errores de código. Un ejemplo de este tipo de lenguajes es Java.

Eligiendo el mejor lenguaje:

Antes de elegir un lenguaje u otro, teniendo en cuenta que todos los lenguajes de la lista son perfectamente válidos, deberemos establecer un criterio para la elección, y no todos tenemos por qué tener el mismo criterio.

Por ejemplo, un criterio podría ser el rendimiento. Es decir, que nuestras aplicaciones se ejecuten lo más rápido posible. Este criterio es importante, ya que muchas aplicaciones de inteligencia artificial deben funcionar y proporcionar resultados en un tiempo aceptable, ya que, en caso contrario, podría considerarse que nuestras aplicaciones son inteligentes, pero lentas (y por tanto podrían ser percibidas por los usuarios finales como aplicaciones “no tan inteligentes”, aunque la velocidad no tenga que ver directamente con la calidad de los resultados)

En este caso, podríamos elegir aquellos lenguajes de más bajo nivel, como C o C++

Evidentemente, en este caso, puesto que el propio aprendizaje y puesta en práctica de las metodologías de inteligencia artificial en un lenguaje concreto es complejo, tendríamos que tener un nivel de partida bastante fluido en estos lenguajes.

Otro criterio posible sería la facilidad de uso del lenguaje de programación. Esta es la opción que suele elegirse para formación relacionada con la inteligencia artificial. De esta forma, el alumno se preocupa únicamente por las complejidades derivadas de la implementación de la IA, y no de las complejidades propias del lenguaje de programación. Esta es la razón por la cual los lenguajes como Python son tan famosos en los cursos de formación relacionados con este ámbito, en contra de la creencia popular de que es debido a su potencia, es por su facilidad y su flexibilidad.

Un ejemplo más concreto del rendimiento entre los diferentes lenguajes de programación podemos encontrarlo en comparativas como la siguiente:

https://www.instagram.com/p/BQTe7NegeSq/

Esta es una de las comparativas que suelo realizar en todo tipo de formaciones relacionadas con la programación en múltiples lenguajes. El objetivo es proponer el mismo reto a resolver a diferentes lenguajes de programación, y observar los resultados.

En esta comparación podemos observar como, para un mismo cálculo, donde lenguajes de un nivel bajo tardan entre 24 y 25 segundos en completar su tarea, los lenguajes de alto nivel como Javascript tardan 38 segundos (aproximadamente un 52% más lentos), pero otros lenguajes como Python pueden llegar a tardar 157 segundos (es decir, un 650% más lentos que los lenguajes de bajo nivel). Por tanto, estos lenguajes no se eligen por su rendimiento sino por su facilidad de uso.

El lenguaje de programación R: Ventajas y desventajas

Existe una serie de lenguajes que suelen considerarse más aptos para el desarrollo de aplicaciones de inteligencia artificial. Uno de ellos es el lenguaje estadístico R.

La diferencia de este lenguaje con respecto a los genéricos es que incluye una serie de herramientas y librerías que facilitan tanto el cálculo como la presentación de resultados de análisis estadísticos (área que tiene una gran importancia en la inteligencia artificial).

Esto a la vez es bueno y a la vez no tanto. Desde un punto de vista del desarrollo, añade productividad permitiendo a los desarrolladores crear presentaciones de resultados de una forma muy sencilla.

Podemos encontrar dos grandes ejemplos de esto en la propia pagina de la Wikipedia:

https://es.wikipedia.org/wiki/R_(lenguaje_de_programaci%C3%B3n)

Repasando los dos ejemplos (tanto en su código fuente como en los resultados), veremos que la inclusión previa de las librerías correspondientes minimizan el código que tiene que desarrollar el ser humano, y automatizan al máximo la tarea de generación de gráficas.

Sin embargo, desde el punto de vista de la formación, realizar tantas abstracciones, en ocasiones puede no resultar tan conveniente, ya que si delegamos todos estos cálculos en el propio lenguaje de programación y sus librerías, no estaremos realmente aprendiendo a realizarlos, y si el día de mañana estamos obligados a cambiar a un lenguaje de programación más genérico, podremos darnos cuenta de la dependencia que habremos desarrollado con respecto al lenguaje de programación R

Aún así, por supuesto es recomendable que cualquier formación en inteligencia artificial contenga algún apartado que muestre a los alumnos el uso del lenguaje de programación R

Matlab y Octave:

En la lista TIOBE, el lenguaje que ocupa el puesto número 11 es Matlab, lo cual es igual de interesante como el lenguage R.

Matlab es un sistema algebráico presentado dentro de un entorno de desarrollo integrado, que desde hace muchos años facilita el desarrollo y la realización de múltiples tipos de cálculos a científicos que no tienen por qué tener conocimientos especialmente profundos de programación. De la misma forma que el lenguaje R provee una serie de facilidades y bibliotecas de presentación de resultados, MatLab realiza lo propio en un nivel todavía superior (el IDE consituye una forma muy asequible y agradable de aproximarse al desarrollo de proyectos que requieran cálculos)

En definitiva, tanto Matlab como software comercial, como Octave como alternativa de código abierto, son excelentes alternativas para personas que desean cumplir con el objetivo de acercarse al mundo de la inteligencia artificial, intentando facilitar o al menos abstraer las complejidades derivadas de los lenguajes de programación duros.

Diferentes niveles:

Dentro de las múltiples alternativas de las que disponemos como entornos de desarrollo para implementar proyectos de realidad virtual, dentro de que cualquier lenguaje de programación con unas mínimas capacidades es viable para implementar este tipo de proyectos, podríamos resumir:

Entornos como Matlab u Octave: Mayor facilidad y abstracción, eliminando o minimizando las dificultades de la programación. El propio entorno que nos facilita el trabajo es el que puede hacer que nuestras aplicaciones no sean posteriormente aplicables y portables en todas las plataformas. Aptos para desarrollar prototipos y en definitiva para que personas que no sean programadores puedan aproximarse a desarrollos de inteligencia artificial.

Lenguajes de programación específicos u optimizados, como R: Buena proporción entre esfuerzo y resultado, herramientas específicas para la tarea concreta. Sin embargo, son lenguajes tan específicos que luego no podemos usarlos para otros tipos de proyectos.

Lenguajes generalistas de programación de alto nivel: Buena proporción entre esfuerzo y resultado, y buen balance entre rendimiento, facilidad, y portabilidad del código en la implementación entre diferentes plataformas. Aptos para el aprendizaje y la implementación de aplicaciones reales de inteligencia artificial donde el rendimiento no sea un factor clave pero el éxito y la facilidad de la implementación si que lo sean.

Lenguajes generalistas de programación de bajo nivel: Alto rendimiento, exigen extensos conocimientos del propio lenguaje de programación ya que son propensos a cometer fallos humanos en la escritura del código. Aptos para la implementación final de aplicaciones en  las que el rendimiento sea un factor clave.

Un par de criterios más: facilidad de compilación y generalidad del lenguaje

Hay otra explicación por la cual los lenguajes de programación de alto nivel, como Python y Javascript, son ampliamente utilizados en formaciones relacionadas con inteligencia artificial, no es solo por su facilidad de uso sino también por la facilidad de puesta en marcha.

La puesta en marcha consiste en la serie de operaciones que deben realizarse para, desde cero, comenzar a desarrollar y ejecutar programas con un lenguaje de programación determinado.

En el caso de Python, todos los prerrequisitos pueden descargarse rápida y gratuitamente desde la página https://www.python.org/

Además, contiene instaladores para todo tipo de sistemas operativos y arquitecturas de hardware, lo que posibilita poder instalar y ejecutar programas en todo tipo de equipos informáticos, incluso en aquellos que están muy desactualizados.

El caso de Javascript es todavía más curioso, ya que cualquier navegador web de los que tenemos ya de por sí instalados en nuestro ordenador, llevan YA incorporados los intérpretes que permiten ejecutar programas realizados en este lenguaje de programación.

Únicamente en ese caso es necesario descargar algún editor de código para crear programas, como por ejemplo el archiconocido Notepad++:

https://notepad-plus-plus.org/download/v7.6.2.html

Conclusiones:

El desarrollo de aplicaciones de inteligencia artificial no se realiza de forma exclusiva con un lenguaje de programación u otro. Prácticamente cualquier lenguaje de programación es apto para realizar implementaciones de IA. Lo que si que es importante es conocer las ventajas y las desventajas de cada uno de los lenguajes, para escoger la mejor alternativa según el criterio o los criterios que se adapten a nuestras necesidades.

Quieres saber más?

Ya estamos inmersos de pleno en la era de la inteligencia artificial, que cambiará nuestras vidas y la forma en la que trabajamos. Pero, ¿estas preparad@ para estos cambios? El objetivo de este curso es proporcionarte las herramientas necesarias para que la inteligencia artificial sea una oportunidad y no una amenaza.

Con este curso, aprenderás las técnicas más punteras que empresas como Google, Facebook o Microsoft ya están utilizando para mejorar sus algoritmos. Cualquier dispositivo móvil, ya esté basado en Android o en iOS, ya está utilizando este tipo de tecnologías para mejorar tu experiencia de usuario. En breve, tus propios usuarios y tus clientes darán por hecho esta tecnología y esperarán que los servicios que tu les ofrezcas contengan inteligencia artificial. ¿Está preparada tu empresa para este reto?

Este curso se divide en tres módulos:

IA para todos – primer módulo del curso pensado para que todas las personas, aún sin conocimientos de programación, puedan entender y aprovechar las oportunidades que nos ofrece la inteligencia artificial


Programando aplicaciones de IA – segundo módulo del curso, en el cual ponemos en funcionamiento los conceptos principales del curso, permitiéndote desarrollar aplicaciones prácticas que usan inteligencia artificial


IA hasta el límite – Tercer módulo del curso en el que te mostramos cómo sacar el máximo partido a la inteligencia artificial desarrollando aplicaciones de visión artificial, procesamiento del lenguaje, y combinación con Big Data, entre otros


Publicado el Deja un comentario

Entrevista en Linkedin Learning

Entrevista realizada para Linkedin Learning y Pulse, por Alicia Ortega.

Puedes leer la entrevista original aqui:

https://es.linkedin.com/pulse/jos%C3%A9-vicente-carratal%C3%A1-3d-y-el-internet-de-las-cosas-ortega-herrero

 

El diseño 3D por ordenador está ya plenamente desarrollado y nos estamos adentrando en el mundo de la impresión 3D. ¿Cuál crees que será el siguiente paso?

Las técnicas de modelado 3D han llegado, aparentemente, a un punto de estabilidad. Es evidente que ya no vemos innovaciones tan grandes como las que vimos al final de la década de los 90 y al principio de la siguiente, donde no solo el modelado 3D llegó a su apogeo, sino que se democratizó en gran medida su uso, mediante el abaratamiento del precio por licencia, o la compatibilidad con sistemas informáticos domésticos, por ejemplo.

Analizando un poco los comienzos de la infografía y el CAD 3D, no podemos olvidar que las técnicas que usamos hoy en día no son más que simplificaciones de una realidad demasiado compleja como para ser simulada con la potencia computacional actual. Solo un cubo de 1 cm de lado se compone de tantos millones de átomos como para que sea ineficiente reproducirlo átomo a átomo en el interior de un ordenador. En lugar de eso, recurrimos a simplificaciones como, por ejemplo, los polígonos. Resolvemos el problema del cubo simplificándolo a 12 triángulos, y en base a esas simplificaciones hemos construido un conjunto de herramientas que nos permite construir cualquier cosa. Pero ,en mi opinión, no debemos perder nunca de vista el hecho de que son simplificaciones y, como tales, tienen limitaciones. ¿Cuál sería la alternativa? Por ejemplo, el modelado 3D en base a nubes de puntos lleva muchos años esperando su turno, aunque parece que no ha llegado todavía su momento, al menos no desde el punto de vista del uso generalizado.

En el caso de la impresión 3D, muchos de los procesos pasan por usar el formato STL, que esta compuesto por triángulos. Es decir, imprimimos objetos reales, digamos «basados en átomos», con archivos simplificados basados en polígonos. ¿Qué hacemos para solventar el problema? Aumentar los polígonos en número y disminuirlos en tamaño para que no se note la simplificación… pero sigue siendo una simplificación.

Así que quien me conoce sabe que adoro el modelado 3D basado en polígonos, pero en mi inconformista opinión, todavía está por desvelarse un paradigma de modelado 3D tal que nos permita reproducir informáticamente en 3D la realidad que nos rodea de una manera tal que nuestra potencia computacional pueda abordar la reproducción, y que las simplificaciones, en el caso de que las haya, no nos impongan tantas limitaciones como las técnicas actuales.

El siguiente paso, para mí, sin duda, es la realidad virtual y/o realidad aumentada. Un concepto que ha estado rondándonos desde hace 20 años, pero que nunca ha acabado de cuajar, y que ahora parece que está recibiendo el apoyo masivo de los grandes, como Microsoft, Google, Sony, o Facebook. Pero, una vez más, como desarrollador y formador de realidad virtual, puedo decir que los polígonos representan una barrera que nos aleja de esa inmersión completa. Por ejemplo, cuando percibimos un mundo sintético en 3D construido con polígonos a través de un medio 2D como es la pantalla de un ordenador, el modelado polígonal queda muy aparente, el resultado final es muy convincente. Sin embargo, cuando esa misma escena la ves a través de un dispositivo de realidad virtual, donde la sensación de inmersión es mucho más completa, la percepción de que los modelos están construidos en base a caras planas arruina bastante el efecto.

De todas formas, debo decir que estoy muy emocionado con las aplicaciones de la realidad virtual y aumentada, y con su combinación con el resto de tendencias tecnológicas actuales. Si bien a día de hoy las gafas de realidad virtual son dispositivos toscos y pesados, yo los considero como los móviles Motorola de los años 90: eran igualmente toscos, pero mira en lo que se han convertido los teléfonos móviles a día de hoy.

 

 

¿Qué tienes en cuenta a la hora de elegir un software de 3D u otro?

Donde hay un problema, debe haber al menos una solución. Cada software tiene unas ventajas y unas desventajas con respecto a los demás. Por tanto en mi opinión no se trata de elegir un software u otro, sino de conocer las ventajas y desventajas de cada uno de ellos.

Escucho lo que el cliente necesita, lo enfrento a las ventajas y desventajas de cada programa, y entonces elijo el más adecuado.

Entonces, un buen día, llega un cliente con un problema concreto que necesita resolver. Lo que suelo hacer es escuchar lo que el cliente necesita, enfrentar esas necesidades con las ventajas y desventajas de cada uno de los programas, y elegir aquel programa que, para ese cliente concreto, y ese proyecto concreto, solucione lo mejor posible sus necesidades.

Yo siempre digo que los programas son como herramientas dentro de una caja de herramientas. No puedes tener una caja de herramientas con solo un martillo. Si ocurre que tienes que clavar un clavo, bueno, en ese caso estarás de suerte. Pero si a continuación tienes que atornillar una estantería… probablemente el martillo no será tu mejor elección. De la misma manera que te interesa tener una caja de herramientas suficientemente nutrida, te interesa conocer cuantos más programas 3D mejor, para poder dar soluciones óptimas a diferentes tipos de proyectos.

 

¿Crees que los avances en modelado 3D y en animación van de la mano, o uno está adelantando al otro?

Es curioso, pero en infografía 3D, el modelado, la animación, la configuración de esqueletos, la iluminación, y otras tantas áreas, se han desarrollado a lo largo de los años juntas pero a la vez separadas. Paralelas, por supuesto, y tocándose en muchos puntos, porque finalmente llega un momento en el que el modelado ha de ser animado. Pero curiosamente el modelado y la animación son el resultado de una serie de técnicas que nada tienen que ver entre si.

Por ejemplo, la animación moderna 3D basada en claves está basada en los conceptos de animación de Disney de principios del siglo XX, en los que un animador principal creaba los fotogramas importantes, llamados primarios, y una serie de animadores secundarios creaban los fotogramas de relleno entre los fotogramas primarios. La animación con claves no es más que la versión digital de este método de animación clásico.

El modelado, por contrario, se ha construido en base a las simplificaciones poligonales que comentaba en la pregunta anterior.

En la vida real, esto no ocurre así. El cómo se mueve una persona depende de su morfología, de su anatomía. Los movimientos que puede hacer dependen de sus músculos, de sus huesos, y de otros elementos, pero en definitiva, la forma y el movimiento son parte de un todo.

Cabe decir que, a lo largo de los años, ha habido diferentes propuestas de sistemas de animación y modelado basados en las físicas de un personaje, que han intentado cubrir este vacío entre las dos técnicas y relacionarlas más entre sí, como ocurre en la vida real. Pero ninguna de ellas ha acabado dando más ventajas que la unión de estos sistemas simplificados e independientes.

En cuanto al ritmo de las innovaciones, igualmente ha discurrido paralelamente, ya que, como una técnica no tiene nada que ver con la otra, el ritmo de estos descubrimientos en una de las dos líneas no está relacionado ni limitado por la otra.

Por ejemplo, a finales de los 90, el modelado de superficies de subdivisión, implementado de diferentes maneras a lo largo de los diferentes programas, revolucionó el modelado de personajes 3D, haciendo que esta tarea fuera mucho más rápida y agradable de lo que era hasta el momento. La primera gran producción en usar esta técnica fue A Bug’s Life (“Bichos”, en España), en el año 1998.

Paralelamente, más o menos en la misma época, se empezó a popularizar el uso de la técnica de captura de movimiento, en lugar de la clásica animación por claves. Una de las primeras producciones cinematográficas en usar ampliamente esta técnica, fue Final Fantasy: The Spirits Within, en el año 1999. Esta producción ya usaba la técnica de captura de movimiento, que después se usó en “El Señor de los Anillos”, por ejemplo para animar a Gollum, pero a la vez se benefició del modelado de superficies de subdivisión, para modelar a los personajes 3D.

Estos son solo dos ejemplos, pero en definitiva, el concepto es que las producciones que vemos hoy en día en la pantalla son el resultado de la suma de miles de innovaciones hechas en los terrenos del modelado 3D, la animación, la iluminación, la creación de esqueletos virtuales, y otras tantas áreas. Así que al final las innovaciones corren de manera completamente paralela, pero acaban convergiendo en el producto final.

 

¿Piensas que el internet de las cosas puede consolidarse como industria de empleo, o que quedará más en ámbitos domésticos?

El término “internet de las cosas” es solo un concepto de paso hacia una realidad futura más compleja, pero en la que no me cabe ninguna duda que la interconectividad jugará un papel crucial. Imagínate, en 1996 yo tenía un ordenador de 66MHz con 16 megas de memoria. Hoy, 20 años después, todos llevamos en el bolsillo dispositivos móviles no sólo 100 veces más potentes, sino que, además, son táctiles y están permanentemente conectados a internet. Algo impensable para la mayoría en 1996. Ahora, analiza el pasado y el presente, e imagínate lo que tendremos en 20 años.

Los dispositivos son cada vez más pequeños, más potentes, y están más cercanos al ser humano.

Otro ejemplo: los ordenadores en los 70 ocupaban habitaciones enteras, en los 80 eran cajas encima de una mesa, en los 90 se popularizaron los portátiles, en los 2000 se extendió el uso de los teléfonos móviles, en el presente se empiezan a popularizar los relojes inteligentes, y las gafas de realidad virtual o aumentada para las masas están ya a la vuelta de la esquina. Si analizas esa tendencia, y la proyectas hacia el futuro, verás que los dispositivos son cada vez más pequeños, cada vez más potentes, y sobre todo, cada vez están más cercanos al ser humano, en el sentido de que los llevamos puestos encima, y quizás en un momento dado los llevaremos no solo encima, sino dentro de nosotros. Puede que si te hablo de dispositivos interconectados e implantados dentro del ser humano te suene a ciencia ficción, pero imagínate cómo percibiría una persona de 1996 el concepto actual de smartphone.

Y ni siquiera están todas las piezas todavía en el tablero. Por ejemplo, tenemos la inteligencia artificial, cuyo importante papel podemos empezar a intuir, pero todavía ni siquiera podemos cuantificar su influencia exacta en nuestro día a día en los próximos años.

Este es el futuro que yo creo que viene, un futuro en el que la interconectividad jugará un papel crucial en nuestras vidas y en nuestro día a día. Y por supuesto, en la medida de que esta interconectividad sea omnipresente, las demandas laborales irán acordes a esa nueva realidad. Es algo que ya pasa hoy en día, los trabajos relacionados con las nuevas tecnologías no tienen casi paro, mientras que la demanda de otros perfiles profesionales, incluso siendo cualificados, ha decaído. Por tanto, ¿habrá oportunidades de empleo? Por supuesto que sí. Pero yo creo que la pregunta interesante es: ¿estaremos preparados para cubrir esos empleos?

Estamos hablando de perfiles profesionales que ni siquiera existen hoy en día. Pasará algo parecido que ocurre con el perfil profesional “programador de aplicaciones Android”. Hace diez años ni siquiera existía ese concepto. ¿Cómo hemos aprendido los que finalizamos nuestros estudios de grado hace diez o quince años? Pues, evidentemente, aceptando que el aprendizaje no acaba con el título universitario. El aprendizaje continuo es algo que debe formar parte de tu vida diaria si quieres asegurar tu futuro laboral. No digo que tengas que dedicar 5 horas al día, de cada uno de tus días, a reciclarte. Pero lo que creo que está claro es que, con lo rápido que cambian los tiempos, no adoptar una postura de aprendizaje continuo no es una alternativa. Si esto es lo que ya ocurre a día de hoy, imagino que el futuro maximizará esta tendencia.

Por ejemplo, una persona de 20 años, una de 30 y una de 40, dentro de 20 años seguirán en el mercado laboral. Pero  en ese momento se demandarán perfiles laborales que todavía ni existen a día de hoy. En mi opinión, la única manera en la que un profesional puede estar preparado para este futuro es mantener una mentalidad abierta al cambio, y aceptar el aprendizaje y el reciclaje continuo como parte normal de tu vida profesional.

 

¿Qué aplicaciones crees que podrán incorporar los elementos como Arduino para hacernos la vida más sencilla?

Yo soy absolutamente fan de Arduino, casi un evangelista, diría yo.

Arduino ha abierto el campo del prototipado de sistemas electromecánicos a cualquier tipo de persona. Lo sacas de la caja, lo conectas al ordenador mediante USB, descargas el IDE (que, además de gratuito, contiene infinidad de ejemplos), y en cinco minutos estás haciendo proyectos. Y luego hay gran cantidad de componentes, de complementos que puedes conectar a tu placa, y que te permiten cosas increíblemente divertidas con poco tiempo, con poco esfuerzo, y con poco presupuesto. Arduino allana el camino para los creadores. Por ejemplo, un diseñador de producto, anteriormente limitado a los componentes físicos del producto, ahora puede también integrar la electromecánica, y programar fácilmente el comportamiento del sistema.

Un ejemplo que me encanta son los talleres de «robótica para niños» que cada vez proliferan más. Son talleres orientados para niños en los que muchas veces montan robots preconstruidos, pero demuestran que los kits de Arduino son tan fáciles, que hasta un niño los puede usar.

Por tanto, ¿qué aplicaciones espero de Arduino? Tengo muchas expectativas, no en la plataforma Arduino en sí misma, sino en las personas que lo usan para crear más y más cosas cada día.

Una expectativa que tengo a medio plazo, y pienso que soy realista en esto que voy a decir, es el advenimiento de la era de la robótica. Hasta hace poco el concepto «robot» era algo casi exclusivo de la ciencia ficcion. Pero, por ejemplo, casi sin darnos cuenta, ya tenemos robots limpiando nuestras casas.

¿Qué nos depara el futuro? Si juntamos el hardware capaz de realizar la tarea, con precios asequibles, con personas formadas y capaces (quiero creer que, por ejemplo, los talleres de «robótica para niños» pavimentan en cierta manera el camino, en este sentido), veremos que tenemos todos los ingredientes para una revolución tecnológica.

En mi opinión, Arduino es una pieza más de esa revolución. La generalización del uso de internet por el ciudadano medio, es una revolución comparable a otras revoluciones anteriores, como la industrial. Personas interconectadas entre sí, comunicadas, intercambiando información. Si al uso de internet como medio de comunicación lesumamos la facilidad actual para aprender a programar, el abaratamiento de técnicas de fabricación o prototipado como la impresión 3D, y la aparición de entornos como Arduino… en mi opinión se están juntando los ingredientes para una ola perfecta de creatividad. Lo puedes ver ahora mismo, abres YouTube, buscas «Arduino», y puedes ver cada día a más gente que, desde cualquier parte del planeta, y con recursos mínimos, construyen y convierten en realidad sus proyectos y sus ideas. Eso, para mí, es lo mejor de todo esto: ahora cualquier persona con interés suficiente, cualquier estudiante, puede tener encima de su escritorio las piezas necesarias para crear y desarrollar esa innovación que mejore nuestras vidas.

Publicado el Deja un comentario

Curso de Programación en C

C es uno de los lenguajes de programación más importantes en el sentido de que una gran cantidad de otros lenguajes derivan de este. Conocer C es imprescindible para crear aplicaciones de alto rendimiento.

En estas navidades vamos a impartir un curso de programación de aplicaciones empresariales en C. Este es uno de los lenguajes más sencillos de aprender, lo cual te habilita a desarrollar aplicaciones informáticas potentes de una forma fácil y sencilla.

En este curso, que realizaremos a través de streaming, en directo, aprenderemos tanto los fundamentos de programación en C, mostrándote cómo crear tus propias aplicaciones informáticas.

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos sean capaces de programar aplicaciones informáticas completas

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Las 5 V del Big Data

Una de las claves para entender cual es la definición del Big Data, qué es y para qué sirve, pasa por entender las 5V. La aplicación del Big Data es prácticamente infinita en un mundo como el de hoy, en el que las organizaciones acumulan enormes cantidades de información. Tendencias tales como el Internet De Las Cosas, la aplicación del Big Data al sector inmobiliario, o incluso al terreno del futbol, nos permiten ver que, dentro de poco, este tipo de ténicas serán ubicuas en prácticamente cualquier terreno.

Cuando empezamos un proyecto de Big Data, no hay, al menos todavía, un manual que seguir, unos pasos que dar, en el sentido de que cada proyecto tiene unas necesidades particulares, y requiere soluciones personalizadas. Sin embargo, esto mismo suele marear a aquellas personas, técnicos o empresas, que quieren aproximarse a este mundo del tratamiento de la información, al menos, entendiendo las bases de su funcionamiento – y un «depende» no suele ser de mucha ayuda en estas ocasiones.

Es por esto que creamos estructuras para que aquellas personas que se inician en esta disciplina, desde cualquier perspectiva, tengan un punto de apoyo y una referencia para entender cómo abordar un proyecto de Big Data – y luego, más adelante, descubrirán que estas estructuras se quedan pequeñas para abordar la enorme complejidad que puede llegar a tener un proyecto de este tipo.

Es por esto que dicha complejidad suele resumirse en tres pasos:

  • Unificar todos los orígenes de datos en un solo formato tratable (limpiando, homogeneizando la información, llenando los huecos faltantes, etc)
  • Realizar operaciones de tratamiento de los datos, apoyándose, cuando es necesario, con técnicas de inteligencia artificial
  • Presentar los resultados de una forma gráfica, mediante informes, analíticas, o de cualquier otra forma

De la misma forma, para empezar a entender en qué casos es necesario comenzar un proyecto de Big Data, y cómo tratar los datos involucrados en el proceso, solemos hablar de 5 V’s, que es otra herramienta, otra estructura, para entender, de forma mucho más fácil, las necesidades de este tipo de proyectos.

Realmente, a un nivel avanzado, hay muchas más que estas 5 V que se suelen utilizar, pero trabajamos con estas cinco primeras como un modo de simplificar y hacer comprensible para el público general, las complejidades de este tipo de proyectos.

VOLUMEN

El principal problema en un proyecto de BIG data es precisamente eso, la gran cantidad de datos que existen en el conjunto inicial con el que se quiere trabajar. Tal volumen puede hacer que ese conjunto no sea tratable por medios tradicionales de forma eficiente, excediendo a las capacidades humanas y técnicas que un equipo puede llegar a tener.

VELOCIDAD

La velocidad es otro de los parámetros importantes para decidir cómo procesar los datos involucrados en un proyecto. Hay varias formas de entender cómo la velocidad afecta en este caso.

Puede entenderse como la velocidad a la que nuevos datos van entrando al sistema, o puede entenderse como la velocidad con la que el sistema debe ser capaz de llegar a conclusiones de valor.

VARIEDAD

La variedad es el primer gran problema al que se enfrenta cualquier proyecto de Big Data. En un proyecto podemos contar con datos como bases de datos, archivos de excel, archivos PDF, correos electrónicos, e incluso documentos en papel que deben ser escaneados y procesados (mediante técnicas de reconocimiento de caracteres)

La variedad suele ser el primer problema con el que hay que enfrentarse, habrá que realizar un proceso mediante el cual deberemos homogeneizar la información a un formato o a un conjunto de formatos a través de los cuales podamos comparar y cruzar la información.

VERACIDAD

En una gran cantidad de ocasiones, el conjunto de datos con el que trabajos es incompleto, no uniforme, o contiene datos que son incorrectos, o falsos. Asegurar que los datos sean veraces en múltiples sentidos es imprescindible para que los resultados obtenidos sean fiables.

VALOR

No todos los datos tienen el mismo valor. En ocasiones, parte de los datos que componen un conjunto pueden ralentizar el sistema, y no aportan valor a la solución que se quiere encontrar. Es por esto que no cualquier dato vale, y en muchas ocasiones tendremos que realizar un filtrado previo.

Analizando todas estas variables es como puedes saber no solo si tu organización necesita realizar un proyecto de big data, sino también en qué situación te encuentras, y cuáles pueden ser tus primeros pasos en el momento de realizar una primera aproximación al proceso de ordenar la información, procesarla, y obtener conclusiones de valor a partir de ella.

Publicado el Deja un comentario

Curso en desarrollo de aplicaciones con C++

Este verano vamos a impartir un curso en directo de aplicaciones informáticas con C++

C++ es uno de los lenguajes más comunes para desarrollar aplicaciones informáticas. Si quieres orientar tu carrera profesional en el desarrollo de aplicaciones informáticas, C++ es uno de los principales lenguajes que debes aprender.

En este curso, que realizaremos a través de streaming, en directo, aprenderemos a crear aplicaciones desarrolladas en Java completas de una forma concreta y directa, con el mínimo de teoría posible, y el máximo de práctica.

Los bloques principales del curso son:

  • Entorno de desarrollo
  • Sintaxis
  • Estructuras de datos
  • Estructuras de control
  • Programación con funciones
  • Programación orientada a objetos
  • Uso de librerías predeterminadas y externas
  • Lectura y escritura de archivos
  • Conexión con bases de datos
  • Interfaces gráficas de usuario
  • Ejercicio final de curso

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos aprendan todas las claves para crear sus propias aplicaciones desarrolladas con C++, y que puedan incorporarse al mercado laboral con garantías.

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso en desarrollo de aplicaciones con Java

Este principio de otoño vamos a impartir un curso en directo de aplicaciones informáticas con Java

Java es uno de los lenguajes más comunes para desarrollar aplicaciones informáticas. Si quieres orientar tu carrera profesional en el desarrollo de aplicaciones informáticas, Java es uno de los principales lenguajes que debes aprender.

En este curso, que realizaremos a través de streaming, en directo, aprenderemos a crear aplicaciones desarrolladas en Java completas de una forma concreta y directa, con el mínimo de teoría posible, y el máximo de práctica.

Los bloques principales del curso son:

  • Entorno de desarrollo
  • Sintaxis
  • Estructuras de datos
  • Estructuras de control
  • Programación con funciones
  • Programación orientada a objetos
  • Uso de librerías predeterminadas y externas
  • Lectura y escritura de archivos
  • Conexión con bases de datos
  • Interfaces gráficas de usuario
  • Ejercicio final de curso

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos aprendan todas las claves para crear sus propias aplicaciones desarrolladas con Java, y que puedan incorporarse al mercado laboral con garantías.

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso en desarrollo de aplicaciones web

En este próximo mes de septiembre vamos a impartir un curso de desarrollo de aplicaciones web.

La gran mayoría de servicios digitales que consumimos actualmente, son realmente servicios web, sitios web 2.0 complejos que, de forma dinámica, nos proporcionan múltiples tipos de funcionalidades. Actualmente el mercado laboral busca intensamente profesionales que sepan crear este tipo de aplicaciones

En este curso, que realizaremos a través de streaming, en directo, aprenderemos a crear aplicaciones web 2.0 completas de una forma concreta y directa, con el mínimo de teoría posible, y el máximo de práctica.

Los bloques principales del curso son:

  • Creación de webs en el lado del cliente con HTML5
  • Estilizado de sitios web con CSS3
  • Creación de interactividad en el lado del cliente con Javascript
  • Optimización de la productuvidad con jQuery
  • Programación en el lado del servidor con PHP
  • Bases de datos con MySQL

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos aprendan todas las claves para crear sus propias aplicaciones web, y que puedan incorporarse al mercado laboral con garantías.

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso de Marketing Digital

En este próximo mes de Julio vamos a impartir un curso de marketing digital.

El marketing digital es la clave para vender más, y sobre todo para vender mejor, aprovechando todas las claves que las nuevas tecnologías ponen a nuestra disposición.

En este curso, que realizaremos a través de streaming, en directo, aprenderemos los pilares principales de cualquier campaña de marketing, de una forma concreta y directa, con el mínimo de teoría posible, y el máximo de práctica.

Los bloques principales del curso son:

-Redes sociales
-Posicionamiento
-Creación de anuncios
-Creación web
-Analítica
-Landing pages
-Videomarketing
-Tiendas online

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos aprendan todas las claves para crear sus propias campañas de marketing digital y empezar a vender sus productos y servicios de forma efectiva.

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso de modelado y render arquitectura/ingeniería/interiorismo

En este próximo mes de Julio vamos a impartir un curso de modelado y render para aquitectura, proyectos de ingeniería, e interiorismo, con Blender 2.8 y el motor de render avanzado Cycles.

¿Por qué usar Blender como herramienta para presentar tus proyectos?

  • Blender es gratuito
  • Es completamente estable
  • Es multiplataforma (está para Windows/MacOS/Linux)
  • Acepta todos los formatos principales de importación/exportación

En este curso, que realizaremos a través de streaming, en directo, aprenderemos todo lo necesario para crear geometría inorgánica en Blender, y para realizar representaciones fotorrealistas.

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos acaben la formación sabiendo realizar imágenes y animaciones con calidad fotorrealista

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso de WordPress

En este próximo mes de Julio vamos a impartir un curso de creación de sitios web con WordPress.

WordPress es la herramienta de creación de sitios web más utilizada en el mundo. Permite crear un sitio web sin necesidad de conocimientos de programación. En este curso, mostraremos a los alumnos no sólo como crear un sitio web, sino también a añadirle una tienda online y un blog, para crear la versión digital de un negocio, de forma rápida, fácil u sencilla.

En este curso, que realizaremos a través de streaming, en directo, aprenderemos tanto los fundamentos de instalación de WordPress, la instalación de una tienda online, la creación de un blog, y muchas otras cosas.

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos acaben la formación con su propia tienda online en funcionamiento.

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso de bases de datos con MySQL

En este próximo mes de Julio vamos a impartir un curso gestión de bases de datos con MySQL

MySQL es una de las bases de datos más conocidas, que nos permite crear estructuras de almacenaje de información tanto para nuestras aplicaciones, como para nuestros sitios web

En este curso, que realizaremos a través de streaming, en directo, aprenderemos tanto los fundamentos de instalación de servidores en linux, como sus operaciones de mantenimiento

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos sean capaces de gestionar eficientemente cualquier tipo de base de datos basada en SQL

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Programando en C: Punteros

Capítulo 18: Punteros en C

Los punteros constituyen una de las herramientas diferenciales del lenguaje de programación C con respecto a otros lenguajes considerados de más alto nivel, desde el punto de vista de la cercanía al lenguaje del ser humano o de la máquina

 dado que el lenguaje de programación C Tiene una consideración, con respecto a esos otros lenguajes, de estar relativamente cerca del lenguaje de la máquina, lógicamente tiene la capacidad de trabajar con punteros o apuntadores, que no es más que la capacidad de poder referirse directamente a un registro en memoria ocupado por una variable, en lugar de llamar directamente a esa variable o a ese referencia 

Obtener la referencia de la posicion en memoria de una variable

En este ejemplo, empezamos declarando una variable de tipo entero a la cual asignamos un valor concreto, que para este ejemplo es el número 5

 a continuación, tal y como hemos hecho otras tantas veces, simplemente devolvemos el valor de esa variable por pantalla, haciendo referencia al propio nombre de la variable directamente en una instrucción de impresión

 la novedad, en este ejercicio, es que, a continuación, devolvemos no ya el valor de la variable, que para esta aplicación no nos interesa tanto, sino la celda de memoria que ocupa en su asignación. es decir, la dirección de la memoria a la que le ha tocado almacenar el valor de esa variable

 dentro de una misma ejecución de un programa, el valor de la posición en la memoria será siempre el mismo.

 sin embargo, si cerramos y abrimos el programa de nuevo, podremos comprobar como naturalmente la posición de la memoria de la variable habrá cambiado, ya que cada vez que se ejecuta el programa, el sistema lo considera como un programa completamente nuevo, y no tiene porqué mantener las posiciones de la memoria con respecto a la ejecución anterior

 además, podremos comprobar fácilmente como la nomenclatura de las direcciones de la memoria podrá variar grandemente de un sistema a otro 

main.c
#include <stdio.h>
int main() {    int numero = 5;    printf(«El numero es: %d \n»,numero);    printf(«La celda de memoria del numero es: %p \n»,&numero);    }

Creación de un puntero

A continuación, una vez que ha quedado claro el concepto anterior, en cuanto a que podemos usar el símbolo ampersand para saber la dirección en memoria de una variable concreta, vamos a declarar un puntero o apuntador

 cómo podemos imaginarnos, el siguiente código es una evolución del código anterior, donde hemos declarado un nuevo puntero, que además, por claridad, recibe exactamente ese mismo nombre. 

Cuando creamos un puntero, habremos observado que la forma de la declaración es exactamente igual que la forma en la que hemos declarado cualquier tipo anterior de variable, pero introducimos un asterisco justo antes del nombre de la variable. esto indica que esa variable no es una variable real, sino que va a apuntar a la dirección de memoria de otra variable

 además, también es importante indicar que el tipo de dato del puntero deberá ser el mismo tipo que el dato al que apunta

 por último, dentro de este ejemplo, vamos a extraer un par de datos del puntero, para saber cómo debemos trabajar y como debemos invocarlos.

 si llamamos al propio puntero, es decir, lo llevamos como si estuviéramos llamando a la propia variable, no tendremos el valor, sino que obtendremos la dirección en la memoria, porque precisamente eso es lo que hace un puntero, básicamente apuntar a la dirección de memoria de otra variable algo así como un acceso directo

 sin embargo, si invocamos al puntero pero lo llamamos con el asterisco antes del nombre de la variable, ahí es cuando estamos llamando al valor de la variable, o lo que es lo mismo, al valor de la variable a la que apunta el puntero 

main.c
#include <stdio.h>
int main() {    int numero = 5;    printf(«El numero es: %d \n»,numero);    printf(«La celda de memoria del numero es: %p \n»,&numero);        int *puntero; // Declaro un puntero    puntero = &numero; // El puntero apunta a la direccion de la memoria de la variable        printf(«El puntero esta en la posicion: %p \n»,puntero);    printf(«El puntero tiene el valor: %i \n»,*puntero);    }

Referencia cambiante al puntero

Todo esto que hemos visto hasta ahora básicamente refuerza el mensaje de que un puntero no es en si una variable, sino que es un acceso directo a la posición es memoria de otra variable existente

 para demostrar la veracidad de esta afirmación, esta extensión del ejercicio, aparentemente trivial, nos demuestra hasta qué punto el puntero va a depender siempre del valor original de la variable referenciada

 de esta forma, en primer lugar, trabajamos con el código con el que hemos estado operando hasta el momento en esta unidad didáctica, pero, como novedad, a continuación, una vez que hemos obtenido el valor del puntero, realizamos un cambio sobre el valor de la variable

 sí la variable fuera una entidad, y el puntero fuera otra entidad, cambiaría el valor de la variable, pero no el valor del puntero

 sin embargo, en el ejemplo a continuación podemos comprobar que, cambiando el valor de la variable, no solo cambia el valor de la variable, sino que también cambia el valor devuelto por el puntero, ya que, una vez más, el puntero finalmente no tiene entidad por si mismo sino que apunta al valor de la variable inicial 

main.c
#include <stdio.h>
int main() {    int numero = 5;    printf(«El numero es: %d \n»,numero);    printf(«La celda de memoria del numero es: %p \n»,&numero);        int *puntero; // Declaro un puntero    puntero = &numero; // El puntero apunta a la direccion de la memoria de la variable        printf(«El puntero esta en la posicion: %p \n»,puntero);    printf(«El puntero tiene el valor: %i \n»,*puntero);        numero = 16;    printf(«El numero es: %d \n»,numero);    printf(«El puntero tiene el valor: %i \n»,*puntero);}

Publicado el Deja un comentario

Curso de servidores con Linux

En este próximo mes de Septiembre vamos a impartir un curso instalación y mantenimiento de servidores con Linux. En este curso aprenderemos todo lo necesario para que puedas instalar tus propios servidores dedicados, y configurarlos adecuadamente

Linux es un sistema operativo que predomina en el sector de los servidores, no solo por su licencia gratuita, sino por ser un sistema abierto y totalmente estable, además de gozar de una gran cantidad de soporte por parte de la comunidad.

En este curso, que realizaremos a través de streaming, en directo, aprenderemos tanto los fundamentos de instalación de servidores en linux, como sus operaciones de mantenimiento

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos sean capaces de montar sus propios servidores, e instalar sobre ellos los servicios que sean necesarios para su correcto funcionamiento, así como las operaciones de seguridad necesarias.

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso de Scratch

En este próximo mes de Julio vamos a impartir un curso de Scratch. Este es uno de los lenguajes más sencillos de aprender, lo cual te habilita a desarrollar aplicaciones informáticas potentes de una forma fácil y sencilla.

Scratch es un lenguaje visual de programación mediante nodos. De esta forma, cualquier persona interesada en aprender y enseñar a programar, puede hacerlo de la forma más sencilla posible

En este curso, que realizaremos a través de streaming, en directo, aprenderemos tanto los fundamentos de programación en Scratch, mostrándote cómo crear tus propias aplicaciones informáticas.

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos aprendan a desarrollar aplicaciones completas mediante el lenguaje visual de programación Scratch

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso de jQuery

En este próximo mes de Julio vamos a impartir un curso de jQuery. Este framework te permite crear aplicaciones de una forma tremendamente sencilla, evitando la parte más compleja de la programación en Javascript, y acelerando y facilitando los procesos mediante los cuales puedes crear tus propias aplicaciones web

En este curso, que realizaremos a través de streaming, en directo, aprenderemos las funciones principales de la librería jQuery, así como la construcción de completos programas con esta librería.

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo del curso es que los alumnos aprendan a desarrollar completas aplicaciones en la web, del lado del cliente, usando jQuery

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso de Inteligencia artificial y visión 3D

En este próximo mes de Julio vamos a impartir un curso de inteligencia artificial aplicada a la visión 3D. La visión tridimensional es uno de los campos más apasionantes de la informática a día de hoy, y su combinación con técnicas de inteligencia artificial hacen que este ambito de conocimiento sea fuente de contínuos nuevos descrubrimientos

Las aplicaciones que vamos a desarrollar en este curso son completamente multiplataforma, lo que quiere decir que las podrás ejecutar en practicamente cualquier lenguaje de programación y en cualquier plataforma informática

En este curso, que realizaremos a través de streaming, en directo, aprenderemos como programar paso a paso aplicaciones de visión artificial usando patrones de inteligencia artificial.

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos sean capaces de programar aplicaciones informáticas completas

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso de HTML5 Canvas

En este próximo mes de Julio vamos a impartir un curso de html5 canvas. Este entorno de trabajo te permite constuir tus propias aplicaciones visuales cuando necesitas que tus programas realicen algun tipo de dibujo 2D o 3D.

Hay ocasiones en las que necesitamos que nuestras aplicaciones puedan generar algun tipo de contenido gráfico de forma completamente personalizada: gráficas, configuradores visuales, juegos en movimiento, etc. Canvas es precisamente la solución a estos casos, te permite crear soluciones visuales estáticas y en movimiento, pudiendo personalizar al máximo el contenido de estas presentaciones.

En este curso, que realizaremos a través de streaming, en directo, aprenderemos tanto los fundamentos de programación en canvas, mostrándote cómo crear tus propias aplicaciones informáticas.

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos sean capaces de programar aplicaciones informáticas completas

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso de Google Drive

En este próximo mes de Julio vamos a impartir un curso de Google Drive. Esta suite de herramientas de Google te permite no solo almacenar tus documentos, sino editarlos y compartirlos directamente en la nube.

Google Drive es una suite que incorpora una gran cantidad de herramientas: crear documentos, hojas de calculo, presentaciones, y mucho más. Estos documentos pueden ser editados en cualquier momento, en cualquier lugar, por equipos cuya unica herramienta necesaria es un navegador web. En este curso mostraremos cómo puedes almacenar y gestionar de una forma terriblemente sencilla tus documentos en la nube de Google Drive

En este curso, que realizaremos a través de streaming, en directo, aprenderemos tanto los fundamentos de programación en Python, mostrándote cómo crear tus propias aplicaciones informáticas.

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos sean capaces de gestionar sus documentos en la nube usando Google Drive

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso de Programación en C

C es uno de los lenguajes de programación más importantes en el sentido de que una gran cantidad de otros lenguajes derivan de este. Conocer C es imprescindible para crear aplicaciones de alto rendimiento.

En este próximo mes de Septiembre vamos a impartir un curso de programación de aplicaciones empresariales en C. Este es uno de los lenguajes más sencillos de aprender, lo cual te habilita a desarrollar aplicaciones informáticas potentes de una forma fácil y sencilla.

En este curso, que realizaremos a través de streaming, en directo, aprenderemos tanto los fundamentos de programación en C, mostrándote cómo crear tus propias aplicaciones informáticas.

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos sean capaces de programar aplicaciones informáticas completas

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Programando en C: Persistencia en bases de datos

Las bases de datos son contenedores de información más avanzados que un simple archivo de texto.

Nos permiten disfrutar de ventajas con respecto a los archivos de texto, tales como por ejemplo un mayor nivel de seguridad en el acceso a la información, o permitir el acceso concurrente de múltiples personas a una misma base de datos, algo que evidentemente no ocurre con los archivos de texto plano.

Las bases de datos, por tanto, finalmente, no son de uso típico en el ámbito doméstico y personal, sino que son más características de aplicaciones empresariales, donde, como he comentado anteriormente, la seguridad y la concurrencia, así como otros factores tales como por ejemplo el rendimiento, son claves.

El soporte nativo para el acceso a bases de datos, no ya en el núcleo, sino en las librerías de base, difiere bastante según los lenguajes de programación.

Hay lenguajes, como por ejemplo pedir HP, donde Las librerías asociadas al núcleo incluyen la capacidad de conectarse a bases de datos concretas, en el caso de ese lenguaje de programación, a ese culete y MySQL, aunque por supuesto, mediante el uso de librerías externas, podemos conectarnos a otras bases de datos.

hay otros lenguajes, como por ejemplo fue, que no incluyen soporte para conexión a bases de datos, ni en el núcleo ni en las librerías por defecto, pero por supuesto, siempre vamos a tener esa opción de descargar librerías para poder realizar esta conexión.

El estándar sql 

Existen multitud de bases de datos actualmente utilizadas en el mundo, pero sin embargo, hay una familia de bases de datos cuyo uso está bastante generalizado, que se basan en el lenguaje sql.

 este lenguaje, muy fácil de aprender ya que se asemeja en gran medida al inglés nos permite establecer una forma muy sencilla de realizar las operaciones básicas y comunes de acceso a base de datos que cualquier aplicación de tipo empresarial puede necesitar.

 además, otra ventaja de este estándar, es que aprendiendo el lenguaje base, tenemos multitud de bases de datos a nuestra disposición, únicamente teniendo en cuenta que cada una de estas bases de datos introducir una serie de modificaciones mínimas con respecto al estándar original

 en esta publicación vamos a usar un motor de bases de datos llamado sq lite, que por supuesto respeta de una forma bastante aproximada el estándar SQL original y por otra parte es muy fácil de implementar

 hay que tener en cuenta que esta publicación no está especializada en la conexión ni el manejo de bases de datos, temática que daría perfectamente por sí misma suficiente como para Publicación individual

 el objetivo, por contra, 

Operaciones básicas

Las operaciones básicas en el estándar SQL son realmente, las mismas que necesita cualquier aplicación de tipo empresarial para poder funcionar correctamente

 son fundamentalmente 4, listar, insertar, eliminar, y actualizar

 listar hace referencia a obtener un listado de los registros existentes en la base de datos. adicionalmente se pueden incluir filtros para personalizar el listado con respecto a nuestros intereses y

 insertar hace referencia a crear un nuevo registro en la base de datos, usualmente a continuación de los registros previamente existentes

 eliminar hace referencia a suprimir un registro previamente existente en la base de datos. esta operación debe realizarse con mucha cautela, indicando el filtro que corresponde al registro concreto que queremos eliminar punto de no indicar este filtro, el programa entiende que queremos borrar la tabla entera de la base de datos, lo cual, como podremos imaginar, suele tener resultados catastróficos. como anotación, decir que  probablemente todos los que nos dedicamos a tratar bases de datos en algún momento de nuestra vida hemos cometido este tipo de error catastrofico

 actualizar hace referencia a cambiar los datos existentes en un registro previo, sin necesidad de borrar el registro en sí mismo, ni insertar un registro nuevo

 adicionalmente a este listado de operaciones, se suele considerar que hay una quinta operación esencial consistente en Buscar

 la operación de buscar realmente es una operación del Estado con un filtro personalizable. en definitiva, obtenemos un listado filtrando mediante un parámetro personalizado 

El motor sql

Todas estas operaciones, que conforman el núcleo de cualquier motor de base de datos, si nos fijamos, ya las hemos implementado anteriormente en esta publicación en el primer ejercicio del curso

 así pues, que es lo que puede aportarnos el motor sql, ya que técnicamente ya sabemos realizar las operaciones que se han indicado como operaciones imprescindibles

 anteriormente nosotros hemos implementado todas estas operaciones de forma completamente manual. el estándar SQL nos ofrece una interfaz simplificada para poder realizar peticiones a nuestra base de datos.

 por poner un ejemplo, cuando anteriormente insertamos un registro, tuvimos que calcular manualmente el índice del último elemento insertado, y sumarle un valor. o, por poner otro ejemplo, cuando realizamos una eliminación, tuvimos que realizar un recalculo y reasignacion de los índices devueltos

 en definitiva, no hay ningún problema por programar un programa que trabaje todas estas operaciones de forma completamente manual, y hasta cierto punto de vista, es incluso didáctico que alguna vez en nuestra vida realicemos estas operaciones de forma manual para entender hasta cierto punto que es lo que está ocurriendo entre bambalinas en una aplicación de tipo SQL

 sin embargo, el estándar sql, o lo que es lo mismo, a traer el acceso a los datos y dejarlo en manos de un motor, como desarrolladores, nos ofrece ventajas sobre todo en cuanto a la productividad

 nosotros indicamos únicamente la operación que queremos realizar sobre la base de datos, y el motor se encarga de gestionar todo lo que está ocurriendo por bajo del programa Punto como podremos comprobar a continuación, este tipo de metodología es especialmente útil cuando queremos realizar peticiones con filtrados complejos a la base de datos. para nosotros, realizar una petición en lenguaje SQL es prácticamente como hablar en inglés, pero como podremos comprobar en los siguientes ejemplos, el programa abstrae toda esa complejidad y nos ofrece una interfaz muy sencilla de utilizar. además, usar el estándar sql, y crear una conexión a una base de datos utilizando un motor como intermediario, tiene muchas otras ventajas que ahora mismo, probablemente, todavía ni siquiera podemos intuir

 si por ejemplo suponemos el caso anterior, es decir, el ejercicio práctico de la agenda que hemos desarrollado hasta este momento, y repasamos su funcionamiento, teníamos que, al principio de la ejecución del programa, podíamos cargar todos los datos existentes en el archivo de texto dentro del programa, y realizar modificaciones.

 al final del proceso de realizar modificaciones, podíamos devolver los datos a la propia base de datos.

 ahora imaginemos que hubieran dos personas intentando utilizar la aplicación e intentando A la base de datos de manera simultánea punto si una persona carga la información de la base de datos dentro del programa, y realiza modificaciones, esas modificaciones no se aplican en la base de datos hasta que la persona no utiliza la opción de escritura que hemos cubierto anteriormente

Eso quiere decir que, sí, en el transcurso del trabajo en la aplicación por parte de la primera persona, la segunda persona carga los datos existentes desde la base de datos en formato texto, lo que estará cargando es un conjunto de datos que no estarán en el último estado modificado por parte del usuario número 1 

Me hace falta decir que todo aquel trabajo que desarrolle el usuario dos, potencialmente podría ser inservible, ya que has descargado o estados de los datos que no tiene nada que ver con el último estado que está modificando el usuario uno

En definitiva, la idea es que los motores de tipo SQL, entre otras muchas cosas, gestionar la concurrencia, o lo que es lo mismo, el acceso por parte de múltiples usuarios de la base de datos, Y que aún así se mantenga cierta integridad en los datos manejados

Descargando la librería

Al contrario que el resto de librerías con las que hemos trabajado hasta el momento, la librería para manejar la pases de datos en formato ese culete no está incluida dentro de la distribución estándar del lenguaje F.

Es por esto que, lo primero que tenemos que hacer, es descargar la librería, y añadirla a nuestro proyecto, para que nuestro código pueda utilizar las funciones específicas para conectarnos a una base de datos de este tipo, y poder empezar a realizar peticiones

Podemos descargar los archivos fuente necesarios desde la siguiente dirección:

Una vez que los hayamos descargado, únicamente tendremos que copiarlos en la misma carpeta donde está nuestro código, y a continuación, llamar al archivo de cabecera, usando la siguiente instrucción:

Ejemplo de uso

A continuación se introduce un ejemplo de cómo usar una conexión a una base de datos en formato ese culete.

En el ejemplo que se presenta a continuación, se ha intentado simplificar al máximo la conexión con la base de datos. Además, como podemos observar, durante la ejecución del programa, automáticamente el motor se encarga de gestionar la creación de la propia base de datos, en el caso de que no exista en el momento de ejecutar el código.

Las bases de datos en formato ese culito y, finalmente, son archivos que existen dentro del directorio de archivos y carpetas con el que trabajamos habitualmente.

Usualmente tienen dos tipos de extensión, la extensión. Debe, y la extensión. Y se culito tres. Para este ejemplo, estamos utilizando la extensión. Debe

No debemos intentar abrir un archivo de base de datos directamente con un editor de texto, ya que no es un archivo directamente evitable, como los archivos de código fuente que hemos usado hasta el momento.

Si lo hacemos, no deberemos extrañarnos de ver una serie de caracteres completamente extraños.

Y lo que es más importante, en el caso de que abramos la base de datos con editor de texto, deberemos abstenernos de realizar ninguna edición ni modificación, ya que eso podría hacer que la base de datos quedará completamente Inutilizable

Además, hay otro factor que debemos tener en cuenta, y es que al usar una librería, debemos vincular esa librería en el momento de la compilación del programa.

Es por esto que, si intentamos combinar el programa como hemos realizado el resto de combinaciones hasta el momento, podremos comprobar que nos da un error:

Para no tener este error en la pantalla, tenemos que llamar a la compilación de la siguiente manera:

Podremos comprobar, por un una parte, que establecemos un archivo de salida, y por otra parte, que realizamos un vínculo a la librería de conexión a la base de datos.

Ésa partir de este momento cuando podemos realizar, después de la compilación, una ejecución con respecto al archivo con el que estamos trabajando

Este parámetro de vinculación deberá mantenerse a lo largo del siguiente pack de ejercicios que se van a plantear para realizar las operaciones básicas con la base de datos

Conexión y creación de una base de datos

En el primer ejemplo desarrollado en esta publicación, nuestro objetivo es conectarnos a una nueva base de datos, y en un momento dado, más adelante,Mantener abierta la conexión con la Base de Datos para empezar a realizar diferentes tipos de peticiones, como vamos a ver más adelante en este capítulo

 es importante notar que este ejercicio inicial se ha creado intencionalmente sencillo, con el objetivo de demostrar que el proceso de conexión a una base de datos desde el lenguaje de programación C no tiene por qué ser especialmente difícil, me largo, ni oscuro

 es evidente, también, que a este sencillo código se le pueden añadir estructuras de control adicionales y opcionales, por ejemplo, para abarcar e implementar la programación defensiva desde el punto de vista de actuar presuponiendo que es posible que no podamos establecer una conexión con una base de datos

 una vez más, sin embargo, no es este el objetivo de este primer ejercicio, sino que el objetivo es realizar una primera conexión exitosa

 el código del ejercicio es el siguiente

main.c
#include <stdio.h>#include <sqlite3.h> 
int main(int argc, char* argv[]) {   sqlite3 *baseDeDatos;   sqlite3_open(«facturacion.db», &baseDeDatos);   sqlite3_close(baseDeDatos);}

 como podremos comprobar, en primer lugar, además de introducir la librería de entradas y salidas, hacemos referencia a la librería de bases de datos

 una vez que la hemos importado, es cuando podemos empezar a realizar conexiones, como podemos comprobar, en la función principal, creando en primer lugar una variable llamada base de datos, que es de un tipo específico que no se encuentra dentro del núcleo de fe, sino que ha sido un tipo importado por la librería que hemos importado anteriormente

 a continuación, la segunda línea es la más importante, ya que estamos abriendo una base de datos con un nombre concreto

 debemos tener en cuenta que, si la base de datos existía previamente, nos conectaremos a ella, pero el comportamiento por defecto de la libreria sqlite, si disponemos de permisos de archivo en la carpeta en la que estamos ejecutando el proyecto, es crear un nuevo archivo de base de datos en el caso de que la base de datos a la que estamos llamando no exista previamente, como es este el caso 

Por último, y como hemos comentado con anterioridad, tenemos la línea correspondiente al cierre de los recursos, que cierra nuestra conexión actual con la base de datos, liberando la para que cualquier otro usuario se pueda conectar sin tener problemas de bloqueo

 al ejecutar este código, si todo ha ido correctamente, podremos comprobar que al lado de nuestro script, al compilarlo y ejecutarlo, aparece una nueva base de datos con el nombre facturación

Crear tablas

Cuando creamos una nueva base de datos, está está vacía. en definitiva, es un contenedor vacío de información del que ahora mismo no podemos extraer mucha utilidad

 el siguiente nivel jerarquico dentro de cualquier base de datos de tipo SQL es la tabla. así que una base de datos puede y de hecho suele contener diferentes tablas dentro de ella

 el siguiente ejercicio trata la creación de una nueva tabla en la conexión que hemos realizado anteriormente punto por tanto, el código que se presenta a continuación es una extensión del código que hemos utilizado en el ejercicio anterior, para ampliarlo, y realizar una operación una vez que la conexión con la Base de Datos ha sido abierta 

main.c
#include <stdio.h>#include <stdlib.h>#include <sqlite3.h> 
static int exito(void *noUsado, int arg1, char **arg2, char **columnas) {   int i;   for(i = 0; i<arg1; i++) {      printf(«%s = %s\n», columnas[i], arg2[i] ? arg2[i] : «NULL»);   }   printf(«\n»);   return 0;}
int main(int argc, char* argv[]) {   sqlite3 *baseDeDatos;   char *msgError = 0;   int conexion;   char *peticion;
   /* Open database */   conexion = sqlite3_open(«test.db», &baseDeDatos);   /* Create SQL statement */   peticion = «CREATE TABLE facturas(»  \         «ID INT PRIMARY KEY     NOT NULL,» \         «cliente       TEXT NOT NULL,» \         «base            INT NOT NULL,» \         «fecha        CHAR(50),» \         «impuesto         INT );»;
   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);      if( conexion != SQLITE_OK ){   fprintf(stderr, «SQL error: %s\n», msgError);      sqlite3_free(msgError);   } else {      fprintf(stdout, «La tabla ha sido creada correctamente\n»);   }   sqlite3_close(baseDeDatos);   return 0;}

Centrándonos en primer lugar en la función principal, a continuación de la apertura de la base de datos, encontramos una variable llamada petición. la variable petición, de hecho, no es más que una cadena, que guarda la petición en el lenguaje sql, de la siguiente forma

 está petición, realmente, está escrita en un lenguaje bastante parecido al inglés de la calle, y básicamente nos está invitando a crear una tabla llamada facturas, que contendrá cuatro campos:

Un identificador, que se establece como una clave primaria auto no médica

 una columna reservada para el nombre del cliente, que es de tipo texto

 una columna con un tipo de dato de número entero para la base imponible de la factura

 una columna de 50 caracteres de amplitud máxima reservada para introducir la fecha

 y por último una columna de tipo de datos de número entero para introducir el impuesto que se aplicará sobre la base imponible

 con esto, ya tenemos el código en el qué establecemos cuál será la petición, pero esto no quiere decir, ni mucho menos, que hayamos ejecutado la propia petición

 la petición se ejecuta en la siguiente línea, en la que se lanza la frase en formato SQL contra la propia base de datos

 en el primer código que hemos utilizado, es decir, en el primer ejemplo, hemos asumido que la conexión con la Base de Datos va a funcionar correctamente. sin embargo, es beneficioso tener en cuenta que puede ocurrir cualquier percance que impida la correcta conexión de nuestro programa con la base de datos con la que pretendemos operar. es por esto que la siguiente estructura de control trata específicamente la captura de si la conexión se ha realizado correctamente, y si no ha sido así, devuelve un error en la consola, de tal forma que el propio error nos puede proporcionar algo de información en el caso de que se active, acerca de qué podemos hacer para solucionar el problema

 de todas formas, si todo funciona correctamente, esa función no se debería llegar a ejecutar, y por tanto no veríamos ningún mensaje de error en pantalla, es por esto que no debemos extrañarnos si el programa funciona correctamente y esa función de programación defensiva nunca se llega a ejecutar

Por último, vemos que la función de ejecución tiene un parámetro opcional que es la función que se ejecuta si la petición tiene éxito

 de hecho, ese ha sido exactamente el nombre que le he dado a la función, precisamente éxito

 así que en la parte superior del código podemos comprobar como he declarado que es lo que ocurre cuando se ejecuta la función de éxito

 sin embargo, una vez más, esa función está preparada para cuándo la utilicemos más adelante, especialmente en el momento en el que pedimos algo a la base de datos y se nos devuelve en pantalla. es decir, ahora mismo, en este ejercicio, es normal que la función de éxito no devuelva nada en la pantalla, ya que la creación de una nueva tabla no tiene porqué devolver un resultado por consola 

Insertar

Aquí es donde las cosas se ponen divertidas, o se ponen feas, según se mire

 por una parte, desde el punto de vista de la diversión, podremos encontrar que el siguiente ejemplo de código, que tiene como objetivo crear registros dentro de la tabla recién creada en la base de datos, es un código que deriva directamente y exactamente del ejercicio anterior

 podremos comprobar que, de hecho, el código el código del ejercicio es exactamente el mismo que en la propuesta anterior de ejercicio, con el único cambio de la petición SQL 

main.c
#include <stdio.h>#include <stdlib.h>#include <sqlite3.h> 
static int exito(void *noUsado, int arg1, char **arg2, char **columnas) {   int i;   for(i = 0; i<arg1; i++) {      printf(«%s = %s\n», columnas[i], arg2[i] ? arg2[i] : «NULL»);   }   printf(«\n»);   return 0;}
int main(int argc, char* argv[]) {   sqlite3 *baseDeDatos;   char *msgError = 0;   int conexion;   char *peticion;
   /* Open database */   conexion = sqlite3_open(«test.db», &baseDeDatos);   /* Create SQL statement */   peticion = «INSERT INTO facturas (ID,cliente,base,fecha,impuesto) »  \         «VALUES (1, ‘cliente1’, 3200, ‘2017-12-5’, 21 ); » \         «INSERT INTO facturas (ID,cliente,base,fecha,impuesto) »  \         «VALUES (2, ‘cliente2’, 4200, ‘2017-12-6’, 21 ); »     \         «INSERT INTO facturas (ID,cliente,base,fecha,impuesto) » \         «VALUES (3, ‘cliente3’, 1200, ‘2017-12-7’, 21 );» \         «INSERT INTO facturas (ID,cliente,base,fecha,impuesto) » \         «VALUES (4, ‘cliente1’, 2200, ‘2017-12-8’, 21  );»;
   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);      if( conexion != SQLITE_OK ){   fprintf(stderr, «SQL error: %s\n», msgError);      sqlite3_free(msgError);   } else {      fprintf(stdout, «Los registros han sido insertados correctamente\n»);   }   sqlite3_close(baseDeDatos);   return 0;}

La petición sql, que no es otra que la que se expresa a continuación

 se encarga básicamente de introducir cuatro registros dentro de la tabla facturas creada dentro de la base de datos

 una vez más, podremos observar que el lenguaje SQL es limpio y sencillo, y muchas veces, si tenemos una fluidez mínima con el lenguaje inglés, no nos costará nada aprender a manejar fluidamente el lenguaje sql, es decir, el lenguaje de manejo de las bases de datos 

Ahora bien, Las peticiones a bases de datos tienen un lado oscuro, que es que el propio lenguaje SQL no es nada permisivo en cuanto a los errores que podamos cometer

 hay un tipo de error muy común, y que generalmente no devuelve un código de error como tal, con lo cual es muy difícil de localizar, que consiste en enviar un número diferente de columnas a la base de datos con la que estamos trabajando

 nosotros como anteriormente, hemos creado una tabla que tiene cinco columnas, un identificador en primer lugar, y cuatro campos entre elementos de texto y elementos numéricos

 sí, al realizar una petición, pasamos 4 campos en lugar de 5, o 6 campos en lugar de 5, simplemente, el sistema no introducir a ningún campo. el problema es que, muy probablemente, en muchos entornos, ni siquiera da tampoco un error

 otro error bastante recurrente, por el que todos hemos pasado, y que a lo largo de los años he visto cometer a muchos alumnos, consiste en confundir cadenas de caracteres con números flotantes o enteros

 los campos numéricos se introducen en la base de datos, como podemos ver en el ejemplo que hemos desarrollado, sin comillas, mientras que los campos basados en texto, se introducen con comillas

 el hecho de pasarle una cadena de texto a un campo numérico, o el hecho de pasar un número, pero puesto con comillas, o el hecho de intentar introducir una cadena de texto sin poner comillas, son errores frecuentes que tampoco suelen generar un código de devolución de error, pero que, sin embargo, resultan en un intento fallido de inserción en la base de datos

 así que, en definitiva, los primeros intentos de introducir información en la base de datos, aunque teóricamente son sencillos, claros, y cristalinos, por experiencia puedo decir que acaban resultando bastante traumáticos, porque siempre parece haber una razón oculta e inexplicable por la cual los datos han acaban por no ser introducidos en la tabla donde los queremos meter

 simplemente, cuando esto ocurre, en una gran cantidad de casos, debemos comprobar varias veces la sintaxis para asegurarnos que no hemos cometido ningún error en el momento de escribir la sentencia SQL y además de no haber cometido errores, no tenemos una falta de concordancia en los tipos de datos o bien en el número de columnas 

Leer registros

Al leer registros, es cuando, por fin, le sacamos utilidad a la función de éxito, ya que, a diferencia de la inserción y otras operaciones, en las que la base de datos no tiene porqué devolver nada más que un ok, por definición la función de leer datos, tiene que tener un retorno, que es un listado de los propios datos que se han solicitado

 el ejemplo siguiente, de hecho, es exactamente igual que el anterior, únicamente cambia la sentencia SQL de realización de una petición a la base de datos, donde, por otra parte, podremos ver que, en su estado más sencillo, la sentencia de petición del Estado es relativamente sencilla con respecto a las dos sentencias que hemos visto anteriormente 

main.c
#include <stdio.h>#include <stdlib.h>#include <sqlite3.h> 
static int exito(void *noUsado, int arg1, char **arg2, char **columnas) {   int i;   for(i = 0; i<arg1; i++) {      printf(«%s = %s\n», columnas[i], arg2[i] ? arg2[i] : «NULL»);   }   printf(«\n»);   return 0;}
int main(int argc, char* argv[]) {   sqlite3 *baseDeDatos;   char *msgError = 0;   int conexion;   char *peticion;
   /* Open database */   conexion = sqlite3_open(«test.db», &baseDeDatos);   /* Create SQL statement */   peticion = «SELECT * from facturas;»;
   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);      if( conexion != SQLITE_OK ){   fprintf(stderr, «SQL error: %s\n», msgError);      sqlite3_free(msgError);   } else {      fprintf(stdout, «Registros listados correctamente\n»);   }   sqlite3_close(baseDeDatos);   return 0;}

La sentencia de petición básicamente nos dice que queremos realizar una selección, el asterisco nos indica que queremos de hecho seleccionarlo todo de esa tabla, y a continuación, indicamos la tabla con respecto a la cual queremos obtener información

 debemos tener en cuenta que, para este ejercicio, estamos trabajando con una única tabla, con lo cual podría parecer que el tercer parámetro no sería necesario, pero evidentemente sí que es completamente necesario en el caso de aplicaciones que tomen datos de varias tablas de forma simultánea, caso que, como podemos imaginar, es bastante común 

Por otra parte, la función de éxito, finalmente, atrapa los datos que devuelve el resultado de la petición, y los lanza por pantalla.

 podremos comprobar como en este caso, dentro de una estructura de bucle, se devuelven los datos directamente con una función de impresión, pero no es difícil imaginar que podríamos perfeccionar esta función de impresión para que los mostrará en una tabla en lugar de en un listado, o en definitiva, para personalizar la forma visual con la que queremos que se nos devuelvan los resultados en pantalla 

Actualizar registros

La operación de actualización de registros Sevasa, igualmente que en los ejercicios anteriores, en el código desarrollado en la última iteración de este bloque de ejercicios, donde estamos repasando las operaciones fundamentales de acceso a datos en cualquier tipo de motor de base de datos

 en este caso, lo que realizamos es una actualización

 este es uno de esos casos donde podemos disfrutar de que el motor de bases de datos que hay detrás de la existencia de petición trate toda la lógica interna y compleja

 cuando realizamos una actualización, seleccionamos un registro concreto de la base de datos, registro que puede estar completamente en mitad de toda la inmensidad de los datos, y modifica únicamente la pieza de información que nos interesa

 esta operación, cuando la hemos realizado de manera manual dentro de la unidad didáctica de persistencia, hemos podido comprobar como tiene una cierta dificultad en la realización

 sin embargo, si la realizamos dentro de este ejemplo, es decir, si realizamos esta misma operación desde el punto de vista de las bases de datos de tipo sql, podremos comprobar como la interfaz es clara y cristalina, nosotros trabajamos con el mínimo grado de dificultad, y el motor gestiona por nosotros toda esa dificultad añadida que hay en el fondo

 por tanto, repetimos el código que hemos desarrollado en la iteracion anterior, pero cambiamos la sentencia SQL a una sentencia de actualización 

main.c
#include <stdio.h>#include <stdlib.h>#include <sqlite3.h> 
static int exito(void *noUsado, int arg1, char **arg2, char **columnas) {   int i;   for(i = 0; i<arg1; i++) {      printf(«%s = %s\n», columnas[i], arg2[i] ? arg2[i] : «NULL»);   }   printf(«\n»);   return 0;}
int main(int argc, char* argv[]) {   sqlite3 *baseDeDatos;   char *msgError = 0;   int conexion;   char *peticion;
   /* Open database */   conexion = sqlite3_open(«test.db», &baseDeDatos);   /* Create SQL statement */   peticion = «UPDATE facturas SET base = 2400 WHERE ID = 4;»;
   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);      if( conexion != SQLITE_OK ){   fprintf(stderr, «SQL error: %s\n», msgError);      sqlite3_free(msgError);   } else {      fprintf(stdout, «Registro actualizado correctamente\n»);   }   sqlite3_close(baseDeDatos);   return 0;}

En la sentencia de actualización, en primer lugar, especificamos la tabla sobre la cual vamos a realizar un cambio punto

 a continuación, especificamos cuál es el cambio que vamos a realizar, indicando el nombre de la columna que recibirá la modificación, y el valor que introduciremos dentro de esa columna

 deberemos tener cuidado, ya que si no introducimos la condición a continuación, realizará el cambio sobre todas las filas de la tabla, con la consecuente pérdida de datos que ello puede conllevar. es por esto que la tercera parte de la petición, que es la condición, es donde especificamos cuál es el criterio para definir qué registro o qué registros deben ser modificados 

Eliminar registros

Una vez que hemos realizado todas las acciones anteriores, la única acción importante que nos queda por revisar es la eliminación de registros.

 una vez más, copiamos y pegamos el código de la operación anterior en un archivo nuevo, por supuesto para en todo momento mantener un registro de todos los archivos que hemos hecho hasta el momento, y modificamos la petición SQL para que tenga la forma que vemos en el código a continuación 

main.c
#include <stdio.h>#include <stdlib.h>#include <sqlite3.h> 
static int exito(void *noUsado, int arg1, char **arg2, char **columnas) {   int i;   for(i = 0; i<arg1; i++) {      printf(«%s = %s\n», columnas[i], arg2[i] ? arg2[i] : «NULL»);   }   printf(«\n»);   return 0;}
int main(int argc, char* argv[]) {   sqlite3 *baseDeDatos;   char *msgError = 0;   int conexion;   char *peticion;
   /* Open database */   conexion = sqlite3_open(«test.db», &baseDeDatos);   /* Create SQL statement */   peticion = «DELETE FROM facturas WHERE ID = 4;»;
   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);      if( conexion != SQLITE_OK ){   fprintf(stderr, «SQL error: %s\n», msgError);      sqlite3_free(msgError);   } else {      fprintf(stdout, «Registro eliminado correctamente\n»);   }   sqlite3_close(baseDeDatos);   return 0;}

Básicamente, la operación de eliminación es igual de peligrosa que la operación de actualización, por motivos muy similares

 como podemos comprobar, en primer lugar, especificamos que es lo que queremos borrar y desde que tabla lo queremos borrar

 en segundo lugar, muy importante, tenemos la condición donde seleccionamos el registro o los registros que queremos borrar

 si fallamos en poner esta segunda parte, es decir, si la omitimos, lo que hará el script es borrar la tabla entera sin pedir ningún tipo de permiso o confirmación punto es por esto que debemos ser especialmente cuidadosos en introducir este tipo de cláusula condicional, para asegurar que únicamente operamos, es decir, que únicamente eliminamos aquellas filas que en un momento dado nos interesan

 como apunte, decir que todos los desarrolladores que hemos trabajado con bases de datos, en algún momento u otro hemos cometido este error, es decir, introducir una sentencia de borrado sin poner una condición, con lo cual todos en algún momento hemos eliminado el contenido de alguna tabla

 así que, asumiendo está estadística, entiendo que en un momento u otro tú también lo harás, con lo cual deseo que, cuando lo hagas, la base de datos que sufra esa operación sea lo menos importante posible, y que en definitiva, aprendas esa lección, como todos la hemos aprendido, con el menor perjuicio posible 

Fusionando todas las acciones en un solo programa

En la parte anterior dentro de esta unidad didáctica, has podido ver como hemos desarrollado los scripts necesarios para realizar las operaciones más importantes durante el tratamiento de bases de datos, que ha consistido en primer lugar en crear una tabla dentro de una base de datos, y a continuación realizar las clásicas operaciones de lectura, escritura, eliminación, y actualización

 sin embargo, todo lo que hemos hecho hasta ahora, han sido en sí mismos programas independientes los unos de los otros, que han realizado tareas muy concretas que nos han servido para aprender

 sin embargo, como hubiera pasado anteriormente con el ejercicio práctico que habíamos desarrollado, lo más interesante va a ser y integrar todas esas piezas individuales en un único programa, donde, a través de un menú de selección inicial, podamos seleccionar la herramienta que queremos utilizar, sin tener que andar ejecutando diferentes programas

 es decir, en definitiva lo que vamos buscando es crear un único programa que tenga integradas todas las funcionalidades de manera clara y continua para el usuario final de nuestro programa, que es finalmente quién importa 

Por supuesto, el proceso de combinación de todos los archivos en un mismo proyecto es exactamente el mismo que hemos realizado en el ejercicio anterior

 sí bien el ejercicio anterior lo empezamos a desarrollar desde un principio como un proyecto monolitico, este caso tiene un principio un poco diferente, ya que partimos desde cuatro o cinco programas diferentes, y lo que queremos es unirlos en uno solo, aunque finalmente, la metodología y el resultado son exactamente los mismos

 por una parte, en el archivo principal, intentamos poner cuanto menos código mejor, dejando, eso sí, únicamente la función principal y derivando todas las funciones secundarias a archivos enlazados en las directivas del preprocesador

 evidentemente, notaremos, como, eso sí, la función principal tiene una llamada a conectar y mantener abierta una conexión con la Base de datos, y a mostrar el menú de selección de opción por parte del usuario 

Cómo podemos observar, aunque eso puede deducirse en las cabeceras, he creado una carpeta llamada funciones al lado del archivo principal, y dentro de esa carpeta llamada funciones, es donde he introducido todos los archivos con el código fuente 

Es un buen momento para indicar y recordar que, en este ejercicio, por claridad, en cada uno de los archivos he introducido una única función, y además, se cumple el principio no solo de que en cada archivo hay una sola función, sino que además el número del archivo refleja exactamente el nombre de la función

 esta metodología recomendada aunque no obligatoria sirve para saber, de un vistazo en la carpeta de funciones, exactamente cuál es la función que cumple cada uno de los archivos, y desde el punto de vista de la mantenibilidad del código, cuando quiero realizar alguna modificación o alguna ampliación, no tener que abrir inútilmente todos los archivos y perder tiempo en ello, sino que, de esta forma, se directamente cuál es el archivo que tengo que abrir

 sin embargo, no se puede negar que no es la única metodología de trabajo, ya que, también podría haber hecho un único archivo externo, llamado por ejemplo funciones. c, y haber introducido en ese archivo directamente todas las funciones

 probablemente perdería legibilidad y mantenibilidad, pero no tendría un listado tan grande de inclusiones dentro del preprocesador

 en definitiva, el mensaje es que la metodología que he escogido es una metodología recomendada aunque no obligatoria, pero que pienso que tiene más ventajas que inconvenientes 

main.c
#include <stdio.h>#include <stdlib.h>#include <sqlite3.h> #include «funciones/datosIniciales.c»#include «funciones/limpiarPantalla.c»#include «funciones/exito.c»#include «funciones/conectar.c»#include «funciones/listado.c»#include «funciones/insertar.c»#include «funciones/actualizar.c»#include «funciones/borrar.c»#include «funciones/menu.c»
int main(){       //conexion();        conectar();        menu();}

A continuación tenemos el Código del archivo de actualización. podremos comprobar que esté archivo únicamente tiene el código correspondiente a la petición de actualización a la base de datos, y aunque tiene una referencia a la función de éxito, esta función está declarada en un archivo diferente.

 por otra parte, podremos comprobar que, tanto en este archivo como en el resto de archivos que contienen funciones de conexión a la base de datos, Tenemos una llamada a una función de limpiar pantalla al principio del código, y una serie de líneas con una entrada por parte del usuario para volver al menú inicial después de cada operación, y por tanto, introducir el concepto de bucle infinito en cualquiera de las operaciones

main.c
void actualizar(){    limpiarPantalla();    /* Open database */   conexion = sqlite3_open(«test.db», &baseDeDatos);   /* Create SQL statement */   peticion = «UPDATE facturas SET base = 2400 WHERE ID = 4;»;
   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);   printf(«Pulsa una tecla para volver al menu inicial \n»);        getchar();        getchar();        menu();}

en la siguiente porción de código, al igual que hemos visto en el ejemplo anterior con la operación de actualización, tenemos la sentencia específica de borrado de la base de datos. igualmente, comprobamos como tenemos una llamada a la función de limpiar pantalla, y una serie de líneas de código para, al finalizar la instrucción, volver al menú principal

main.c
void borrar(){    limpiarPantalla();    /* Open database */   conexion = sqlite3_open(«test.db», &baseDeDatos);   /* Create SQL statement */   peticion = «DELETE FROM facturas WHERE ID = 4;»;
   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);   printf(«Pulsa una tecla para volver al menu inicial \n»);        getchar();        getchar();        menu();}

 la función de conexión a la base de datos se ejecuta antes que ningún tipo de función, y básicamente introduze una creación de una tabla, donde, si nos fijamos la sintaxis, en la petición sql, he introducido unas pocas palabras para controlar si la tabla existe o no existe.

 esto es importante porque, si la tabla existe previamente, al ejecutar la conexión, lanzaría un error y con toda probabilidad el programa se pararía

 pero si intento realizar una serie de operaciones con una tabla que no existe, evidentemente obtendría un error

 así que esta sentencia sql, básicamente, intenta averiguar si existe la tabla con la que quiero trabajar. si no la si no la encuentra, la crea, y si la encuentra, simplemente no hace nada y continúa trabajando 

main.c
#include <stdio.h>#include <stdlib.h>#include <../sqlite3.h>
    sqlite3 *baseDeDatos;   char *msgError = 0;   int conexion;   char *peticion;   void conectar(){      /* Open database */       conexion = sqlite3_open(«facturas.db», &baseDeDatos);        /* Create SQL statement */         /* Create SQL statement */   peticion = «CREATE TABLE IF NOT EXISTS facturas(»  \         «ID INT PRIMARY KEY     NOT NULL,» \         «cliente       TEXT NOT NULL,» \         «base            INT NOT NULL,» \         «fecha        CHAR(50),» \         «impuesto         INT );»;
   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);   peticion = «INSERT INTO facturas (ID,cliente,base,fecha,impuesto) »  \         «VALUES (1, ‘cliente1’, 3200, ‘2017-12-5’, 21 ); » \         «INSERT INTO facturas (ID,cliente,base,fecha,impuesto) »  \         «VALUES (2, ‘cliente2’, 4200, ‘2017-12-6’, 21 ); »     \         «INSERT INTO facturas (ID,cliente,base,fecha,impuesto) » \         «VALUES (3, ‘cliente3’, 1200, ‘2017-12-7’, 21 );» \         «INSERT INTO facturas (ID,cliente,base,fecha,impuesto) » \         «VALUES (4, ‘cliente1’, 2200, ‘2017-12-8’, 21  );»;
   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);}

Este archivo de código fuente, con tiene muy poca parte de código, pero, paradójicamente, requiere de bastante explicación

 la idea es que el menú es recursivo, entendiendo que es una función que se introduze al final de cada una de las llamadas a la base de datos

 vamos a visualizar lo de la siguiente forma dos puntos

 no podemos introducir en primer lugar, en el preprocesador del archivo principal, la llamada al menú, que a su vez llama a cada una de las funciones, porque en ese caso el menú se queja de que está llamando a unas funciones que todavía no existen porque todavía no han sido declaradas

 pero a la vez, cada una de las funciones, al final llama al menú, y esto quiere decir que tampoco podemos llamar primero las funciones y luego al menú, porque en ese caso nos pasa lo mismo, pero al revés

 así que la idea es que esta función declara que voy a utilizar una función llamada menú, pero todavía no estoy introduciendo su código, es decir, no estoy inicializando la función, y por tanto, no tengo el problema del orden de aparición de las funciones

 la idea de que no se puede llamar a una función que no se ha declarado todavía, ya que el compilador trabaja línea A línea, y no por archivos o proyectos completos como otros lenguajes de programación, constituye una limitación, y por tanto, esta técnica, que es la de declarar implícitamente las funciones antes de inicializar las, constituye una práctica muy extendida en este lenguaje de programación concreto, precisamente para sortear el problema que se nos da en este programa 

main.c
void menu();

Como nos podremos imaginar, el hecho de que todos los archivos llamen a una misma función de éxito, nos facilita las cosas desde el punto de vista de en que simplemente creamos la función de éxito en un archivo de código fuente separado, y lo preparamos para que pueda ser llamado desde cualquiera de las peticiones SQL 

main.c
static int exito(void *noUsado, int arg1, char **arg2, char **columnas) {   int i;   for(i = 0; i<arg1; i++) {      printf(«%s = %s\n», columnas[i], arg2[i] ? arg2[i] : «NULL»);   }   printf(«\n»);   return 0;}

main.c
void insertar(){    limpiarPantalla();     peticion = «CREATE TABLE facturas(»  \         «ID INT PRIMARY KEY     NOT NULL,» \         «cliente       TEXT NOT NULL,» \         «base            INT NOT NULL,» \         «fecha        CHAR(50),» \         «impuesto         INT );»;
   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);   printf(«Pulsa una tecla para volver al menu inicial \n»);        getchar();        getchar();        menu();}

La función de limpieza de pantalla, que es utilizada en prácticamente todas las funciones importantes de trabajo con base de datos, simplemente imprime un carácter especial que se encarga de avanzar el carro las suficientes líneas como para dar la impresión de que se ha borrado la pantalla 

main.c
void limpiarPantalla(){    printf(«\033[2J»);}

La función del Estado básicamente corresponde a la instrucción de selección de registros por partes de la base de datos, y no tiene más secreto que el archivo de inserción o el archivo de actualización

 simplemente se establece una petición a la base de datos, que, en este caso sí, será devuelta en pantalla de forma visual a través de la función de éxito

main.c
void listado(){    limpiarPantalla();    /* Create SQL statement */   peticion = «SELECT * from facturas;»;
   /* Execute SQL statement */   conexion = sqlite3_exec(baseDeDatos, peticion, exito, 0, &msgError);   printf(«Pulsa una tecla para volver al menu inicial \n»);        getchar();        getchar();        menu();}

Por último, la función del menú, crea en primer lugar un menú visual en pantalla recurriendo a la instrucción de impresión que tantas veces hemos usado con anterioridad, a continuación espera una entrada por parte del usuario, y procesa esa entrada mediante una estructura de control switch, que es la estructura encargada de ejecutar cada una de las funciones de tratamiento de base de datos que hemos declarado anteriormente punto

 finalmente, la estructura de este archivo es prácticamente idéntica a cómo funcionaba el menú de selección por parte de usuario en la aplicación anterior 

main.c
void menu(){    printf(«Programa de facturación v1.0 \n»);    printf(«1.-………..Listado \n»);    printf(«2.-………..Insertar \n»);    printf(«3.-………..Actualizar \n»);    printf(«4.-………..Borrar \n»);    printf(«Escoge una opción \n»);    char opcion = getchar();    printf(«La opción escogida es: %c»,opcion);    switch(opcion){        case ‘1’:            listado();            break;        case ‘2’:            insertar();            break;        case ‘3’:            actualizar();            break;        case ‘4’:            borrar();            break;    }}

Personalización de las funciones 

En la su unidad anterior, hemos cumplido el objetivo de integrar todo el programa como una unidad completa, en lugar de como una serie de partes inconexas entre sí

 una vez que hemos cumplido este objetivo, podremos comprobar como, en sí, nuestro programa es relativamente extraño desde el punto de vista de que siempre inserta los mismos registros, siempre inserta actualiza el mismo registro, y siempre borra el mismo registro

 es decir, permite una cierta interacción con el usuario, pero finalmente el usuario no puede seleccionar los datos nuevos que quiere insertar, no puede especificar que registro quiere borrar, ni tampoco qué es lo que quiere actualizar

 por tanto, A continuación, vamos a complementar esta aplicación utilizando lo que hemos aprendido previamente en cuanto a personalización de las funciones a través de parámetros, dado que esto nos servirá para llamar correctamente a las funciones, personalizando su aplicación, y en definitiva, haciendo del ejercicio de este curso un programa prácticamente final en cuanto a la usabilidad 

Publicado el Deja un comentario

Curso de Blender 2.8

En pocas semanas comienza la siguiente edición del curso de Blender. En esta nueva edición aprenderemos a crear imágenes y animaciones en 3D usando la última versión del programa, la 2.8.

En esta versión se han introducido múltiples mejoras, tanto en la interfaz de usuario, que cambia radicalmente con respecto a versiones anteriores, como en la inclusión de nuevas y potentes herramientas de modelado, de render, escultura, y simulación, entre otras.

Este curso está pensado tanto para usuarios nuevos del programa, que quieran aprender a crear sus propias animaciones desde cero, como para usuarios existentes que quieran actualizarse y aprender las novedades de las últimas versiones.

En este curso, que realizaremos a través de streaming, en directo, aprenderemos a usar el programa Blender 3D para crear nuestros propios proyectos de imagen y animacion tridimensional

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos sean capaces de crear imágenes y animaciones 3D

Si deseas recibir más información o inscribirte al curso, puedes hacerlo enviando el siguiente formulario:

Publicado el Deja un comentario

Curso de Python

En este próximo mes de Septiembre vamos a impartir un curso de Python. Este es uno de los lenguajes más sencillos de aprender, lo cual te habilita a desarrollar aplicaciones informáticas potentes de una forma fácil y sencilla.

Python es un lenguaje multiplataforma, lo que quiere decir que tus aplicaciones se podrán ejecutar, sin prácticamente modificar el código, en múltiples sistemas y dispositivos.

En este curso, que realizaremos a través de streaming, en directo, aprenderemos tanto los fundamentos de programación en Python, mostrándote cómo crear tus propias aplicaciones informáticas.

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de este curso es que los alumnos sean capaces de programar aplicaciones informáticas completas

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:

Publicado el Deja un comentario

Curso de Arduino

Aprovecha este mes de septimebre para formarte aprendiendo a montar y programar robots basados en el sistema Arduino. 

Gracias a Arduino, podemos crear ensamblajes electromecánicos de una forma muy fácil sencilla, y conveniente desde el punto de vista económico, siendo capaces de crear máquinas, y en el caso del objetivo de este curso, robots autónomos, qué podemos incluso programar utilizando un lenguaje de programación divertido y visual.

En este curso, que realizaremos a través de streaming, en directo, aprenderemos tanto los fundamentos de programación de Arduino, cómo a conectar las diferentes piezas y partes en la placa base.

El curso se realizará en directo, qué tal forma que los alumnos podrán ver en tiempo real el contenido que se va impartiendo, y podrán realizar preguntas y plantear dudas que serán resueltas en la misma clase. 

Las clases se grabarán, y las grabaciones se facilitarán a los alumnos, para que puedan repasar el contenido de las clases en cualquier momento.

El objetivo de esta acción formativa es que cada alumno acabe desarrollando su propio robot personalizado, construido a partir de un kit de inicio de Arduino. 

Si deseas obtener más información acerca de este curso, o incluso matricularte, puedes hacerlo a través del siguiente formulario de contacto:



Publicado el Deja un comentario

Programando en C: Libreria de tiempo

Capítulo 16: Libreria de tiempo

Control del tiempo

Dentro de la mayoría de los programas, la gestión del tiempo juega un papel fundamental.

Por ejemplo, cuando usamos registros, cuando un programa trabaja con registros que en un momento dado escribimos y que más adelante queremos leer, muchas veces es necesario introducir elementos tales como por ejemplo la fecha en la que ese registro quedó escrito.

de esta forma, en la gran mayoría de lenguajes de programación, junto al núcleo, es costumbre disponer de una librería específica de tratamiento del tiempo, que a su vez se suele dividir en dos librerías, una de tratamiento de la fecha, y otra de tratamiento del tiempo.

esto puede diferir a lo largo de los lenguajes de programación, pero generalmente, hay una serie de operaciones para tratar con años, meses, ideas, y hay otras operaciones para trabajar con horas, minutos, y segundos.

Adicionalmente, en cada una de las librerías, puede haber instrucciones adicionales tales como por ejemplo las que permiten contabilizar los números de días de cada mes, el número de semanas del año, los años bisiestos, etc.

en el caso del lenguaje de programación C, lo primero que tenemos que hacer para trabajar con fechas, es importar la siguiente librería.

main.c
#include <stdio.h>#include <time.h>
int main(int argc, char *argv[]) {    }


A continuación, y solo a partir de ese momento, es cuando podemos crear variables cuyo tipo de datos corresponde con la librería que acabamos de importar:

main.c


#include <stdio.h>#include <time.h>
int main(int argc, char *argv[]) {    time_t tiempo;}

A continuación se describe un sencillo programa que se encarga de devolver en pantalla la fecha actual.

main.c

#include <stdio.h>#include <time.h>
int main(int argc, char *argv[]) {    time_t tiempo;    char* tiempoCadena;    tiempo = time(NULL);    tiempoCadena = ctime(&tiempo);        printf(«El tiempo actual es: %s \n»,tiempoCadena);}

Clicks de ejecución de procesador

A través del ejemplo anterior hemos sido capaces de obtener la lectura del tiempo del sistema, en un formato preestablecido y estandarizado.

 en este ejemplo, usando la misma librería de tiempo, utilizamos una variable llamada clock, que nos permite obtener el número de clicks que han sido ejecutados por el reloj del procesador, desde que el programa está en funcionamiento

 los clics no se miden en tiempo, sino en operaciones, en instrucciones ejecutadas por el procesador

 este tipo de medida puede ser de utilidad para realizar comparaciones de rendimiento entre diferentes arquitecturas, en un mismo programa 

main.c
#include <stdio.h>#include <time.h>
int main() {     clock_t t1;      t1 = clock();    printf(«El reloj es: %li \n «,t1);}

Tiempo

Volviendo al primer ejemplo ilustrado en este capítulo, es posible que, en un momento dado, nos interese o tener una marca de tiempo en un formato más personalizado

 de esta forma, el siguiente ejemplo sigue usando la librería de tiempo, pero desglosa la información en 6 unidades principales, que son el año, el mes, el día, la hora, el minuto, y el segundo

 como podremos comprobar, mediante el almacenaje de estos datos en variables, más adelante, podemos formatear una fecha de una forma completamente personalizada 

main.c
#include <stdio.h>#include <time.h>
int main() {    time_t t = time(NULL);    struct tm tm = *localtime(&t);    printf(        «tiempo: %d-%d-%d %d:%d:%d\n»,         tm.tm_year + 1900,         tm.tm_mon + 1,         tm.tm_mday,         tm.tm_hour,         tm.tm_min,         tm.tm_sec        );}

Proyecto del curso

A continuación, aplicamos lo que hemos aprendido en esta unidad al ejercicio que estamos desarrollando a lo largo de la publicación

 la aplicación de la librería de tiempo, en este caso, sucede de forma que, en el menú principal, cada vez que lo ejecutamos, obtenemos un desglose del momento exacto en el que estamos ejecutando nuestro programa. nueva línea

 disfrutamos, una vez más, de la aplicación de la filosofía de divide y vencerás, al haber externalizado cada una de las funciones en un archivo de código de fuente diferente

 de esta forma, ahora no tenemos que ir arriba y abajo en un largo programa principal, buscando exactamente la línea en la que se encuentra el código que creemos modificar.

 como podemos comprobar en el listado de archivos a continuación, únicamente tenemos que modificar aquellos archivos donde intervenga la entrada del tiempo, como es el archivo principal, una nueva función creada a propósito para este efecto, y el archivo del menú principal. el resto de archivos de funciones, quedan completamente intacto 

dameFecha.c
#include <stdio.h>#include <time.h>
void dameFecha() {    time_t t = time(NULL);    struct tm tm = *localtime(&t);    printf(        «hoy es: %d-%d-%d %d:%d:%d\n»,         tm.tm_year + 1900,         tm.tm_mon + 1,         tm.tm_mday,         tm.tm_hour,         tm.tm_min,         tm.tm_sec        );}

agenda.c
/* Programa agendapor Jose Vicente Carratala */#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»#include <stdio.h>#include <string.h>#include «libAgenda/datos.c»#include «libAgenda/dameFecha.c»#include «libAgenda/listadoRegistros.c»#include «libAgenda/introducirRegistro.c»#include «libAgenda/eliminarRegistro.c»#include «libAgenda/buscarRegistro.c»#include «libAgenda/actualizarRegistro.c»#include «libAgenda/guardarDatos.c»#include «libAgenda/recuperarDatos.c»#include «libAgenda/menuPrincipal.c»
int main(int argc, char *argv[]) {
    // Primer registro    printf(«\033[2J»);    strcpy(agenda[1].nombre,»Jose Vicente»);    strcpy(agenda[1].telefono,»12345678″);    strcpy(agenda[1].email,»info@josevicentecarratala.com»);        // Segundo registro    strcpy(agenda[2].nombre,»Juan»);    strcpy(agenda[2].telefono,»53254″);    strcpy(agenda[2].email,»juan@josevicentecarratala.com»);    // Tercer registro    strcpy(agenda[3].nombre,»Jaime»);    strcpy(agenda[3].telefono,»64566″);    strcpy(agenda[3].email,»jaime@josevicentecarratala.com»); printf(«\033[2J»);    menuPrincipal(); return 0;}

menuPrincipal.c
void menuPrincipal(){ printf(«\033[2J»);     // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); dameFecha(); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«\t 6 – Guardar datos en un archivo \n»); printf(«\t 7 – Recuperar datos desde un archivo \n»); printf(«Tu opcion: «); char opcion = getchar(); printf(«La opción que has seleccionado es: %c \n»,opcion); switch(opcion){     case ‘1’:         listadoRegistros();         break;        case ‘2’:         introducirRegistro();         break;        case ‘3’:         eliminarRegistro();         break;        case ‘4’:         buscarRegistro();         break;     case ‘5’:         actualizarRegistro();         break;       case ‘6’:         guardarDatos();         break;       case ‘7’:         recuperarDatos();         break;        default:            printf(«La opción que has introducido no es válida»);             printf(«Pulsa Enter para volver al menú principal \n»);     getchar();     getchar();     printf(«\033[2J»);     menuPrincipal();                        break; }}
Publicado el Deja un comentario

Programando en C: Persistencia

Capítulo 15: Persistencia

Persistencia, qué es?

Hasta ahora, detrás del programa que hemos generado, trata información que existe previamente en variables, o bien que podemos introducir de forma manual.

El programa realiza las operaciones que sean necesarios, y finalmente, devuelve un resultado al ser humano.

Sin embargo, en el trabajo diario de un ser humano, generalmente, es necesario que esta información quede guardada de una forma permanente en algún soporte estable.

Esto quiere decir que, hasta el momento, cada programa que hemos hecho olvidar completamente sus datos en el momento que el programa es cerrado.

Si ponemos como ejemplo el programa que estamos desarrollando a lo largo de este curso, es decir, la agenda, nos habremos dado cuenta, que, al final de la ejecución del programa, todos los datos que hemos introducido quedan completamente perdidos, y cuando ejecutamos el programa de nuevo, tenemos que volverlos a introducir.

Huelga decir lo inconveniente que es este hecho, ya que, lo que muy probablemente desearíamos, es que todo el trabajo que hemos creado quede guardado de alguna manera, tal que la próxima vez que volvamos a ejecutar nuestro programa, los datos se encuentran en el mismo punto en el que los dejamos.

esto exactamente es la persistencia.

Consiste, básicamente, en asegurar que los datos quedan guardados en un soporte persistente, es decir, no en un soporte volátil como es por ejemplo la memoria RAM, sino en un soporte en los que los datos puedan sobrevivir, tal y como por ejemplo un disco duro, o una tarjeta de memoria.

Persistencia en archivos de texto

Una de las formas más básica y más clásica de realizar esta persistencia es utilizando archivos dentro del ordenador.

En un momento dado, el programa puede escribir en estos archivos la información que necesite, y recuperar, mediante una operación de lectura, la información que quede contenida dentro de este archivo.

existen fundamentalmente dos tipos de archivo en cualquier sistema operativo, los archivos binarios, y los archivos de texto.

El soporte para escribir archivos binarios y para poder leerlos depende inmensamente del lenguaje de programación en el que estemos trabajando.

Sin embargo, prácticamente cualquier lenguaje de programación incluye soporte para poder escribir y leer archivos en formato texto.

además, las instrucciones necesarias para poder leer y escribir archivos de texto, si bien rara vez se encuentran en el núcleo de un lenguaje de programación, sí que suelen encontrarse en esa colección de librerías por defecto añadidas al núcleo de cualquier lenguaje de programación.

escritura de archivos.

A continuación se muestra un ejemplo de código en el que, en primer lugar, se hace uso de una librería, con la que importamos la capacidad de poder leer y poder escribir archivos de texto.

A continuación, dentro del bloque inicial, dentro de la función principal, establecemos el código que nos permite, en primer lugar, abrir un archivo, y a continuación, escribir texto dentro de

El

main.c
#include <stdio.h>
int main(int argc, char** argv) {    FILE *archivo;    archivo = fopen(«prueba.txt»,»w»);    fprintf(archivo,»Esto es una prueba \n»);    fclose(archivo);    return 0;}

El cierre de los recursos.

siempre que trabajamos con archivos externos al propio programa principal, se entiende que, en el momento en el que abrimos un archivo, realmente estamos abriendo un recurso.

Esto es importante ya que, en la mayoría de ocasiones, cuando se abre un recurso este recurso queda bloqueado, para impedir que, mientras que tenemos el recurso abierto, cualquier otra persona desde cualquier otra ubicación pues pueda escribir dentro de él, introduciendo una situación de inconsistencia.

de esta manera, si el programa es capaz de bloquear un recurso para darnos acceso exclusivo a él, debemos tener cuidado de liberar el recurso una vez que hemos finalizado su utilización.

Es por esto que al final del programa que hemos mencionado anteriormente existe esta línea:

Que nos permite que el programa cierre, de manera manual, el recurso que estaba siendo utilizado.

aunque la mayoría de lenguajes de programación tienen mecanismos de cierre automático de recursos, bien cuando se dejan de usar, o bien cuando el programa se cierra, es importante acostumbrarse a cerrar los recursos de forma manual, ya que de otro modo, podemos cerrar el acceso accidentalmente a un recurso de manera temporal o de manera permanente, dificultando el trabajo de otras personas, o incluso de nosotros mismos cuando queremos acceder a ese recurso a través de cualquier otro medio que no sea el programa que lo ha bloqueado.

cómo leer un archivo

Una vez que ya somos capaces de escribir en un archivo, a continuación queremos leer su contenido.

Generalmente, en cualquier lenguajes de programación, leer un archivo de texto se basa en los siguientes pasos:

En primer lugar, abrimos el recurso y, opcionalmente, indicamos que la apertura es el modo de lectura.

A continuación, generalmente, las librerías de lectura de archivos trabajan línea a línea.

Esto quiere decir que tenemos que apoyarnos en una estructura de tipo guay que vaya recorriendo el archivo línea a línea, permitiéndonos realizar una operación sobre cada una de las líneas leídas.

En el ejemplo que ponemos a continuación, la operación consiste simplemente en devolver en la pantalla el contenido del archivo, aunque por supuesto, la operación podría consistir en introducir la línea en la memoria, trabajar con ella, etc.

main.c
#include <stdio.h>
int main(int argc, char** argv) {    char cadena[100];    FILE *archivo;    archivo = fopen(«prueba.txt»,»r»);    fprintf(archivo,»Esto es una prueba \n»);    while( fgets (cadena, 60, archivo)!=NULL ){        puts(cadena);    }    fclose(archivo);    return 0;}

Ejercicio del curso

agenda.c
/* Programa agendapor Jose Vicente Carratala */#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»#include <stdio.h>#include <string.h>#include «libAgenda/datos.c»#include «libAgenda/listadoRegistros.c»#include «libAgenda/introducirRegistro.c»#include «libAgenda/eliminarRegistro.c»#include «libAgenda/buscarRegistro.c»#include «libAgenda/actualizarRegistro.c»#include «libAgenda/guardarDatos.c»#include «libAgenda/recuperarDatos.c»#include «libAgenda/menuPrincipal.c»
int main(int argc, char *argv[]) {
    // Primer registro    printf(«\033[2J»);    strcpy(agenda[1].nombre,»Jose Vicente»);    strcpy(agenda[1].telefono,»12345678″);    strcpy(agenda[1].email,»info@josevicentecarratala.com»);        // Segundo registro    strcpy(agenda[2].nombre,»Juan»);    strcpy(agenda[2].telefono,»53254″);    strcpy(agenda[2].email,»juan@josevicentecarratala.com»);    // Tercer registro    strcpy(agenda[3].nombre,»Jaime»);    strcpy(agenda[3].telefono,»64566″);    strcpy(agenda[3].email,»jaime@josevicentecarratala.com»); printf(«\033[2J»);    menuPrincipal(); return 0;}

menuPrincipal.c
void menuPrincipal(){ printf(«\033[2J»);     // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«\t 6 – Guardar datos en un archivo \n»); printf(«\t 7 – Recuperar datos desde un archivo \n»); printf(«Tu opcion: «); char opcion = getchar(); printf(«La opción que has seleccionado es: %c \n»,opcion); switch(opcion){     case ‘1’:         listadoRegistros();         break;        case ‘2’:         introducirRegistro();         break;        case ‘3’:         eliminarRegistro();         break;        case ‘4’:         buscarRegistro();         break;     case ‘5’:         actualizarRegistro();         break;       case ‘6’:         guardarDatos();         break;       case ‘7’:         recuperarDatos();         break;        default:            printf(«La opción que has introducido no es válida»);             printf(«Pulsa Enter para volver al menú principal \n»);     getchar();     getchar();     printf(«\033[2J»);     menuPrincipal();                        break; }}

guardarDatos.c
void guardarDatos(){    printf(«\033[2J»);    // Creamos un archivo    FILE *archivo;    archivo = fopen(«agenda.txt»,»w»);    // Recorremos los registros uno a uno, los mostramos por pantalla    for(int i = 1; i<=longitudDatos;i++){        fprintf(archivo,»%s|%s|%s \n»,agenda[i].nombre,agenda[i].telefono,agenda[i].email);    }    fclose(archivo);    // Volvemos al menu principal    printf(«Pulsa Enter para volver al menú principal \n»);    getchar();    getchar();    printf(«\033[2J»);    menuPrincipal();}

recuperarDatos.c
void recuperarDatos(){        printf(«\033[2J»);    // Declaraciones iniciales        char cadena[80];       const char delimitador[2] = «|»;       char *partido;       FILE *archivo;   // Abrimos un archivo    archivo = fopen(«agenda.txt»,»r»);   // Leemos el archivo linea a linea        while( fgets (cadena, 60, archivo)!=NULL ){            // Partimos lineas a structs                partido = strtok(cadena, delimitador);                int contador = 0;                longitudDatos++;                while( partido != NULL ) {                  if(contador == 0){strcpy(agenda[longitudDatos].nombre,partido);}                  if(contador == 1){strcpy(agenda[longitudDatos].telefono,partido);}                  if(contador == 2){strcpy(agenda[longitudDatos].email,partido);}                  partido = strtok(NULL, delimitador);                  contador++;               }        }   // Feedback al usuario        printf(«Registros cargados, pulsa una tecla para volver al menu inicial \n»);        getchar();        getchar();    // Volvemos al menu principal        printf(«\033[2J»);        menuPrincipal();   }

Sobre la instruccion de partir cadenas a mtriz

main.c
#include <stdio.h>#include <string.h>
int main(int argc, char** argv) {    char cadena[80] = «primero|segundo|tercero»;   const char delimitador[2] = «|»;   char *partido;      partido = strtok(cadena, delimitador);      while( partido != NULL ) {      printf( » %s\n», partido );          partido = strtok(NULL, delimitador);   }      return(0);}

Publicado el Deja un comentario

Programando en C: Desarrollo de las diferentes partes del programa del curso

Capítulo 13: Desarrollo de las diferentes partes del programa del curso

agenda.c
/* Programa agendapor Jose Vicente Carratala */#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»#include <stdio.h>#include <string.h>#include «libAgenda/datos.c»#include «libAgenda/listadoRegistros.c»#include «libAgenda/introducirRegistro.c»#include «libAgenda/eliminarRegistro.c»#include «libAgenda/buscarRegistro.c»#include «libAgenda/actualizarRegistro.c»#include «libAgenda/menuPrincipal.c»
int main(int argc, char *argv[]) {
    // Primer registro    printf(«\033[2J»);    strcpy(agenda[1].nombre,»Jose Vicente»);    strcpy(agenda[1].telefono,»12345678″);    strcpy(agenda[1].email,»info@josevicentecarratala.com»);        // Segundo registro    strcpy(agenda[2].nombre,»Juan»);    strcpy(agenda[2].telefono,»53254″);    strcpy(agenda[2].email,»juan@josevicentecarratala.com»);    // Tercer registro    strcpy(agenda[3].nombre,»Jaime»);    strcpy(agenda[3].telefono,»64566″);    strcpy(agenda[3].email,»jaime@josevicentecarratala.com»); printf(«\033[2J»);    menuPrincipal(); return 0;}

datos.c
struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };        struct RegistroAgenda agenda[100];        int longitudDatos = 3;

listadoRegistros.c
void listadoRegistros(){    printf(«\033[2J»);    // Recorremos los registros uno a uno, los mostramos por pantalla    for(int i = 1; i<=longitudDatos;i++){        printf(«Registro: %s %s %s \n»,agenda[i].nombre,agenda[i].telefono,agenda[i].email);    }    // Volvemos al menu principal    printf(«Pulsa Enter para volver al menú principal \n»);    getchar();    getchar();    printf(«\033[2J»);    menuPrincipal();}

introducirRegistro.c
void introducirRegistro(){    printf(«\033[2J»);    // Información al usuario        printf(«Vamos a introducir un registro \n»);    // Solicitamos el nombre        printf(«Indica el nombre del contacto: \n»);        char nombre[100];        scanf(«%s»,nombre);    // Solicitamos el telefono        printf(«Indica el telefono del contacto: \n»);        char telefono[100];        scanf(«%s»,telefono);    // Solicitamos el email        printf(«Indica el email del contacto: \n»);        char email[100];        scanf(«%s»,email);    // Aumentamos el indice de la matriz        longitudDatos++;    // Creamos una nueva estructura        strcpy(agenda[longitudDatos].nombre,nombre);        strcpy(agenda[longitudDatos].telefono,telefono);        strcpy(agenda[longitudDatos].email,email);    // Feedback al usuario        printf(«Registro añadido, pulsa una tecla para volver al menu inicial \n»);        getchar();        getchar();    // Volvemos al menu principal        printf(«\033[2J»);        menuPrincipal();    }

eliminarRegistro.c
void eliminarRegistro(){    printf(«\033[2J»);    // Mensaje informativo para el usuario        printf(«Vamos a eliminar un registro»);    // Solicitamos el id a eliminar        printf(«Introduce el id del registro a eliminar: \n»);        getchar();        int id = getchar();    // Recorremos la matriz copiando el siguiente registro, en el anterior, a partir del registro indicado        for(int i = id;i<longitudDatos;i++){            agenda[i] = agenda[i+1];        }    // Recortamos la longitud de los datos        longitudDatos–;    // Volvemos al menu inicial        printf(«Pulsa Enter para volver al menu principal»);        getchar();        getchar();        printf(«\033[2J»);        menuPrincipal();}

buscarRegistro.c
void buscarRegistro(){    printf(«\033[2J»);    // Mensaje informativo para el usuario        printf(«Vamos a buscar un registro \n»);    // Introducimos el nombre a buscar        printf(«Introduce el nombre del contacto: \n»);        char nombre[100];        scanf(«%i»,nombre);    // Recorremos la matriz registro a registro, comparando la cadena        for(int i = 1;i<=longitudDatos;i++){            if(strcmp(nombre,agenda[i].nombre) != 0){                printf(«Registro: %s %s %s \n»,agenda[i].nombre,agenda[i].telefono,agenda[i].email);            }        }    // Volvemos al menu principal        printf(«Pulsa Enter para volver al menu principal»);        getchar();        getchar();        printf(«\033[2J»);        menuPrincipal();}

actualizarRegistro.c
void actualizarRegistro(){    printf(«\033[2J»);    // Informamos al usuario        printf(«Vamos a actualizar un registro \n»);    // Introducimos el identificador del contacto        printf(«Introduce el id del contacto: \n»);        getchar();        int idmodificar = getchar();        idmodificar -= 48; // Convertimos de ASCII a numero    // Informamos al usuario del id que se va a modificar        printf(«Has introducido el id para modificar: %d \n»,idmodificar);    // Solicitamos el nuevo nombre        printf(«Introduce el nuevo nombre del contacto: (anterior: %s) \n»,agenda[idmodificar].nombre);        char nombre[100];        scanf(«%s»,nombre);    // Solicitamos el nuevo telefono        printf(«Introduce el nuevo telefono del contacto: (anterior: %s) \n»,agenda[idmodificar].telefono);        char telefono[100];        scanf(«%s»,telefono);    // Solicitamos el nuevo email        printf(«Introduce el nuevo email del contacto: (anterior: %s) \n»,agenda[idmodificar].email);        char email[100];        scanf(«%s»,email);    // Creamos una nueva estructura        strcpy(agenda[idmodificar].nombre,nombre);        strcpy(agenda[idmodificar].telefono,telefono);        strcpy(agenda[idmodificar].email,email);    // Feedback al usuario        printf(«Registro añadido, pulsa una tecla para volver al menu inicial \n»);        getchar();        getchar();    // Volvemos al menu principal        printf(«\033[2J»);        menuPrincipal();    }

menuPrincipal.c
void menuPrincipal(){ printf(«\033[2J»);     // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«Tu opcion: «); char opcion = getchar(); printf(«La opción que has seleccionado es: %c \n»,opcion); switch(opcion){     case ‘1’:         listadoRegistros();         break;        case ‘2’:         introducirRegistro();         break;        case ‘3’:         eliminarRegistro();         break;        case ‘4’:         buscarRegistro();         break;     case ‘5’:         actualizarRegistro();         break;        default:            printf(«La opción que has introducido no es válida»);             printf(«Pulsa Enter para volver al menú principal \n»);     getchar();     getchar();     printf(«\033[2J»);     menuPrincipal();                        break; }}

agenda.c

agenda.c

Publicado el Deja un comentario

Programando en C: Funciones

Capítulo 11: Funciones

¿Qué son las funciones?

Las funciones existen para cubrir varias necesidades que el programador acaba teniendo en su día a día.

De hecho, en nuestro caso, tal y como llevamos ahora mismo el ejercicio del curso, veremos que el uso de funciones no supone claras ventajas para mantener nuestro código entendible y mantenerle.

podemos incluso concebir las funciones como pequeños programas dentro de un programa más grande, ya que son bloques de código encapsulados que aceptan una entrada, realizar un cálculo, y devuelven un resultado.

La diferencia es que, si bien el programa original acepta una entrada usualmente proporcionada por el ser humano, y ofrece una salida también usualmente al ser humano, las funciones son pequeños programas que existen dentro del programa principal, y es por esto que, muy generalmente, aceptan datos no del ser humano sino del programa principal, y devuelven datos no al ser humano, sino al programa principal.

por tanto, el concepto principal cuando hablamos de funciones es el de la encapsulación. Es decir, introducir una pieza del código que tenga sentido como bloque, y aislarla del resto del código.

Esto, en un momento dado, puede tener claras y evidentes ventajas.

en primer lugar, es muy común, durante el desarrollo de un programa informático, que haya porciones de código que se repitan.

Las funciones nos proporcionan una posibilidad fantástica de aislar estas porciones en una función, y simplemente llamar a la función tantas veces como sea necesario, centralizando el código, y evitando repeticiones innecesarias que dificultan enormemente la mantenía peligrar del código.

de esta forma, y como podemos imaginar, lo principal que debemos aprender con respecto a las funciones es, en primer lugar, como declararlas, y en segundo lugar, cómo usarlas.

Así que, vamos a poner un primer ejemplo, en el que tendríamos, por ejemplo, un programa que realiza la siguiente función:

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    printf(«Hola, Jose Vicente \n»); return 0;}

de hecho todo el tiempo hemos estado trabajando con una función principal, una función que se encarga de establecer el punto de entrada del programa, así que, en el fondo, el uso de funciones no no se es extraño en absoluto, ya que, sin quererlo, las llevamos usando desde el principio de nuestra andadura con este lenguaje de programación.

Declaración de funciones

Ahora, lo importante, es que en un momento dado, podemos declarar nuevas funciones.

Dependiendo del lenguaje de programación, podemos declarar nuevas funciones antes o después de la función principal.

Eres de caso, lo que haremos, por compatibilidad, es declarar nuestras funciones antes de la función principal, para que cuando se profesen, el sistema sea consciente primero de nuestras funciones, y luego desuso

Así que el código anterior se transforma en el siguiente código.

main2.c
#include <stdio.h>void saluda(){    printf(«Hola, Jose Vicente \n»);}int main(int argc, char *argv[]) {     return 0;}

Como podemos observar, al declarar una función, en primer lugar, declaramos el tipo de dato te va a devolver la función.

A continuación, establecemos el nombre del programa, siguiendo las reglas de estilo que hemos visto anteriormente.

Lo siguiente que podemos observar, es que las funciones, Mediante la aparición de unos paréntesis, pueden aceptar parámetros. Sin embargo, para este primer ejemplo, vamos a crear una función sin necesidad de poner parámetros.

Deberemos tener en cuenta, eso sí, que aunque la función no acepte parámetros, es obligatorio poner los paréntesis, aunque finalmente se queden vacíos.

Por último, encerrado entre llaves, encontramos el código que se va a ejecutar en el momento en el que se llame a la función.

Así que, finalmente, nuestro código quedaría de la siguiente forma:

main2.c
#include <stdio.h>void saluda(){    printf(«Hola, Jose Vicente \n»);}int main(int argc, char *argv[]) {     return 0;}

Sin embargo, si ejecutamos el código que he descrito anteriormente, podremos comprobar que el programa no hace nada.

Este es un concepto muy importante que debemos entender del uso de el cabo Encapsulación es, y en este caso, del uso de funciones.

En el momento en el que yo creo una cápsula, es decir, en el momento en el que creamos una función, eso no implica que la función se esté ejecutando.

Si nos fijamos, ocurre exactamente lo mismo que cuando declaramos variables.

El hecho de que yo declare una variable, no implica, en absoluto, que yo estoy usando esa variable. Con las funciones ocurre exactamente lo mismo, que yo esté declarando una función no implica, en absoluto, que esté ejecutando esa función.

Lo único que estoy haciendo es introduciendo esa función en la memoria, y preparando el programa para cuando yo la llame, pero el caso es que, de momento, no he llamado a la función

Uso de funciones

Una vez que hemos definido una función, a continuación, probablemente querremos llamarla.

Mediante la invocación de una función, ejecutamos el código que está contiene.

Así que, por ejemplo, en la función principal, vamos a escribir el siguiente código:

main.c
#include <stdio.h>void saluda(){    printf(«Hola, Jose Vicente \n»);}int main(int argc, char *argv[]) {    saluda(); return 0;}

De esta forma, si ahora ejecutamos el programa, cómo podremos comprobar, obtenemos de vuelta la ejecución del código que contiene la función.

De esta forma, hemos visto como declarar en primer lugar una función, y a continuación, utilizarlo

Funciones con parámetros

Lo que hemos visto hasta el momento en cuanto al trabajo con funciones, ya es útil desde el punto de vista en que nos permite aislar porciones de código, y eventualmente, en el caso de que esa porción se repita, nos permite simplificar y reducir la repetición, mediante la definición invocación de funciones.

Sin embargo, los parámetros nos permiten aumentar todavía más la potencia de las funciones mediante la personalización de su función.

La función que hemos declarado anteriormente tiene un único comportamiento es decir, tiene una única posibilidad de ejecución.

Así que, si en lugar de querer una función que me salude a mí, quiero una función y que salude a cualquier otro nombre de persona, tendría que escribir tantas funciones como nombres de personas pudiera imaginar.

Como podemos imaginarnos, esto sería terriblemente ineficiente para lo que son los mecanismos y las estructuras de un lenguaje de programación.

Para esto precisamente existen los parámetros de las funciones. Los parámetros nos permiten personalizar y adaptar el comportamiento de una función, para que se comporte de tantas maneras como necesitemos.

así que, en el ejemplo anterior, voy a introducir un parámetro dentro del paréntesis, al que llamaré nombre.

El código anterior, queda de la siguiente manera:

main4.c
#include <stdio.h>void saluda(char* nombre){    printf(«Hola, %s \n»,nombre);}int main(int argc, char *argv[]) {    saluda(); return 0;}

Si ahora intento ejecutar el código en la función principal de la misma forma que lo había hecho hasta el momento, ahora obtendré un error de vuelta, producido evidentemente por el hecho de que yo ahora estoy prometiendo que la función afecta un parámetro, Pero sin embargo, cuando la invoco, no le estoy pasando este parámetro.

Lo que ocurre en ese momento depende en gran medida de lo permisivo que sea el lenguaje de programación, pero en la mayoría de los casos, el resultado es un error debido a que no estoy invocando la función de la forma correcta, es decir, no la estoy invocando con las mismas reglas que la he definido.

Si ahora introduzco un parámetro de los paréntesis, la función vuelve a funcionar correctamente.

main5.c
#include <stdio.h>void saluda(char* nombre){    printf(«Hola, %s \n»,nombre);}int main(int argc, char *argv[]) {    saluda(«Jose Vicente»); return 0;}

Pero sobre todo, lo más importante, es que puedo llamar varias veces a la función, y en cada una de las ejecuciones, puedo llamar a un parámetro diferente.

Si ahora, dentro de los paréntesis, introducimos diferentes nombres de persona, comprobaremos que tenemos una misma función que puede tener múltiples comportamientos, todo ello basado en los parámetros que tiene la función

Funciones con múltiples parámetros

por supuesto, una función no solo puede aceptar un parámetro, sino que generalmente acepta varios de ellos.

Eres de ejemplo, voy a extender la función para introducir un segundo parámetro, no Merico, que sea la edad.

main6.c
#include <stdio.h>void saluda(char* nombre, int edad){    printf(«Hola, %s, tienes %i años \n»,nombre,edad);}int main(int argc, char *argv[]) {    saluda(«Jose Vicente»,40); return 0;}

Como habremos observado anteriormente, lo único importante al declarar parámetros de funciones, es que exista una coincidencia absoluta entre el nombre del parámetro cuando lo declaramos en los paréntesis, y el nombre del parámetro cuando lo utilizamos dentro del código.

Así que, de esta manera, si introduzco dos parámetros dentro de los paréntesis, y los uso correctamente dentro del código, podremos observar, evidentemente llamando correctamente a la función dentro del método print principal, como, sin ningún problema, la función ahora puede trabajar con dos parámetros

Sobrecarga de parametros

El concepto de sobrecarga tiene, usualmente, connotaciones negativas cuando lo aplicamos a cualquier otro aspecto de la vida.

Cuando sobrecargamos algo, quiere decir que lo estamos cargando con más carga de la que nominalmente puede soportar.

Y como podemos imaginar, cuando cargamos algo con más carga de la que nominalmente puede soportar, lo más probable es que ese objeto se rompa o se parta.

Sin embargo, en el mundo de la programación funcional el concepto de sobrecarga tiene una connotación absolutamente positiva, y es que nos permite hacer que una función se comporte de varias formas diferentes.

Mediante la sobrecarga, podemos definir una misma función para que tenga diferentes comportamientos en base al número de parámetros que va a contener.

main7.c
#include <stdio.h>void saluda(char* nombre, int edad){    printf(«Hola, %s, tienes %i años \n»,nombre,edad);}
void saluda(char* nombre, int edad){    printf(«Hola, %s \n»,nombre);}int main(int argc, char *argv[]) {    saluda(«Jose Vicente»,40); return 0;}

Al igual que ocurre con las variables yo no podría declarar dos veces una función, ya que si intento ejecutar el código, naturalmente dará error.

Sin embargo, lo que sí que puedo hacer, y en ocasiones resulta extremadamente conveniente, es definir varias veces una función, cambiando elementos tales como por ejemplo el tipo de dato devuelto, o el número de parámetros.

así pues, de esta manera, retomando el ejemplo anterior, yo podría desear llamar a la función a veces solo con el nombre, y otras veces con el nombre y la edad.

si no hiciera esto, lo que ocurriría, es que tendría que usar dos funciones diferentes, es decir, dos nombres de función completamente diferenciados.

Sin embargo, si escribo el código que ves a continuación:

main.c

Verás que no hay ningún problema en llamar, en el código principal, unas veces a la función solo introduciendo el nombre como parámetro, y otras veces a la función introduciendo tanto el nombre como la edad.

Por supuesto las funciones no solo admiten una sobrecarga, sino que pueden admitir tantas sobrecargas como necesitemos, con respecto a nuestras necesidades dentro del programa

El ámbito de las variables:

Hay un concepto de vital importancia durante el desarrollo de aplicaciones, qué consiste en controlar el ámbito de las variables. el ámbito hace referencia al contexto en el que esas variables existen

 la regla en cuanto al ámbito de las variables es realmente sencilla. si una variable se declara dentro de una función, s.a. variable sólo existe, y por tanto solo puede usarse, dentro de esa función.

 sí intentamos llamar a esa variable fuera de la función, encontraremos que el programa no reconoce el valor de esa variable, como en el ejemplo siguiente

 sin embargo, si esa variable ha sido declarada fuera de la función, y por tanto, con respecto al lenguaje de programación que estamos cubriendo en esta publicación, ha sido declarada fuera de todas las funciones, pasa a conocerse con el nombre de variable global, y por tanto es una variable que existe, y por tanto se comparte entre las diferentes funciones que comparten un programa

 en definitiva, el conocimiento de la existencia del ámbito de las variables nos permite jugar, ya que hay casos en los que nos interesa que una variable solo exista, solo tenga sentido, solo se pueda modificar desde dentro de una función, y hay otras muchas veces en las que nos interesa que una variable pueda ser modificada a lo largo de las diferentes funciones de un programa 

Ejercicio del curso

Código fuente de nuestro programa se va alargando, y en cierta forma, se va complicando

Es por esto que empezamos a aislar el contenido y la funcionalidad de cada una de las opciones que se le ofrece al usuario, en una función diferente punto en esta fase del ejercicio, antes de la función principal, declaramos una serie de funciones, donde cada una de ellas corresponde a cada una de las opciones que se le proporcionan al usuario. incluso definimos una función que corresponde al propio menú del programa

 una vez que estas funciones han sido declaradas en la parte inicial del programa, esto es, recomendablemente siempre antes de la función principal, a continuación, extraemos el código de cada una de las opciones del usuario, y lo introducimos dentro de cada una de las funciones que hemos creado anteriormente

 por último, en la función de menú principal, en cada una de las opciones, reemplazamos el código original con la llamada a la función correspondiente. al realizar esta acción, podremos comprobar como el código resultante es, de momento, igualmente grande, pero desde luego mucho más legible de lo que era anteriormente

 el último paso, en este caso, consiste simplemente en realizar una llamada a la función de menú principal, desde la propia función principal del programa 

agenda.c
/* Programa agendapor Jose Vicente Carratala */#include <stdio.h>#include <string.h>#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»
struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };        struct RegistroAgenda agenda[100];void listadoRegistros(){    for(int i = 1; i<=3;i++){        printf(«Registro: %s %s %s \n»,agenda[i].nombre,agenda[i].telefono,agenda[i].email);    }}void introducirRegistro(){    printf(«Vamos a introducir un registro»);}void eliminarRegistro(){    printf(«Vamos a eliminar un registro»);}void buscarRegistro(){    printf(«Vamos a buscar un registro»);}void actualizarRegistro(){    printf(«Vamos a actualizar un registro»);}void menuPrincipal(){     // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«Tu opcion: «); char opcion = getchar(); printf(«La opción que has seleccionado es: %c \n»,opcion); switch(opcion){     case ‘1’:         listadoRegistros();         break;        case ‘2’:         introducirRegistro();         break;        case ‘3’:         eliminarRegistro();         break;        case ‘4’:         buscarRegistro();         break;     case ‘5’:         actualizarRegistro();         break;        default:            printf(«La opción que has introducido no es válida»);            break; }}int main(int argc, char *argv[]) {
    // Primer registro        strcpy(agenda[1].nombre,»Jose Vicente»);    strcpy(agenda[1].telefono,»12345678″);    strcpy(agenda[1].email,»info@josevicentecarratala.com»);        // Segundo registro    strcpy(agenda[2].nombre,»Juan»);    strcpy(agenda[2].telefono,»53254″);    strcpy(agenda[2].email,»juan@josevicentecarratala.com»);    // Tercer registro    strcpy(agenda[3].nombre,»Jaime»);    strcpy(agenda[3].telefono,»64566″);    strcpy(agenda[3].email,»jaime@josevicentecarratala.com»);    menuPrincipal(); return 0;}

Externalización del contenido del programa en diferentes archivos.

en el desarrollo de aplicaciones informáticas suele aplicarse la regla de » divide y vencerás » con bastante éxito.

aunque existen ocasiones en las que está justificado mantener un código monolítico, una gran pieza de código contenida en un único archivo o en un pequeño conjunto de archivos, por regla general, la recomendación es justo la contraria:

Mantener el código separado en un número razonable y justificado de archivos independientes, para ver esta manera, Mantener el código modular izado, independiente, y más fácilmente mantenerle.

todo el código que hemos desarrollado hasta ahora, está dentro de un único archivo, en el caso tanto de los ejercicios individuales, como en el caso del proyecto continuo que vamos realizando unidad a unidad.

A continuación, se muestra un ejemplo en el que partimos del siguiente código:

main.c
#include <stdio.h>int calculadoraSuma(int operando1, int operando2){    return(operando1 + operando2);}int main(int argc, char *argv[]) {    printf(«El resultado es: %i \n»,calculadoraSuma(5,4)); return 0;}

Como podemos ver, tenemos una función principal, y también tenemos una función que antecede a la función principal, que cumple un cometido concreto, sea cual sea.

una estrategia que podemos cumplir es la de externalizar esa función no principal en un archivo que puede estar adherido al archivo inicial, o puede estar incluido dentro de una carpeta.

para este ejemplo, dentro de la estructura de directorios, dentro de la misma carpeta donde se encuentra el proyecto actual, donde encontramos el código del archivo principal.

Dentro de esta carpeta, creamos una nueva su carpeta, y le ponemos el nombre que queramos, siguiendo las mismas reglas de estilo que estamos utilizando a lo largo de todo el desarrollo.

Por ejemplo, la carpeta puede recibir el nombre de » librerías «

dentro de esta carpeta, creamos un nuevo archivo con la extensión C, donde introduciremos nuestro código. Es decir, cortamos el código de la función no principal desde el archivo mail. C, hasta el archivo que acabamos de crear dentro de la carpeta librerías. Por ejemplo, le ponemos el nombre saludar. C, y pegamos dentro de él el contenido cortado, es decir, la función.

lib/calculadoraSuma.c
int calculadoraSuma(int operando1, int operando2){    return(operando1 + operando2);}

debemos tener cuidado porque, si no estamos trabajando en un entorno de desarrollo integrado, muy probablemente, al haber movido la función a otro archivo con respecto al archivo original, la función principal ya no es capaz de ver dónde está la declaración de la función de saludo.

Esto quiere decir que, si ahora ejecutamos el programa principal, dará error, porque se está invocando a la función, pero no se sabe dónde donde se está declarando la función.

Para conseguir este objetivo, lo que tenemos que hacer es usar las cabeceras para realizar una importación.

Mediante la siguiente importación:

main.c
#include <stdio.h>#include «lib/calculadoraSuma.c»int main(int argc, char *argv[]) {    printf(«El resultado es: %i \n»,calculadoraSuma(5,4)); return 0;}

Estamos indicándole al programa principal que tiene que tomar el código de la carpeta de librerías, y por tanto, tiene que ser consciente de la declaración de la función.

De esta full de esta forma, ahora, si ejecutamos el código, podremos comprobar cómo vuelve a funcionar correctamente, ya que, aunque la función no está físicamente declarada dentro del archivo principal, sí que estás siendo incluida a través de la cabecera, con lo cual, a efectos prácticos de la compilación, es como si estuviera dentro del archivo original del proyecto.

Como nos podemos imaginar, este proceso es repetible tantas veces como sea necesario, para mantener el código lo más modular posible, y por tanto facilitar su comprensión y su mantenimiento y dad

Ejercicio del curso:

Aplicamos este valioso conocimiento para mejorar la mantenibilidad del código que hasta el momento hemos desarrollado

 nuestro proyecto de agenda, en la iteracion anterior, se ha convertido en un programa ciertamente largo. esto suele suceder con mucha frecuencia a medida que vamos desarrollando, diría yo, cualquier tipo de programa punto llega un momento, especialmente cuando estamos usando programación estructurada, en el que el código fuente de nuestra aplicación tiene un número par de líneas que le empieza a resultar incómodo ir de una sección a otra del código, para implementar cambios, mejoras, o nuevas funcionalidades

 cuando este momento llega, es cuando debemos plantearnos implementar alguna metodología para conseguir que el proyecto sea más fácilmente manipulable

 así que en este caso, lo que hacemos es externalizar cada una de las funciones en un archivo diferente, que más adelante será incluido dentro del programa principal

 de esta forma, en primer lugar, creamos una carpeta en la que introducimos nuevos archivos con la extensión c. aunque no es obligatorio, evidentemente, por claridad, cada archivo recibe el nombre de la función que contiene. y cada archivo contiene únicamente, para este ejemplo, una función, aunque debemos tener en cuenta que esto, para este ejercicio, es más una recomendación que una obligación

Por supuesto, a medida que vamos poniendo el código fuente de las funciones en cada uno de los archivos externos, también lo quitamos del programa principal, para que no esté por duplicado

 por último, en la parte inicial del programa principal, dentro del preprocesador, incluimos todos los archivos de las funciones, para que más adelante puedan ser utilizadas 

agenda.c
/* Programa agendapor Jose Vicente Carratala */#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»#include <stdio.h>#include <string.h>#include «libAgenda/datos.c»#include «libAgenda/listadoRegistros.c»#include «libAgenda/introducirRegistro.c»#include «libAgenda/eliminarRegistro.c»#include «libAgenda/buscarRegistro.c»#include «libAgenda/actualizarRegistro.c»#include «libAgenda/menuPrincipal.c»
int main(int argc, char *argv[]) {
    // Primer registro        strcpy(agenda[1].nombre,»Jose Vicente»);    strcpy(agenda[1].telefono,»12345678″);    strcpy(agenda[1].email,»info@josevicentecarratala.com»);        // Segundo registro    strcpy(agenda[2].nombre,»Juan»);    strcpy(agenda[2].telefono,»53254″);    strcpy(agenda[2].email,»juan@josevicentecarratala.com»);    // Tercer registro    strcpy(agenda[3].nombre,»Jaime»);    strcpy(agenda[3].telefono,»64566″);    strcpy(agenda[3].email,»jaime@josevicentecarratala.com»);    menuPrincipal(); return 0;}

libAgenda/introducirRegistro.c
void introducirRegistro(){    printf(«Vamos a introducir un registro»);}

libAgenda/actualizarRegistro.c
void actualizarRegistro(){    printf(«Vamos a actualizar un registro»);}
libAgenda/datos.c
struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };        struct RegistroAgenda agenda[100];

libAgenda/listadoRegistros.c
void listadoRegistros(){    for(int i = 1; i<=3;i++){        printf(«Registro: %s %s %s \n»,agenda[i].nombre,agenda[i].telefono,agenda[i].email);    }}

libAgenda/eliminarRegistro.c
void eliminarRegistro(){    printf(«Vamos a eliminar un registro»);}

libAgenda/buscarRegistro.c
void buscarRegistro(){    printf(«Vamos a buscar un registro»);}
libAgenda/menuPrincipal.c
void menuPrincipal(){     // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«Tu opcion: «); char opcion = getchar(); printf(«La opción que has seleccionado es: %c \n»,opcion); switch(opcion){     case ‘1’:         listadoRegistros();         break;        case ‘2’:         introducirRegistro();         break;        case ‘3’:         eliminarRegistro();         break;        case ‘4’:         buscarRegistro();         break;     case ‘5’:         actualizarRegistro();         break;        default:            printf(«La opción que has introducido no es válida»);            break; }}

Publicado el Deja un comentario

Programando en C: Estructuras

Capítulo 11: Estructuras

Que son las estructuras?

Las estructuras en C, que no tienen nada que ver con las estructuras de datos tal y como las hemos presentado en los capítulos anteriores, constituyen un nivel superior de ordenación de los datos, que estaría por encima de las matrices, y por debajo de Los objetos, tal y como se entienden en el paradigma de programación orientada a objetos.

El lenguaje C, de base, no tiene soporte para el paradigma de programación orientada a objetos, al menos de forma nativa, aunque se puede conseguir mediante el uso de librerías, o, más frecuentemente, mediante el uso del lenguaje C++, que frecuentemente recibe el nombre de » C con clases «

así pues, si bien el lenguaje se no tiene soporte para programación orientada a objetos de forma nativa, en esta publicación vamos a presentar una serie de conceptos acerca de este paradigma de programación, ya que nos ayudan a entender la utilidad de las estructuras

¿Qué es la programación orientada a objetos?

Si nos fijamos en lo que hemos aprendido hasta el momento, podremos observar como, en un momento dado, empezamos trabajando con variables, pero más adelante, extendimos el concepto de variables mediante el uso de estructuras de datos más avanzadas, como por ejemplo, las matrices.

de esta forma, las variables nos ayudan a solucionar una serie de problemas concretos, ya que nos permiten almacenar datos de uno a uno en cada una de estas variables.

Sin embargo, en multitud de ocasiones, necesitamos guardar varios datos, varias piezas de información, dentro de la misma estructura.

así pues, las estructuras de datos avanzadas, no son más que una solución a ese problema que frequentemente se nos puede presentar.

de la misma forma, en cuanto a la funcionalidad, empezamos la publicación presentando cómo ejecutar instrucciones, pero en un momento dado, observamos como la programación en base a funciones suponía un avance en cuanto a nuestra metodología con como programadores, y por tanto, el uso de funciones, y el encapsulado que ello representa, nos permite realizar desarrollos más complejos, pero a la vez de una forma más mantenerle.

hasta el momento, digamos que por una parte hemos ido evolucionando en cuanto al almacenaje de información, y por otra parte, hemos ido al más avanzando en la ejecución de instrucciones.

la programación orientada a objetos, o lo que es lo mismo, la programación mediante clases, supone un avance un paso más allá todavía en el mismo camino y en la misma dirección en la que nosotros ya hemos empezado a avanzar.

Supone la aparición de una estructura superior llamada clase,que alguna, en una misma burbuja, en una misma cápsula, variables, que pasan a llamarse propiedades, y funciones, que pasan a llamarse métodos.

Así que, desde el plano más básico, las clases no añaden nuevas estructuras de datos ni nuevas funciones que no conozcamos, simplemente, las agregan Y las engloban dentro de una misma burbuja, por supuesto únicamente cuando esto tiene algún tipo de sentido, es decir, cuando ese conjunto de propiedades y ese conjunto de métodos tiene, con textualmente, una función y un sentido en común.

Como he comentado anteriormente, Fede no tiene soporte nativo para trabajar con clases, pero tiene un elemento parecido llamado estructura.

La estructura tiene un comportamiento muy parecido con respecto a las clases, ya que nos permite introducir una serie de variables, que pasan a llamarse propiedades, y que se aglutinan teniendo un sentido

Que son las estructuras?

Las estructuras, por tanto, no son más que grupos de datos, que comparten un significado entre sí, y que además, tienen una enumeración finita.

El clásico ejemplo de estructuras en C, lo encontramos en la declaración de un punto en el espacio tridimensional.

En el momento en el que pensamos en declarar un punto en el espacio tridimensional, sabemos que ese punto, si nos ceñimos a las tres dimensiones del espacio, tiene invariablemente tres propiedades: Su valor en LG X, su valor en el FY, su valor en el FZ.

De esta forma, cuando declaramos una estructura, realmente lo que estamos declarando es 1 U de datos llamada., Y dentro de ella, declaramos tres propiedades, que son X, Y, Z

Declaración de estructuras

En el siguiente ejemplo vamos a materializar el caso que previsualización amos en el párrafo anterior.

Si trabajamos con el ejemplo de un punto en el espacio tridimensional, veremos como una estructura se declararía de la siguiente forma:

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    struct Punto{        int x;        int y;        int z;    };}

Por una parte, como hemos podido observar, declaramos el nombre de la estructura, para, a continuación, dentro de las llaves, introducir cada uno de los parámetros, es decir, cada una de las propiedades que va a tener esa estructura, cada una de ellas, con su propio tipo de datos.

de esta forma, declaramos, de forma abstracta, y todavía no usándola, la plantilla de lo que será esa estructura de datos, al igual que declaramos de forma abstracta una función antes de usarla.

adicionalmente, podemos inicializar el valor de la estructura, con un concepto que está a caballo entre la inicialización de una variable, y un método constructor en el caso de la programación orientada a objetos.

La sintaxis quedaría de la siguiente manera:

main.c


lo que haríamos en ese caso es preparar la estructura para que, cada vez que se cree un punto nuevo, se le asignen una serie de valores iniciales a las propiedades, antes de que nosotros podamos escribir los nuestros propios.

Si nosotros escribimos los nuestros propios, por supuesto sobrescribirán a los valores por defecto, pero si no queremos introducir valores por defecto, sabremos que al crear una estructura, por defecto ya tiene un juego de valores pre implementados.

Creación de estructuras

Una vez que ya tenemos una estructura declarada en memoria, es decir, tenemos la plantilla Del comportamiento y los elementos que va a tener esa estructura, es cuando tenemos que crear nuevos objetos a partir de ella.

Una vez más, es en este punto donde la creación de estructuras a partir de la plantilla, tiene evidentemente similitudes con la programación y la creación de objetos a partir de clases.

así que podremos crear nuevas estructuras simplemente invocando al código de la siguiente forma.

main.c

#include <stdio.h>
int main(int argc, char *argv[]) {    struct Punto{        int x;        int y;        int z;    };    struct Punto punto1;    punto1.x = 100;    punto1.y = 200;    punto1.z = 300;    printf(«La propiedad x es: %d \n»,punto1.x);}

la creación de propiedades de tipo cadena tiene una particularidad con respecto a la escritura de las propiedades de tipo numérico.

Para el trabajo con propiedad de ese tipo numérico, simplemente tenemos que aplicar un operador de igualdad para asignar valor a la propiedad de la estructura.

Sin embargo, si lo que queremos es asignar propiedades en formato de cadena alfa número Alfa numérica, tendremos que usar la siguiente función para conseguir el pase correcto de los parámetros:

main.c

#include <stdio.h>
int main(int argc, char *argv[]) {    struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };    }

Como podremos comprobar, simplemente utilizando una de las funciones de la librería de tratamiento de cadenas, podremos no aplicar una igualdad, pero si realizar una copia de la cadena dentro de el valor de la propiedad.

Si seguimos el siguiente ejemplo conjunto:

main.c
#include <stdio.h>#include <string.h>int main(int argc, char *argv[]) {    struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };    // Primer registro    struct RegistroAgenda registro1;    strcpy(registro1.nombre,»Jose Vicente»);    strcpy(registro1.telefono,»12345678″);    strcpy(registro1.email,»info@josevicentecarratala.com»);    // Segundo registro    struct RegistroAgenda registro2;    strcpy(registro2.nombre,»Juan»);    strcpy(registro2.telefono,»87654321″);    strcpy(registro2.email,»juan@josevicentecarratala.com»);    // Devolvemos:    printf(«El nombre del primer registro es: %s \n»,registro1.nombre);    printf(«El telefono del segundo registro es: %s \n»,registro2.telefono);}

Podremos comprobar cómo, a partir de una estructura, asignaremos tanto valores numéricos como valores alfa numéricos sin ningún problema dentro del mismo proyecto.

Estructuras dentro de matrices

agenda.c
#include <stdio.h>#include <string.h>int main(int argc, char *argv[]) {    struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };        // Primer registro    struct RegistroAgenda registros[1];    strcpy(registros[1].nombre,»Jose Vicente»);    strcpy(registros[1].telefono,»12345678″);    strcpy(registros[1].email,»info@josevicentecarratala.com»);            printf(«El registro es: %s»,registros[1].nombre);}

Ejercicio del curso

A continuación, aplicamos el contenido didáctico de esta unidad, al ejercicio práctico que estamos desarrollando en el curso

 queda patente como el uso de estructuras tiene claras ventajas con respecto, por ejemplo, si nos fijamos en la unidad anterior, al uso de matrices de múltiples dimensiones

 por ejemplo, en el caso de las matrices de múltiples dimensiones, es perfectamente entendible que cada uno de los registros tenga una entidad numérica, el registro número 1, el registro número 2, el registro número 3 de la agenda telefónica

 pero si nos fijamos en el ejercicio anterior, en la segunda dimensión, teníamos un carácter uno para el nombre, dos para el teléfono, y tres para el correo electrónico punto esto es perfectamente usable y funcional, pero sin embargo, finalmente somos nosotros quién le damos sentido a la segunda dimensión

 con las estructuras, en cambio, para con el ejemplo del curso, tenemos exactamente el mismo almacenaje de datos, pero lo hacemos de un modo mucho más entendible, tanto desde el almacenaje de los datos, como también desde la recuperación de los mismos, ya que no estamos llamando a un índice anónimo de una matriz, sino que estamos llamando a una propiedad de una forma mucho más clara y transparente

 dicho esto, la consecuencia no es necesariamente que las estructuras siempre sean mejores con respecto al uso de matrices multidimensionales, simplemente es una herramienta más que el lenguaje de programación pone a nuestra disposición 

agenda.c
/* Programa agendapor Jose Vicente Carratala */#include <stdio.h>#include <string.h>#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»
int main(int argc, char *argv[]) {        struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };    // Primer registro    struct RegistroAgenda agenda[100];    strcpy(agenda[1].nombre,»Jose Vicente»);    strcpy(agenda[1].telefono,»12345678″);    strcpy(agenda[1].email,»info@josevicentecarratala.com»);        // Segundo registro    strcpy(agenda[2].nombre,»Juan»);    strcpy(agenda[2].telefono,»53254″);    strcpy(agenda[2].email,»juan@josevicentecarratala.com»);    // Tercer registro    strcpy(agenda[3].nombre,»Jaime»);    strcpy(agenda[3].telefono,»64566″);    strcpy(agenda[3].email,»jaime@josevicentecarratala.com»);        // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«Tu opcion: «); char opcion = getchar(); printf(«La opción que has seleccionado es: %c \n»,opcion); switch(opcion){     case ‘1’:         printf(«Vamos a listar los registros \n»);         printf(«Registro: %s %s %s \n»,agenda[1].nombre,agenda[1].telefono,agenda[1].email);         printf(«Registro: %s %s %s \n»,agenda[2].nombre,agenda[2].telefono,agenda[2].email);         printf(«Registro: %s %s %s \n»,agenda[3].nombre,agenda[3].telefono,agenda[3].email);         break;        case ‘2’:         printf(«Vamos a introducir un registro»);         break;        case ‘3’:         printf(«Vamos a eliminar un registro»);         break;        case ‘4’:         printf(«Vamos a buscar un registro»);         break;     case ‘5’:         printf(«Vamos a actualizar un registro»);         break;        default:            printf(«La opción que has introducido no es válida»);            break; } return 0;}

Estructuras de bucle

Las estructuras de control del bucle nos permiten repetir la ejecución de una serie de instrucciones.

En ocasiones, es necesario una cierta parte del programa número determinado, o incluso indeterminado de veces.

De esta forma, cuando en un programa repetimos varias veces una pieza del código, debemos saber que existen varios tipos de estructuras que nos permiten automatizar este proceso.

Un ejemplo bastante típico y característico serían los días de un calendario mensual.

Supongamos que queremos representar los 30 días estándar de un mes, por lo que el código necesario tendría un aspecto aproximadamente como el siguiente.

Cuando en un programa vemos que se repite una porción del código, nuestra mente del programador debe advertirnos de que debería haber una forma a más sencilla de representar esa parte del código.

A continuación, vamos a ver de qué herramientas de control de bucle disponemos.

La estructura de control for.

La estructura de control sur, tiene la sintaxis que vemos en el ejemplo anterior, de la cual podemos destacar, que primero introducimos la palabra reservada favor, a continuación, dentro de los paréntesis, introducimos las tres condiciones, de inicio, de finalización, y de incremento, y por último, dentro de las llaves, introducimos el código que se va a repetir.

De esta forma, el ejemplo del calendario quedaría representado de la siguiente manera.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int diasDelMes = 30;    for(int i = 1;i<diasDelMes;i++){        printf(«Hoy es un día \n»);    }}

Como podemos comprobar, constituye una forma muy conveniente de repetir la ejecución.

Además, nos podremos fijar de que a lo largo de la utilización del buque favor, se define una variable, que recibe el nombre de variable y te Ladora.

Es por esta razón que la letra elegida para ocupar esta función suele ser la letra vocal y, aunque, como podemos comprobar, que esta función puede ser desarrollada por cualquier variable.

en el ejemplo amor mostrado, podremos comprobar como la variable empieza en el día número uno del mes, llega hasta el día 30 del mes, y cada vez que ejecutamos el bucle, es decir, cada vez que se repite el bucle, encontramos un nuevo día más añadido al bucle de información.

Además, la variable utilizada como integradora, se puede usar dentro de las llaves, dentro de el código que se utiliza en el programa.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int diasDelMes = 30;    for(int i = 1;i<=diasDelMes;i++){        printf(«Hoy es el dia %i del mes \n»,i);    }}

Podemos variar el código tanto como necesitemos, para realizar, por ejemplo, las siguientes variaciones.

El siguiente ejemplo, muestra los días únicamente impares del mes.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int diasDelMes = 30;    for(int i = 1;i<=diasDelMes;i+=2){        printf(«Hoy es el dia %i del mes \n»,i);    }}

El siguiente ejemplo, muestra los días únicamente Padres del mes.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int diasDelMes = 30;    for(int i = 2;i<=diasDelMes;i+=2){        printf(«Hoy es el dia %i del mes \n»,i);    }}

El siguiente ejemplo muestra los días pares empezando en el 10, y acabando en el 20.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int diasDelMes = 30;    for(int i = 10;i<=20;i+=2){        printf(«Hoy es el dia %i del mes \n»,i);    }}

Además, el Peter Ador no tiene porque ir desde un número inferior hasta un número superior.

En el siguiente ejemplo se muestra la enumeración de días del mes, desde el día 30, hasta el día uno.

la estructura de control Wilde

Si bien la estructura de control llamada favor resulta muy conveniente porque contiene, dentro de los paréntesis, tanto la condición de inicio, como la condición de finalización, como la condición de incremento o decremento, la estructura de control de Google de tipo while, tiene un formato parecido, en cuanto a que se invoca a la estructura, se pone entre paréntesis las condiciones, y se ejecuta el código a repetir entre las llaves, pero tiene la característica de que, dentro de los paréntesis, únicamente es posible poner la condición de finalización.

De esta forma, si por ejemplo escribimos el siguiente código, encontraremos que estaremos ejecutando un bucle infinito.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int dia = 1;    while(dia < 30){        printf(«Hoy es el dia %i del mes \n»,dia);    }}

Es decir, podremos comprobar que no existe una condición de finalización, y por tanto, el programa entrará en una situación de ejecución constante sin fin.

Esto no es en se negativo, sino que existen diversos casos en los que puede interesarnos ejecutar un programa sin una finalización concreta . nueve

De todas formas, en el caso más típico y característico, es decir, en el caso de un bucle del cual esperamos poder controlar tanto el inicio, como al final, como en el incremento, formularemos el bucle while como podemos ver en el ejemplo a continuación.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int dia = 1;    while(dia < 30){        printf(«Hoy es el dia %i del mes \n»,dia);        dia++;    }}

Cómo podremos ver, finalmente, al igual que en el bucle favor, existen la condición de inicio, deparada, y de incremento, con la diferencia de que en este ejemplo que se presenta, la condición de inicio está fuera del bucle, la condición de finalización está dentro de los paréntesis, y la condición de incremento se encuentra dentro del código del propio Google.

El bucle Do While

El bucle Duguay constituye una variación con respecto al bucle repetitivo guay que hemos visto con anterioridad.

El bucle Güell contiene una condición de finalización, en definitiva, una condición de ejecución, que hará que el bucle se ejecute mientras que esa condición sea cierta.

Si la condición no es cierta, el bucle no se ejecutará.

Si vemos por ejemplo el siguiente caso, podremos comprobar que, si la condición no es cierta, el bucle, de hecho, no se llega a ejecutar ni una sola vez.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int dia = 1;    while(dia < 30){        printf(«Hoy es el dia %i del mes \n»,dia);        dia++;    }}

Precisamente para estos casos existe el bucle de Uruguay.

Existen casos y situaciones, aunque honestamente no se dan todos los días, en los que es necesario que el contenido del bucle se ejecute al menos una vez, aunque su condición de validación no sea cierta.

Es por eso que este bucle, en ocasiones, recibe el nombre de » bucle de primero dispara y luego pregunta «.

En el ejemplo que presento a continuación, puede fácilmente visualizarse como, aunque el código no se debería ejecutar, ya que la condición de ejecución no es cierta, pero sin embargo, sí que se llega a ejecutar una vez.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int dia = 34;    do{        printf(«Hoy es el dia %i \n»,dia);    }while(dia <= 30);}

Como podemos comprobar, primero se ejecuta el código, y luego se valida la veracidad de la expresión evaluada.

El problema estriba en que si la condición es falsa, para cuando es evaluada, el código ya se ha ejecutado una vez.

Por supuesto, al validar, falsa, el código no se volverá a ejecutar, a menos que en un momento la condición sea cierta de nuevo.

Por último, es importante notar que el bucle Dubái es el único que es obligatorio finalizar con un punto y,, Arrizar a diferencia del resto de estructuras de control.

la estructura de control for each

cuando hemos guardado la información en una matriz, es muy común, en un momento dado, más adelante con respecto al momento del guardado, necesita recuperar la información contenida en esa matriz.

main.c

De esta forma, es perfectamente posible recordar el contenido de la matriz usando una estructura de control de tipo foro.

Esto puede hacerse, introduciendo manualmente la longitud de la matriz, o bien, usando la propiedad de longitud de la matriz.

Sin embargo, es mucho más conveniente usar una estructura de control de Google que sirve específicamente para poner recorrer matrices.

Esta estructura de control tiene la forma que se describe en ejemplo a continuación.

Antes de empezar a desarrollar el contenido

La estructura de control goto:

Ejercicio del curso:

En la versión anterior del ejercicio en la opción de listado de registros, teníamos una forma completamente ineficiente de obtener de vuelta los registros de la estructura que guarda la agenda

 si nos fijamos, en el desarrollo anterior del ejercicio, cada vez que realizábamos un listado, lo que conseguíamos era listar uno a uno, de forma repetitiva, los elementos de la agenda. esto, evidentemente, es terriblemente ineficiente. en el desarrollo de programas informáticos, siempre que vemos que una estructura se repite varias veces, nos vemos repetirla a mano, sino que deberíamos encontrar una forma automatizada de realizar esa repetición

 esto es exactamente lo que nos proporcionan las estructuras de control de bucle, la posibilidad de que el programa repita automáticamente por nosotros una tarea que, hasta el momento, habíamos tenido que repetir de manera completamente manual

 así que en esta aplicación de la unidad didáctica al ejercicios del curso, como podemos comprobar, se ha utilizado una estructura de control for para automatizar la devolución de registros en el listado en pantalla

 de esta forma, ahora no importaría en la teoría que el listado de registros tuviera uno, dos, tres, o 3000 componentes, porque simplemente tendríamos que indicar una nueva finalización a la estructura de control for 

agenda.c
/* Programa agendapor Jose Vicente Carratala */#include <stdio.h>#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»
int main(int argc, char *argv[]) { struct RegistroAgenda{        char nombre[50];        char telefono[50];        char email[50];    };    // Primer registro    struct RegistroAgenda agenda[100];    strcpy(agenda[1].nombre,»Jose Vicente»);    strcpy(agenda[1].telefono,»12345678″);    strcpy(agenda[1].email,»info@josevicentecarratala.com»);        // Segundo registro    strcpy(agenda[2].nombre,»Juan»);    strcpy(agenda[2].telefono,»53254″);    strcpy(agenda[2].email,»juan@josevicentecarratala.com»);    // Tercer registro    strcpy(agenda[3].nombre,»Jaime»);    strcpy(agenda[3].telefono,»64566″);    strcpy(agenda[3].email,»jaime@josevicentecarratala.com»);     // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«Tu opcion: «); char opcion = getchar(); printf(«La opción que has seleccionado es: %c \n»,opcion); switch(opcion){     case ‘1’:         for(int i = 1; i<=3;i++){             printf(«Registro: %s %s %s \n»,agenda[i].nombre,agenda[i].telefono,agenda[i].email);         }         break;        case ‘2’:         printf(«Vamos a introducir un registro»);         break;        case ‘3’:         printf(«Vamos a eliminar un registro»);         break;        case ‘4’:         printf(«Vamos a buscar un registro»);         break;     case ‘5’:         printf(«Vamos a actualizar un registro»);         break;        default:            printf(«La opción que has introducido no es válida»);            break; } return 0;}

Publicado el Deja un comentario

Programando en C: Estructuras de datos

Capítulo 10: Estructuras de datos

¿Qué son las estructuras de datos?

Hasta este momento, hemos visto que es completamente frecuente y normal guardar la información que usa un programa en variables, y realizar operaciones con estas.

Las variables, por tanto, constituyen una forma inicial de guardar información, y de poder empezar a mover esta información a lo largo de un programa.

Sin embargo, hay ocasiones en las que la sencillez de las variables las hacen demasiado pequeñas como recurso, para solucionar ciertos tipos de problema.

Yo suelo decir que una variable es algo así como una caja de zapatos.

Es un contenedor, que puede contener una pieza de información, pero que no puede contener demasiadas piezas de manera simultánea.

de esta forma, hay veces que, cuando necesitamos guardar múltiples piezas de información, realmente no necesitamos una caja, ni un cajón, sino un armario.

Un armario, en definitiva, es una estructura donde podemos guardar múltiples piezas de información de manera simultánea.

Así que, por tanto, las estructuras de datos son formas más complejas y más estructuradas de guardar múltiples piezas de información.

Las estructuras de datos nos ofrecen métodos más complejos y más completos de almacenar múltiples piezas de información, que finalmente necesarias por parte de los programas que desarrollamos.

Las estructuras que vamos a ver en este capítulo

Matrices

Las matrices son una de las formas más básicas de implementar las estructuras de datos, y se encuentran disponibles en la gran mayoría de lenguajes de programación

Permiten almacenar multitud de datos, en la gran mayoría de lenguajes de programación, permiten almacenar varias dimensiones

A continuación, se muestra un ejemplo en el que, en primer lugar, se declara una matriz, a continuación, valores y por último, se recuperan estos valores previamente introducidos.

agenda.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int telefono[10];    telefono[1] = 12345;    telefono[2] = 23456;    telefono[3] = 34567;        printf(«El segundo telefono es: %i \n»,telefono[2]); return 0;}

Como podemos observar, también conocidas como colecciones, pueden albergar diferentes piezas de información bajo un mismo nombre.

De esta forma, realmente realizan una función que podríamos con varias variables, tener que usar los diferentes

Aplicación sobre el ejercicio de la publicacion

Matrices multidimensionales

Hasta el momento, mediante el uso de las matrices de una sola dimensión, hemos podido comprobar que podemos introducir múltiples piezas de información de forma simultánea, y las podemos recuperar más adelante, lo cual evidentemente ya constituye una ventaja con respecto al uso de las variables

 sin embargo, con respecto al ejercicio de la publicación, o en definitiva, con respecto al desarrollo de cualquier ejemplo parecido al de una agenda, veremos que, realmente, en cada registro, es poco práctico únicamente poder introducir un dato, que en este caso ha sido el número de teléfono

 para poder introducir un registro de forma correcta, lo habitual es poder introducir una serie de piezas de información para cada uno de los registros. típicamente, por ejemplo, en el caso de una agenda, como mínimo, queremos saber a qué nombre de usuario pertenece ese teléfono, y ya que estamos, podríamos introducir también una dirección de correo electrónico asociado a ese usuario y a ese teléfono. estas piezas de información serán suficientes para ilustrar el concepto que se muestra a continuación, ya que evidentemente, donde introducimos 3 piezas de código podríamos introducir 300 o 3000 

Mediante el uso de dos o más dimensiones somos capaces de albergar todavía más piezas de información dentro de cada uno de los registros que guardamos en la estructura de datos

 en el siguiente ejemplo se muestra un guardado en una matriz de 2 dimensiones punto en primer lugar, podemos comprobar como como, utilizando dos parejas de corchetes, especificamos el número de dimensiones de la matriz, e indicamos el número de elementos que va a contener 

A continuación, empezamos a introducir cada uno de los registros, donde, como podremos comprobar, tenemos espacio tanto para albergar el nombre, el teléfono, como el correo electrónico, virtualmente entre otros tantos datos que podríamos introducir

 de esta forma, las matrices bidimensionales se asemejan a hojas de cálculo, en las que encontramos filas y columnas. digamos que las filas, serían cada uno de los registros principales, correspondientes a la primera dimensión, y las columnas, serían cada uno de los registros secundarios, correspondientes en este ejemplo a la segunda dimensión

 por supuesto es posible introducir más dimensiones. cuando se trabaja con tres dimensiones ya no se puede poner el ejemplo de la hoja de cálculo, pero sin ejemplo pero sin embargo se puede introducir el ejemplo del palet lleno de cajas

 con matrices de 4 dimensiones, que son perfectamente posibles, el ejemplo, evidentemente, es más difícil de visualizar, pero no por ello menos posible o menos funcional 

agenda.c
#include <stdio.h>
int main(int argc, char *argv[]) {    char* agenda[10][4];    agenda[1][1] = «Jose Vicente»;    agenda[1][2] = «123456789»;    agenda[1][3] = «info@josevicentecarratala.com»;        agenda[2][1] = «Juan»;    agenda[2][2] = «987654321»;    agenda[2][3] = «juan@josevicentecarratala.com»;        printf(«El segundo telefono es: %s \n»,agenda[2][1]); return 0;}

Publicado el Deja un comentario

Programando en C: Estructuras de control

Capítulo 9: Estructuras de control

¿Qué son las estructuras de control?

Las estructuras que vamos a ver en este capítulo nos permiten controlar el flujo de la información a lo largo de un programa.

Un programa, tal y como lo hemos visto hasta ahora, es una sucesión de instrucciones que acaban llevando a un resultado fijo y concreto.

Sin embargo, hay ocasiones en las que un programa no tiene un único resultado, sino que puede tener diferentes resultados, puede tener diferentes secciones, y la ejecución de unas secciones uno tras dependerá de las decisiones que nosotros tomemos durante la ejecución de dicho programa.

El objetivo de este apartado, es precisamente presentar y mostrar estas estructuras de control, que forman parte Del núcleo de cualquier lenguaje de programación, y además, encontraremos las mismas estructuras, o prácticamente iguales, a lo largo de diferentes lenguajes, durante nuestro proceso de aprendizaje.

Estructuras condicionales

El flujo de ejecución de un programa puede ser modificado mediante la aparición de estructuras condicionales, es decir, mediante la ejecución condicional de un código o otro, después de la validación de una condición previa.

fundamentalmente existen dos tipos de estructura condicional, que son las que vamos a presentar a continuación.

La primera es la estructura condicional es, que se encarga de ejecutar un código y otro mediante la validación verdadero falso de una expresión, y la segunda es la estructura condicional switch, que admite varios casos de manera simultánea como verdadero

La estructura condicional

anteriormente hemos hablado de que el lenguaje nativo en el que habla una computadora es el binario, compuesto de unos y ceros, que, finalmente, representan el estado encendido y apagado de cada uno de los componentes más básicos del lenguaje de programación.

Así que, finalmente, la validación mediante estados de verdadero y falso es una validación bastante cercana para lo que es la naturaleza del lenguaje con el que trabaja la máquina, a diferencia del lenguaje con el que trabaja el ser humano, que entre blanco y negro distingue una variedad bastante grande de grises, por regla general.

la estructura de control, por tanto, contiene en primer lugar una expresión que, finalmente, puede ser validada como verdadera o cierta.

A continuación, tiene un bloque de código, que solo se ejecutará en el caso de que la expresión validada sea cierta.

Adicional y opcionalmente, la expresión puede tener un caso Els, es decir, un caso que solo se ejecutará en el caso de que la expresión haya sido validada como falsa.

Es por esto que, por ejemplo, podríamos expresar una estructura de control es de la siguiente manera:

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int edad = 40;    if(edad < 30){        printf(«Eres un joven»);    }else{        printf(«Ya no eres tan joven»);    } return 0;}

Alización de las estructuras de control condicionales

Las estructuras de control pueden ser perfectamente anidadas, para ofrecer validaciones más complejas que el ejemplo que hemos visto con anterioridad.

De esta forma, con respecto al ejemplo anterior, dentro de cada uno de los casos, podemos introducir a su vez otra estructura completa de validación condicional.

Si aplicamos esta validación sobre el ejercicio que mostrado anteriormente, podemos encontrar que, ahora, la salida del programa, ya no se limita a dos estados, sino que puede resultar en cuatro.

Evidentemente, puedo repetir este proceso iterativa mente tantas veces como necesites, para conseguir que la estructura general tantos estados como yo necesite

main2.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int edad = 40;    if(edad < 30){        if(edad < 20){            printf(«Eres muy joven»);        }else{            printf(«Eres un joven»);        }            }else{        if(edad < 40){           printf(«Ya no eres tan joven»);         }else{            printf(«Definitivamente ya no eres joven»);        }            } return 0;}

Aplicación de operadores en la validación de la expresión

Por supuesto, teniendo en cuenta que, finalmente, se valida una expresión como verdadera o falsa, podemos aplicar todo aquello que hemos aprendido anteriormente en cuanto al uso de operadores.

Es por esto que es frecuente observar el uso de operadores lógicos dentro de la expresión validada en una estructura de control condicional, por ejemplo, de la siguiente manera

main.c


La estructura de control condicional switch

Hasta el momento, con la estructura de Control condicional ismos o Els es, finalmente lo que hacemos es validar una expresión en cuanto a su veracidad o su falsedad.

Sin embargo, existen infinidad de casos donde no hay una validación verdadera y una falsa, sino que puede haber muchas variaciones verdaderas infinitas validaciones falsas.

Un ejemplo claro y clásico de esto, son los días de la semana.

Si yo pregunto, qué día de la semana es hoy? La respuesta a esa pregunta no es verdadero o falso.

La respuestas correctas son lunes, martes, miércoles, jueves, viernes, sábado, y domingo, y hay infinidad de otras respuestas incorrectas, pero en definitiva sabemos que hay al menos siete respuestas verdaderas.

La estructura de control switch trata específicamente este tipo de preguntas, en definitiva, preguntas para las que no hay un solo caso verdadero.

Así que, el ejemplo planteado en el párrafo anterior, el ejemplo de los días de la semana, quedaría reflejado en el siguiente código

main.c

#include <stdio.h>
int main(int argc, char *argv[]) {    int dia = 1;        switch(dia){        case 1:            printf(«Hoy es lunes»);            break;        case 2:            printf(«Hoy es martes»);            break;        case 3:            printf(«Hoy es miercoles»);            break;        case 4:            printf(«Hoy es jueves»);            break;        case 5:            printf(«Hoy es viernes»);            break;        case 6:            printf(«Hoy es sabado»);            break;        case 7:            printf(«Hoy es domingo»);            break;    } return 0;}

Como podemos ver, a la estructura de control tiene una serie de componentes similares a cualquier otra estructura, tiene el nombre de la propia estructura, entre paréntesis la expresión que se está validando, y dentro de las llaves, se escriben cada uno de los casos que trata la expresión como posibles casos válidos.

debemos fijarnos en que lo que hay después de la palabra clave caso son: y no un punto y,.

Por otra parte, también deberemos tener en cuenta que cada uno de los casos deberá acabar con una instrucción break.

Una vez que se ha ejecutado uno de los casos verdaderos, la instrucción break impide que se ejecuten el resto de casos en cascada.

El caso default

En el ejemplo anterior, en el caso switch, hemos visto como la estructura de control puede reaccionar a una serie de casos verdaderos, pero, qué es lo que ocurre cuando se introduce un caso falso?

Por defecto, cuando ocurre que el usuario introduce un caso que no es válido, por defecto la estructura de control no realiza una acción.

De esta forma, siguiendo los patrones de la programación defensiva, existe un último caso dentro de la estructura switch llamado de Ford, que se encarga de gestionar precisamente como debe comportarse la estructura de control cuando se le introduce un caso no válido.

De esta forma, la estructura de control quedaría de la siguiente manera:

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int dia = 15;        switch(dia){        case 1:            printf(«Hoy es lunes»);            break;        case 2:            printf(«Hoy es martes»);            break;        case 3:            printf(«Hoy es miercoles»);            break;        case 4:            printf(«Hoy es jueves»);            break;        case 5:            printf(«Hoy es viernes»);            break;        case 6:            printf(«Hoy es sabado»);            break;        case 7:            printf(«Hoy es domingo»);            break;        default:            printf(«Entrada no reconocida»);            break;    } return 0;}

La estructura de control condicional else if

Prácticamente el mismo resultado que hemos conseguido mediante el uso de la estructura de control switch, podríamos conseguirlo mediante la estructura de control el cif, que en principio es una variación a la estructura de control y que ha sido presentado anteriormente

 el ejercicio, de esta manera, quedaría transformado en el siguiente código 

main.c


Sin embargo, procediendo de esta manera, no estaremos evaluando realmente el potencial que tiene la estructura de control el cif, ya que en cada una de las condiciones evaluadas, podemos introducir un nivel mayor de complejidad que en la estructura de control switch

 de esta forma, el siguiente ejemplo aprovecha bastante mejor el potencial de extra estructura, comparada con la estructura de control switch 

main.c


Sobre el ejercicio del curso:

A continuación aplicamos lo que hemos aprendido en la presente unidad didáctica al desarrollo del ejercicio continuo de la publicación

 sí en unidades anteriores hemos preparado una variable de tipo carácter para almacenar la elección del usuario, a continuación, utilizamos una estructura de control de tipo suite para poder reaccionar de diferente forma dependiendo de la elección que efectivamente haya realizado el usuario humano 

agenda.c
/* Programa agendapor Jose Vicente Carratala */#include <stdio.h>#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»
int main(int argc, char *argv[]) {    // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«Tu opcion: «); char opcion = getchar(); printf(«La opción que has seleccionado es: %c \n»,opcion); switch(opcion){     case ‘1’:         printf(«Vamos a listar los registros»);         break;        case ‘2’:         printf(«Vamos a introducir un registro»);         break;        case ‘3’:         printf(«Vamos a eliminar un registro»);         break;        case ‘4’:         printf(«Vamos a buscar un registro»);         break;     case ‘5’:         printf(«Vamos a actualizar un registro»);         break;        default:            printf(«La opción que has introducido no es válida»);            break; } return 0;}
Publicado el Deja un comentario

Programando en C: Operadores

Capítulo 8: Operadores

Que son los operadores

El objetivo de este apartado es describir el uso y la utilidad de los diferentes tipos de operadores que se encuentran dentro de un lenguaje de programación.

El objetivo de los operadores es poder realizar operaciones usando dos o varios de los datos que, previamente, generalmente hemos almacenado en contenedores de información, tales como por ejemplo variables o matrices.

El resultado de estas operaciones es decisivo para poder especificar, por ejemplo, el flujo de la información de un programa en concreto.

existen diferentes tipos de operadores, en los siguientes sub apartados vamos a tratar aquellos más importantes y cuyo uso es, con diferencia, más frecuente.

Operadores aritméticos

Los operadores aritméticos son aquellos que nos permiten realizar operaciones matemáticas combinando las diferentes piezas de información.

El operador aritmético de suma, nos permite realizar una suma aritmética entre dos o más operandos.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int numero1 = 4;    int numero2 = 3;    int resultado = numero1 + numero2;    printf(«El resultado es: %i \n»,resultado); return 0;}

El operador aritmético de restar, representado por un guión, nos permite realizar una diferencia entre dos o más operandos, aunque generalmente se trabajan con dos piezas de información.

int resultado = numero1 – numero2;

El operador aritmético de multiplicación, representado por un*, nos permite multiplicar dos o más operandos.

int resultado = numero1 * numero2;

El operador aritmético de división, representado por una barra, que usualmente podemos obtener con la combinación de mayúsculas y el número siete del teclado, en el teclado español, nos permite dividir dos operandos.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    float numero1 = 4;    float numero2 = 3;    float resultado = numero1 / numero2;    printf(«El resultado es: %f \n»,resultado); return 0;}

Existe un operador específico para obtener el resto de la división entera, que suele ser el de el símbolo del porcentaje.

Al usar este operador, el resultado que obtendremos en pantalla es el resto de la división entera entre dos operandos.

Si bien este operador no es de uso común a diario, de vez en cuando puede sernos de utilidad, por ejemplo para realizar operaciones relacionadas con el cálculo financiero.

float resultado = numero1 % numero2;

Orden de preferencia en las operaciones aritméticas.

Al igual que ocurre en el mundo matemático, hay que tener en cuenta que, en prácticamente cualquier lenguaje de programación, se siguen las mismas reglas de procedencia que encontramos encontramos en el mundo de las matemáticas.

De esta manera, deberemos tener en cuenta que las operaciones de multiplicación y de división se resolverán siempre antes que las operaciones de suma y de resto.

Por otra parte, y una vez más, igual que en el mundo matemático, podemos alterar el orden de la preferencia mediante el uso de paréntesis.

El uso de paréntesis, por tanto, nos permite invertir el orden para especificar que las sumas se ejecuten antes que las multiplicaciones, por poner un ejemplo.

De la misma forma, las operaciones se pueden admirar de manera múltiple utilizando diferentes conjuntos de paréntesis. Esto, de hecho, es muy normal en programas complejos, y a la vez, suele ser frecuente fuente de errores.

Es por esto que debemos tener a la hora de maletas las diferentes combinaciones de paréntesis.

es muy frecuente, en el mundo de la programación, ver el uso de paréntesis, para indicar, sobre todo entre diferentes programadores, cuál es el orden en el que se deben resolver las operaciones, aún en casos en los que no sería necesario, ya que los paréntesis acaban indicando el mismo orden natural de procedencia.

Incluso en estos casos, ya que muchos programadores, sorprendentemente, desconocen cuáles son estas reglas de procedencia, suele ser útil el uso de paréntesis para asegurar que, sea como sea, se entiende el orden en el cual se van a repetir las operaciones en un punto concreto de la programación.

Operadores de comparación

Existe un conjunto de operadores de comparación, que nos permiten, no voy a sumar, restar, o en definitiva realizar operaciones aritméticas sobre dos o más operadores, sino obtener el resultado verdadero o falso de una comparación entre dos o más operadores.

En esta unidad didáctica vamos a desarrollar una serie de ejemplos teniendo como referencia el uso de dos operadores.

La doble igualdad

Si viene el operador de igualdad se usa para realizar una asignación, es decir, cuando ponemos lo siguiente:

Lo que le estamos queriendo decir a la máquina es que a una variable le asignamos un valor, cuando introducimos expresiones, es muy normal encontrar una doble igualdad.

A los ojos inexpertos puede parecer una asignación, pero sin embargo, Suso no tiene nada que ver con esta.

En el momento en el que vemos una doble igualdad, estamos viendo que el programa comprobar si es cierto que el operando a es igual al operándome.

Debemos recordar, por tanto, que siempre que vemos una doble igualdad, en cierta forma, es como si estuviéramos viendo una pregunta.

Así que, una vez más, sobre el ejemplo anterior, cuando vemos esto:

Lo que realmente tenemos que pensar en nuestra cabeza es que el programa está diciendo: es cierto que el operando va es igual al operándome? La respuesta, evidentemente, será verdadera o falsa

El operador de triple igualdad

De la misma forma que existe la doble igualdad para comparar dos operandos, existe, aunque no es tan frecuente en su uso, el operador de triple igualdad.

El operador de doble igualdad comprueba si el valor de los dos operandos es igual, pero no se preocupa realmente por comprobar el tipo de datos de cada uno de los dos operandos.

Así que, por ejemplo, podríamos tener esta expresión, en la que tenemos dos operandos que tienen el mismo valor, pero sin embargo, el tipo de datos no es exactamente el mismo:

Con la operación de la doble igualdad, el resultado sería verdadero.

Sin embargo, si los evaluamos con la triple igualdad, este ejemplo:

Don falso, ya que no solo se está evaluando el valor de los dos operandos, si no además está preguntando si el tipo de datos también es igual, cosa que en este caso es falsa.

Así que, aunque el valor sea igual, la diferencia de tipos justifica que el resultado sea falso.

El operador not y cual

De la misma forma que podemos evaluar si un operando es igual a otro, podemos evaluar si un operando no es igual a otro.

Es decir, es como una operación de igualdad, pero en negativo.

En C, y en la mayoría de lenguajes de programación, el operador de negación es el!.

Así que, de esta forma, el ejemplo siguiente evaluaría la pre pregunta de si el operando ver no es igual al operando a.

El operador nota igual con triple guardado.

De la misma forma que existe operador de triple igualdad para comprobar el valor y el tipo, también existe la triple igualdad con negación, que consiste en un! Con dos iguales.

El ejemplo sería el siguiente:

Ahora bien, si ya hemos comentado anteriormente que la evaluación de triple igualdad es bastante poco común, es menos común todavía la triple igualdad con negación.

<Y >

Las operaciones de evaluación de si el operando a es menor que el operando B, o el operando a es mayor que el operándome, se escriben de la siguiente forma.

Disponemos de una evaluación de menor, otra aplicación de menor o igual, de la misma forma, que disponemos de una evaluación de mayor, y una evaluación de mayor o igual.

Deberemos tener en cuenta que, en cualquiera de los dos casos, en la gran mayoría de lenguajes de programación, primero se pone los símbolos de menor o mayor, y luego se pone el símbolo de igualdad, y nunca al revés.

Además, no debe existir ningún espacio entre los dos, ya que entonces el programa lo interpreta como dos operadores diferentes, y da error en la gran mayoría de los casos.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    float numero1 = 4;    float numero2 = 3;    int resultado = numero1 == numero2;    printf(«El resultado es: %d \n»,resultado); return 0;}

#include <stdio.h>

int main(int argc, char *argv[]) {

    float numero1 = 4;

    float numero2 = 3;

    int resultado = numero1 == numero2;

    printf(«El resultado es: %d \n»,resultado);

return 0;

}

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    float numero1 = 3;    float numero2 = 3;    int resultado = numero1 == numero2;    printf(«El resultado es: %d \n»,resultado); return 0;}

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    float numero1 = 4;    float numero2 = 3;    int resultado = numero1 < numero2;    printf(«El resultado es: %d \n»,resultado);    resultado = numero1 > numero2;    printf(«El resultado es: %d \n»,resultado); return 0;}

Operadores lógicos

Los operadores lógicos ande y oro se encargan de evaluar multitud de expresiones de una sola vez.

En primer lugar, en el operador lógico anda, se evalúa que dos o más conjuntos de evaluaciones sean verdaderos o falsos, con la característica de que con que uno de los operandos evaluados sea falso, la globalidad de la expresión es falsa.

Un ejemplo sería el siguiente, cuya evaluación de falso.

Otro ejemplo sería el siguiente, cuya evaluación del verdadero.

En los dos ejemplos puestos con anterioridad, se están evaluando tres expresiones de manera simultánea, pero evidentemente es solo un ejemplo, se pueden evaluar tantas expresiones como se quiera, sin límite.

El operador lógico hora.

El operador lógico ahora es algo más permisivo que el operador ando, en términos de que, cuando se evalúan una serie de expresiones, con que una de ellas sea cierta, el resultado global de la comparación es cierto.

Es decir, volviendo a los ejemplos anteriores, pero transformándolos al caso por, tendríamos este primer ejemplo, donde todos los resultados son verdaderos, luego la expresión global es verdadera.

Tenemos este otro ejemplo, donde dos casos son falsos, pero uno es verdadero, así que la expresión global validar como verdadera.

Y luego por supuesto tenemos este otro ejemplo, donde las tres sub expresiones validadas son falsas, luego la expresión global válida como falsa.

main.c

Operadores de incremento y decremento

Durante el desarrollo de programas informáticos en la gran mayoría de lenguajes, es muy común necesitar realizar operaciones de incremento y decremento, donde, respectivamente, se realizan incrementos y restas sobre los valores de las variables que se están tratando

 de esta forma, a continuación se presenta un ejemplo de incremento, que básicamente consiste en llamar a la variable con el doble operador más

 por otra parte, observamos también en el siguiente ejemplo el uso de los operadores de decremento, que nos permiten restar una unidad a la variable en cuestión, en cada una de las ejecuciones del código 

operadores abreviados

Los operadores de incremento y decremento sirven para sumar y restar un valor, respectivamente. nueva línea nueva línea sin embargo, en el momento en el que queremos realizar un incremento de dos valores consecutivamente, nos damos cuenta de que simplemente no existe esta opción es prácticamente ningún lenguaje de programación

 de esta forma, es como nos encontramos con los operadores aritmeticos abreviados

 por poner un ejemplo, si lo que queremos es sumar 2 unidades a una variable previamente existente, podríamos hacerlo de la siguiente forma

 pero sin embargo, esa sintaxis no se recomienda, y se recomienda utilizar el operador abreviado de la siguiente forma

 así que por tanto, si hemos expuesto el operador abreviado de suma, a continuación se muestra el operador abreviado de resta

 este sería el operador a primero de multiplicación

 y por último el operador abreviado the división

 para el usuario novel en un primer momento y pueden resultar difíciles de comprender, pero sin embargo, con un poco de práctica, podremos observar como suponen evidentemente una ventaja desde el punto de vista de la cantidad de código que se escribe para conseguir el mismo objetivo 

Publicado el Deja un comentario

Programando en C: Entrada de información en un programa

Capítulo 7: Entrada de información en un programa

Anteriormente hemos aprendido como extraer información del programa, y mostrarla al ser humano, de momento en la consola, y mediante la instrucción printf.

También hemos aprendido anteriormente que un programa no es más que una serie de operaciones realizadas sobre unos datos de partida, y que ofrecen un resultado en base a cálculos realizados sobre esos datos.

Así que sabemos cómo extraer datos en la pantalla, y pronto aprenderemos cómo realizar cálculos dentro del propio programa. Pero, ¿como podemos permitir al usuario introducir información?

Existen varias formas de permitir que un usuario introduzca información dentro de una aplicación informática.

En el caso del lenguaje que nos ocupa en esta publicación, la instrucción más frecuente para permitir esta entrada, forma parte de la misma librería de entrada y de salida que nos permite escribir texto en la consola.

Usaremos las siguiente instrucción, dentro de este programa de ejemplo, de forma de forma que:

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    printf(«Introduce una tecla»);    char seleccion = getchar();    printf(«El caracter que has cogido es: %c \n»,seleccion); return 0;}

Cuando ejecutamos el programa, comprobamos como la ejecución queda detenida en ese punto concreto del programa, esperando a que el usuario introduzca una letra, una palabra, o una línea dentro de la consola.

Debemos tener en cuenta que, según la tipificación de los datos que hemos introducido, ahora mismo, solo se estaría atrapando la primera letra de toda la cadena que hemos introducido.

 Sin embargo, también podemos modificar el programa para que admita una matriz de cadenas, y de esta forma, que nos permita leer varios caracteres de la línea.

En este código de ejemplo que se muestra a continuación, podemos observar como, al ejecutarlo, no solo se está obteniendo el primer carácter de la cadena introducida, sino que se está obteniendo toda la cadena en sí misma, hasta el límite de caracteres especificado en la matriz.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    printf(«Introduce una tecla \n»);    char palabra[100];    scanf(«%s»,palabra);    printf(«La palabra introducida es: %s \n»,palabra); return 0;}

Por último, en el siguiente programa, realizamos una demostración para comprobar que somos capaces de pedirle al usuario una entrada, almacenarla en una variable, y devolverla en la consola.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    printf(«Introduce una tecla \n»);    char palabra[100];    scanf(«%s»,palabra);    printf(«La palabra introducida es: %s \n»,palabra); return 0;}

Evidentemente, más adelante, en las siguientes unidades, vamos a visualizar cómo, al haber atrapado esa información en una variable, podremos realizar operaciones de validación, para que el usuario, a través de esa entrada, pueda controlar el flujo de la información a lo largo de la aplicación

Aplicandolo sobre el ejercicio del curso:

En la versión anterior del ejercicio continuo de la publicación, nos habíamos quedado declarando una variable que, más adelante, almacenaría la opción que elige el usuario en cada una de las situaciones de ejecución del programa.

Así que, como aplicación práctica del ejercicio que desarrollamos a lo largo del curso, podremos comprobar que ahora a la variable opción, se le asignó una instrucción para capturar la entrada del usuario.

Por último, se introduce, de momento, a efectos de comprobar que el programa funciona correctamente, una instrucción de impresión en pantalla que simplemente se encarga de decir cuál es la opción escogida, simplemente para asegurarnos que se está recogiendo correctamente la instrucción, para, más adelante, a medida que vayamos cubriendo las siguientes unidades didácticas, poder actuar de una forma u otra en base a la elección que el usuario final realice.

agenda.c
/* Programa agendapor Jose Vicente Carratala */#include <stdio.h>#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»
int main(int argc, char *argv[]) {    // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«Tu opcion: «); char opcion = getchar(); printf(«La opción que has seleccionado es: %c \n»,opcion); return 0;}
Publicado el Deja un comentario

Simulación mediante software del efecto del aislamiento en la propagación del Coronavirus

Nota: Esta es la segunda parte de un artículo previo publicado hace dos semanas, que puedes encontrar aqui: https://jocarsa.com/software-de-simulacion-expansion-de-un-virus-como-el-coronavirus

En las últimas semanas he estado desarrollando un software que simula los diferentes escenarios en la propagación de un virus como el Coronavirus también conocido como COVID-19

En las últimas iteraciones, he realizado diferentes pruebas que simulan el confinamiento de la población, y su liberación en diferentes momentos. A grandes rasgos, el software confirma que el aislamiento es una solución para evitar la propagación del virus, y para evitar el colapso de un sistema sanitario que tenga que tratar a demasiados pacientes que enfermen de forma simultánea.

En primer lugar, he realizado una simulación en la que la población no es aislada, y el virus campa a sus anchas. Es inevitable que, en un periodo de tiempo, la población quede infectada. Finalmente se produce una inmunización, pero a coste de un número de vidas, y de un número elevado de enfermos, en un cierto momento. Por cierto que el software no calcula subida de tasa de mortalidad en el caso de sistema sanitario saturado, de haberlo calculado, probablemente los datos saldrían diferentes. Puedes visualizar esta simulación en el siguiente video:

En segundo lugar, he realizado una simulación en la que la población comienza a infectarse, y se recluye en sus domicilios durante un breve periodo de tiempo. Tras ese breve periodo de tiempo, la población es liberada. Sin embargo, liberar a la población demasiado pronto, produce un segundo repunte definitivo de la enfermedad – y por tanto, se demuestra que levantar demasiado pronto el aislamiento no detendría la expansión del virus, ni sus consecuencias negativas

En sucesivas simulaciones he realizado nuevos cálculos acerca del tiempo de liberacion. En un caso extremo, aumentar el tiempo de aislamiento, pero no lo suficiente, produce un segundo repunte de las infecciones, retrasando el momento de forma inevitable.

Solo cuando el levantamiento del aislamiento se produce tras el suficiente tiempo, es cuando no existe una propagación del virus. El problema, evidentemente, en el caso real (no en una simulación) es saber con precisión cual es ese tiempo, para evitar que la propagación vuelva a empezar cuando las medidas de aislamiento cesen

Solo cuando ha pasado el tiempo suficiente en aislamiento, es cuando se puede liberar a los sujetos implicados, sin peligro aparente de que la infección se vuelva a extender

En el ultimo video, he recopilado unas cuantas simulaciones realizadas con varios casos posibles, para que el resultado sea más ilustrativo

Conclusiones:

Dentro de que las simulaciones realizadas son simplificaciones de una realidad compleja, el software no simula una serie de condiciones sobre las cuales los usuarios han proporcionado retroalimentación, tales como:

  • Simulación de un estado de semilibertad (actividades profesionales imprescindibles)
  • Simulación de una tasa de muertes diferente cuando el sistema sanitario está colapsado (el sistema, actualmente, asume una tasa de curación uniforme para todos los enfermos)

Aún teniendo en cuenta estas limitaciones (que serán resueltas en próximas versiones del programa), la clara conclusión que podemos sacar es que el aislamiento realmente sirve para contener la propagación del virus, y para dosificar la afluencia de enfermos a un sistema sanitario que no está preparado para una situación como la actual. Aunque la simulación no lo refleja, es evidente que dosificar la afluencia de enfermos a los centros sanitarios aumentará en gran medida sus posibilidades de recuperación, y disminuirá el número de bajas.

Siguientes pasos

El sistema, actualmente, acepta una serie de entradas como variables paramétricas. En las próximas semanas realizaré una batería de pruebas, para conectar el software con un sistema generativo, a fin de que, mediante fuerza bruta, el propio sistema pueda encontrar un balance, un caso óptimo, en el que el tiempo de aislamiento sea lo menor posible, minimizando igualmente el número de muertes.

Publicado el Deja un comentario

Programando en C: Contenedores de datos

¿Qué son las variables?

Tipos de datos

Los tipos de contenedores de datos para las variables varían bastante entre un lenguaje de programación y otro.

Sin embargo, a continuación, voy a indicar los grandes tipos de variables que encontramos a lo largo de los lenguajes de programación más comunes hoy en día.

variables de tipo numérico

Éstas variables guardan números en multitud de formatos.

En primer lugar tenemos las variables de tipo entero, que guardan números decimales.

A continuación tenemos las variables de tipo flotante, que son capaces no solo de guardar números enteros, positivos, sino que también 

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int variable = 5; printf(«La variable vale: %i \n»,variable); return 0;}

Son capaces de guardar decimalesComa para aquellos casos en los que necesitemos aumentar la precisión en el cálculo. en el siguiente ejemplo, mostrado a continuación, podemos observar como se declara tanto una variable de tipo entero, como una variable de tipo flotante, es decir, con la posibilidad de guardar decimales 

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int variable = 5; printf(«La variable vale: %i \n»,variable); float variableConDecimales = 0.5; printf(«La variable vale: %f \n»,variableConDecimales); return 0;}

Texto

Existen varias formas de guardar cadenas de texto dentro de nuestros programas desarrollados en C

 una de ellas es mediante el tipo de dato primitivo char, que, como su nombre indica, es capaz de guardar un carácter

 podríamos considerar, por tanto, que una palabra o incluso una frase o un texto no es más que un conjunto de caracteres dispuestos uno detrás de otro

 de esta forma, aunque la cuestión de las matrices y los arreglos será discutida más adelante, en este caso, estamos creando una variable a la que, a continuación, e introducimos un corchete de apertura y un corchete de cierre

 estos dos corchetes indican que esa variable no solo contiene una unidad de ese tipo de datos, en este caso un carácter, sino que contiene un conjunto de ese tipo de datos, es decir, en este caso concreto contiene un conjunto de caracteres, o lo que es lo mismo, una palabra, o un texto 

main.c
#include <stdio.h>

int main(int argc, char *argv[]) {
    int variable = 5;
printf(«La variable vale: %i \n»,variable);
float variableConDecimales = 0.5;
printf(«La variable vale: %f \n»,variableConDecimales);
char variableTexto[] = «Jose Vicente»;
printf(«La variable vale: %s»,variableTexto);
return 0;
}

Reglas de declaración de variables

debemos tener en cuenta que existen una serie de reglas para declarar correctamente variables.

Éstas reglas pueden variar a lo largo de los lenguajes de programación, y es por esto que yo suelo recomendar una serie de pautas, comunes entre los diferentes lenguajes de programación, para asegurar que, más adelante, vamos a poder saltar de un lenguaje de programación a otro teniendo que reaprender el mínimo número de cosas posibles.

Las variables pueden contener números, pero no deben empezar con números.

De esta forma, esto estaría perfectamente aceptado:

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int variable2 = 5; return 0;}

Esto también estaría aceptado

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int vari3able = 5; return 0;}

Pero esto no sería aceptable, ya quedaría error en la mayoría de programas.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int 1variable = 5; return 0;}

larga la mayoría de lenguajes de programación no aceptan el uso de espacios a la hora de declarar variables.

Los espacios que eran reemplazados por guiones bajos.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int una_variable = 5; return 0;}

De todas formas, mi recomendación es usar la nomenclatura Camell queréis, ya que es compatible en la gran mayoría de lenguajes modernos.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int unaVariable = 5; return 0;}

soporte para Unicode

La gran mayoría de lenguajes modernos tienen soporte para Unicode, permitiéndonos usar caracteres como vocales con acento, la letra N, o la Ç para el nombre de las variables.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int escaño = 5; return 0;}

Mi recomendación, en la medida de lo posible, es no usar estos caracteres, por una cuestión de retro compatibilidad, y compatibilidad entre lenguajes de programación.

Sin embargo, curiosamente, también recomiendo poner nombres de variables, funciones, clases, y otras estructuras en castellano y no en inglés.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int edad = 5;    int age = 5; return 0;}

Los lenguajes de programación, todos ellos, tienen palabras reservadas.

Las palabras reservadas no pueden ser usadas por el desarrollador.

cuando estamos aprendiendo a programar, una de las dificultades más costosas de superar, consiste en saber, en un determinado código, cuál es son las palabras que nosotros, pero como programadores, podremos cambiar, y cuáles son las palabras reservadas por el lenguaje de programación.

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    int auto = 5; return 0;}

dado que prácticamente todos los lenguajes de programación están escritos en inglés, en nuestro caso, hablar en español puede suponer una ventaja, ya que nos permite nombrar a nuestras estructuras en nuestro idioma, y de esa forma, podemos diferenciarlas perfectamente, y sabemos que, salvo en mi caso es concretos como el uso de la palabra » final «, es decir, palabras que existen en los dos idiomas, salvo en esos casos concretos, las probabilidades de colisión disminuyen, y el entendimiento del código fuente mejora.

Evidentemente, es de Consejos solo es aplicable para desarrolladores o equipos de desarrollo formados únicamente por personas españolas o por personas para las que el español sea su lenguaje natural.

en el caso de que el equipo de trabajo este compuesto por personas de otras nacionalidades, en ese caso, por claridad y en pro de la comunicación, será recomendable usar nomenclatura inglesa para todas las estructuras que puede elegir el usuario

Listado de palabras reservadas de C

Estas son las 32 palabras reservadas en C que no debemos usar como nombres de varables o estructuras:

auto, break, case, char, const, continue, default, do, int, long, regiester, return, short, signed, sizeof, static, struct, switch, typedef, union, unsigned, void, volatile, while, double, else, enum, extern, float, for, goto, if

Aplicación sobre el ejercicio del a publicacion

A continuación, aplicamos lo que hemos aprendido en la presente unidad didáctica, hasta el momento, al ejercicio que estamos desarrollando en el curso

 si anteriormente hemos definido un menú en el que el usuario podrá seleccionar una serie de opciones, preparamos un carácter para poder recibir esas opciones

 debemos tener en cuenta que, ahora mismo, hemos aprendido a crear variables, y a preparar las para contener datos, pero todavía no hemos aprendido a pedirle una entrada de datos al usuario humano, y poder guardar esos datos en una variable. evidentemente, esto no aprenderemos en las siguientes unidades didácticas

 sin embargo, adelantamos el hecho de que, cuando le pedimos al usuario una entrada de datos, por defecto esta entrada se efectúa en formato de carácter, o cadena de caracteres

 es por esto que el lector se podría preguntar cuál es el motivo de estar declarando una opción como un tipo de datos carácter, cuando las opciones consisten en indicar un número desde el 1 hasta el 5. en principio, podríamos pensar que el tipo de variable más correcto sería el de número entero, ya que coincide con el concepto de números enteros desde el 1 hasta el 5 

Sin embargo, debido a que la entrada de datos se produce por defecto en formato de carácter, es por eso que estoy reservando una variable específica con ese tipo de datos, paraque no haya discordancia entre los datos recibidos, y el tipo de dato de la variable que finalmente lo va a guardar, un problema que, por cierto, es muy característico de los programas informáticos, y que más adelante, hacia el final de la publicación, veremos cómo tratar 

agenda.c
/* Programa agendapor Jose Vicente Carratala */#include <stdio.h>
int main(int argc, char *argv[]) {    // Mensaje de bienvenida printf(«Programa agenda v1.0 \n»); printf(«Selecciona una opción \n»); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«Tu opcion: «); char opcion; return 0;}

Constantes

Las variables ocupan un cierto espacio en la memoria, y no solo eso, sino que además el uso de espacio no es particularmente eficiente desde el punto de vista en que se está reservando un espacio que se supone que está abierto a cambios puntos

existen ocasiones, sin embargo, en las que, cuando declaramos una variable, sabemos que su valor, pese a su nombre, no va a variar a lo largo del programa.

Un ejemplo clásico fácilmente entendible es el valor del número pi.

cuando tenemos este tipo de recursos, usamos, siempre que el lenguaje de programación tenga disponible, el concepto de constante.

Una constante básicamente es como una variable, pero no varía su contenido a lo largo de la ejecución del programa.

esto puede parecer una desventaja con respecto a usar variables, pero sin embargo, también cabe decir que el uso de constantes optimizar el uso de memoria por parte del programa, y por tanto, el rendimiento en su ejecución.

Así que, de esta manera, será recomendable que usemos constantes siempre que podamos, y siempre que estemos trabajando con un programa donde el rendimiento sea un factor clave.

main.c
#include <stdio.h>#define PI 3.1416
int main(int argc, char *argv[]) {    const float velocidadSonido = 343.2;    printf(«El valor de pi es: %f \n»,PI);    printf(«La velocidad del sonido es:  %f \n»,velocidadSonido); return 0;}

Aplicandolo al ejercicio del programa:

A continuación, he creado una nueva copia de seguridad del proyecto del curso, y, sobre el único archivo que ahora mismo componen el proyecto, que es el agenda. Se, he añadido el siguiente código:

Como podemos comprobar, he definido tres constantes en la zona del pre procesador, indicando tanto el nombre del programa, como la versión, como el autor.

Lo primero que debemos notar, es que, por el estilo, los números de las variables se describen completamente en mayúsculas, para diferenciarlas de las variables que más adelante definiremos.

Recordemos, que, una vez más, las constantes podrían declararse siguiendo la nomenclatura Camel gays, O todo en minúsculas, pero aceptamos la regla estilística para que nuestro código esté en sintonía con la reglas que están usando el resto de programadores.

En cuanto al uso de constantes, evidentemente se debe a que, una vez que el Program Ana se ha empezado a ejecutar, evidentemente no esperamos que cambie el nombre del programa, la versión, o el autor.

De esta forma, es por lo que, pudiendo haberlas declarado como variables, las hemos declarado como constantes, para hacer un uso más eficiente de la memoria, ya que recordamos que las constantes son más fáciles de albergar que las variables.

Por otra parte, al final del programa, observamos como el creado una variable de tipo carácter para almacenar la opción que, más adelante, el usuario elegirá.

Evidentemente, esta opción se declara como variable y no como constante, ya que a lo largo de la ejecución del programa, por supuesto será normal que la opción que vaya eligiendo el usuario final del programa, vaya variando.

Es decir, eso talmente normal que el usuario, por ejemplo, empiece obteniendo un listado de registros, luego eligen introducir un registro, y más adelante, quién sabe, podrá eliminar, buscar, o actualizar, en definitiva, ir a eligiendo una opción diferente en cada una de las situaciones dentro de la misma ejecución, y es por esto que la opción nunca debería ser una constante, ya que se espera que vaya a variar.

agenda.c
/* Programa agendapor Jose Vicente Carratala */#include <stdio.h>#define NOMBREPROGRAMA «Programa agenda»#define VERSION «1.0»#define AUTOR «Jose Vicente Carratala»
int main(int argc, char *argv[]) {    // Mensaje de bienvenida printf(«%s v%s \n»,NOMBREPROGRAMA,VERSION); printf(«%s \n»,AUTOR); printf(«\t 1 – Listado de registros \n»); printf(«\t 2 – Introducir un registro \n»); printf(«\t 3 – Eliminar un registro \n»); printf(«\t 4 – Buscar un registro \n»); printf(«\t 5 – Actualizar un registro \n»); printf(«Tu opcion: «); char opcion; return 0;}
Publicado el Deja un comentario

Programando en C: Operaciones de impresion en pantalla

¿Que son?

Un lenguaje de programación no tiene porque estar mostrando continuamente información en pantalla.

Puede tomar datos de entrada, y puede estar continuamente operando con esos datos de entrada de manera interna, sin mostrar, hasta el final, o quizás a veces nunca, nada de información al ser humano.

Sin embargo, cuando estamos aprendiendo a programar, es altamente útil contar con algún tipo de salida por pantalla, para, de alguna manera, poder comprobar que el código que estamos desarrollando cumple las funciones que inicialmente estaban previstas.

es por esto que, en el aprendizaje de cualquier lenguaje de programación, es altamente útil que, a lo largo de los primeros pasos de aprendizaje, se aprende algún tipo de instrucción que nos permita realizar una salida de información por pantalla, ya sea a través de una consola, o bien a través de una interfaz de usuario más elaborada, como por ejemplo, una aplicación en ventanas

main.c
#include <stdio.h>
int main(int argc, char *argv[]) { printf(«Esto es un mensaje \n»); printf(«Esto es otro mensaje \n»); return 0;}

Las operaciones de impresión en pantalla, por el momento, son nuestra herramienta para crear, de alguna manera, interfaces de usuario.

De esta forma, en definitiva, vamos a estar trabajando con esta instrucción, para que el programa se comunique con nosotros.

Durante una buena parte de esta publicación, por lo tanto, estaremos trabajando desde la terminal, es decir, tanto usaremos la terminal para introducir información, cómo será la terminal la que nos devuelva información.

De esta forma, debemos adaptarnos a ciertas reglas de los terminales tanto de Windows, como de Linux, como de Mac.

Es por esto que, como habremos observado en el código, muy frecuentemente encontraremos el carácter de contra/N.

Éste carácter, en cualquier terminal, no sirve para invocar el retorno de carro, o lo que es lo mismo, la creación de una nueva línea, es decir, que el programa finalice la línea actual, y coloque el cursor en una nueva línea a continuación, bajo de la línea antigua.

Sin embargo, una vez más, debemos recordar que el motivo de este carácter es porque estamos trabajando en la terminal.

Por ejemplo, otro uso de fe es generar archivos cgi para ser ejecutados en un servidor web, que en definitiva, acaba transformando la información en el código html.

Es decir, en ese caso, en el caso de la creación de archivos cgi con el lenguaje sí, finalmente, el contenido no se muestra en la consola sino que se muestra en un navegador web, con las reglas del lenguaje html.

De esta forma, cuando esto ocurre, el carácter de retorno de carro no es contra/N, sino que es el propio de ese lenguaje de marcaje, que es br

Aplicando lo que hemos aprendido en el ejercicio de la publicación:

A continuación, abrimos el programa con el que hemos estado trabajando en las dos lecciones anteriores, introducimos una serie de líneas, que nos ayudarán a formatear un menú de inicio.

Es decir, una vez que hemos presentado el programa, la versión, y le hemos indicado al usuario que debe seleccionar una opción, introducimos una serie de líneas más, para especificar cuáles son estas opciones disponibles en el programa.

Deberíamos notar la presencia de los caracteres contra barrote, y contra/N.

El carácter contra/N, como hemos comentado anteriormente, no sirve para saltar una nueva línea.

El carácter contra barrote, actúa de manera similar, con la diferencia de que, en lugar de saltar a una

, Realiza un salto de tabulador.

En definitiva, nos permite realizar una sangría, no ya en el código que estamos escribiendo, sino en el texto que escribe el programa en la consola en el momento de ejecutarse.

, Podremos observar, en la última de las operaciones de impresión, se nos ofrece escoger una opción.

Evidentemente, de momento paramos el desarrollo del ejercicio del curso aquí, ya que todavía no sabemos cómo hacer para que el usuario introduzca una opción, y el programa la reconozca. Evidentemente esto se va a desarrollar en las siguientes unidades didácticas de esta publicación.

agenda.c
/* Programa agendapor Jose Vicente Carratala */#include <stdio.h>
int main(int argc, char *argv[]) {    
// Mensaje de bienvenida
printf(«Programa agenda v1.0 \n»);
printf(«Selecciona una opción \n»);
printf(«\t 1 – Listado de registros \n»);
printf(«\t 2 – Introducir un registro \n»);
printf(«\t 3 – Eliminar un registro \n»);
printf(«\t 4 – Buscar un registro \n»);
printf(«\t 5 – Actualizar un registro \n»);
printf(«Tu opcion: «); return 0;
}
Publicado el Deja un comentario

Software de simulación – expansión de un virus como el coronavirus

Actualización: El 29 de abril estaré impartiendo un webinar online sobre Inteligencia Artificial y Big Data para marketing. Puedes apuntarte al webinar de forma gratuita aqui:

https://capitolempresa.com/webinars/

Este artículo ha sido actualizado con un artículo más reciente, que puedes encontrar aqui:

Primera versión del software

Concienciado por la situación actual y en aislamiento domiciliario para frenar el avance del CoronaVirus, he desarrollado un programa de simulación del contagio de un virus por parte de una población en movimiento.

La versión corta del software puede verse en este video:

Mediante un sistema de partículas, he recreado un entorno virtual en el que, en medio de una población en movimiento (partículas grises), aparece un individuo infectado (partícula roja), que tiene la capacidad de transmitir el virus a las personas con las que establece contacto.

El sistema simula la existencia de personas que no desarrollan síntomas del virus, y que sin embargo contribuyen al contagio (partículas amarillas). Una vez que ha pasado el tiempo, esas personas pueden curarse por sí mismas sin haber desarrollado síntomas de la enfermedad (partículas verdes) y por tanto dejan de ser contagiosas. Otra posibilidad es que, después del periodo de contagio, enfermen (partículas rojas), resultando igualmente contagiosas.

En la gráfica podemos ver que, como es lógico, en un entorno donde los individuos circulan libremente, los contagios son contínuos, y los individuos enfermos, en un momento dado, pueden llegar a sumar el 25% de la población (con el consiguiente colapso del sistema sanitario que ello podría causar)

El software simula que un cierto porcentaje de los individuos que han enfermado no superan la enfermedad, mientras que otros si que lo hacen, y se curan. Sin embargo, el software asume una curación espontánea, y no simula la existencia o ausencia de un sistema sanitario, y su influencia en el número de personas que superen o que no superen la enfermedad.

El objetivo de este software es resultar ilustrativo para que la población general entienda el patrón de contagio de un virus en una población en contínuo movimiento.

En este video más largo se pueden apreciar más simulaciones, dando todas ellas unos datos similares.

Segunda versión del software

En una segunda iteración del software, incrementando el número de individuos, podemos ver aproximadamente los mismos datos que en la primera iteración, donde, en un primer lugar se produce una cadena de contagios, estos contagios producen individuos enfermos, y finalmente, la gran mayoría del colectivo de individuos acaba recuperándose (no sin un porcentaje de bajas, desgraciadamente)

En otro video, he realizado una serie de simulaciones secuenciales, que confirman el modelo original

Publicado el Deja un comentario

Programando en C: Comentarios

Comentarios

Los comentarios son mensajes o anotaciones que se introducen en cualquier parte del código fuente del programa que estamos desarrollando.

Estos mensajes, estos comentarios, son completamente ignorados por el intérprete, compilador, en lanzador, o en definitiva por cualquiera de las piezas que se encargan de interpretar el código de nuestro programa.

Por tanto, no tienen absolutamente ninguna regla sintáctica que seguir, más allá de aquella que define como empieza y acaba un comentario.

Fundamentalmente, se usan los dos comentarios para dos finalidades.

la primera, la obvia, consiste en dejar mensajes en lenguaje humano aclarando el funcionamiento de una sección de código.

Este mensaje puede ser dejado por un programador para asimismo, para cuando visualice su propio código fuente un tiempo después, para recordar la razón por la que había creado cada una de las secciones de código.

también puede utilizarse para que un desarrollador dejé instrucciones o pistas para que otros desarrolladores puedan comprender mejor su código.

por regla general los comentarios del código constituyen una buena costumbre y una buena práctica, especialmente cuando estamos empezando nuestro aprendizaje en cualquier lenguaje de programación.

Desde el punto de vista de la mantenimiento y dar del código, también constituyen una herramienta muy importante para realizar una documentación de las tareas que cubre nuestro código fuente.

Sin embargo, como todo en la vida, no hay que pegar ni por defecto ni por exceso, y es por esto que se suele decir que, cuando un código tiene un exceso de comentarios, es decir, cuando el código es tan complejo que requiere muchos comentarios para que cualquier otro programador lo pueda comprender, se suele decir que entonces probablemente lo que hace falta es simplificar el código, y no sobre comentarlo.

La segunda utilidad de los comentarios, tan importante como la primera, es la de desactivar ciertas partes del código.

Durante el desarrollo de un programa, especialmente durante la fase de depuración, es decir, la fase en la que aparecen los errores de ejecución y tenemos que buscarlos y limpiarlos, es muy normal necesitar desactivar temporalmente ciertas partes del código, por varias razones, siendo la más común de ellas la propia búsqueda de errores por descarte.

Si abrazamos una porción del código con un comentario, el compilador cree que esa porción del código es un mensaje en formato humano, y por tanto, omite la ejecución de esa porción.

En la mayoría de lenguajes de programación hay dos tipos de comentarios, los de una única línea, y los de varias líneas

Éstos dos tipos de comentarios podrían quedar resumidos en este ejemplo a continuación:

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {    
// Esto es un comentario de una sola línea 
   /*        Esto es un comentario
        de varias líneas
    */
printf(«Hola Mundo \n»);
return 0;
}

Aplicando lo que hemos aprendido sobre el ejercicio de la publicación:

A continuación, realizamos una copia de seguridad del estado anterior del proyecto, es decir, del proyecto agenda, en una nueva carpeta, para continuar dándole forma.

Recordamos que el único archivo que tiene, por el momento, nuestro proyecto, es un archivo llamado agenda. C.

Así que, a continuación, lo abrimos, introducimos el siguiente código:

agenda.c
/* Programa agendapor Jose Vicente Carratala */
#include <stdio.h>
int main(int argc, char *argv[]) {
    // Mensaje de bienvenida
printf(«Programa agenda v1.0 \n»);
printf(«Selecciona una opción \n»);
return 0;
}

Por una parte, porque como podemos observar, hemos introducido un comentario de múltiples líneas, al principio del todo del código, a forma a modo de presentación, introduciendo el nombre del programa, el autor, lo que suele constituir una costumbre bastante extendida en la escritura de programas informáticos.

A continuación, dentro del método principal, hemos introducido un comentario de una única Lineal, indicando cuál es la función de las dos instrucciones a continuación.

Este comentario de una única línea será bastante frecuente a largo del desarrollo de los ejercicios parciales, y del ejercicio final, para comentar y explicar, el lenguaje humano cuál, cuál es la función de cada uno de los bloques de código que escribiremos en esta publicación.

Publicado el Deja un comentario

Programando en C: Empezando con C

Para empezar a programar, únicamente hace falta un editor de archivos, es decir, un editor de texto plano, donde, en el menor de los casos, se recomienda una aplicación de tipo Block de Notas.

Lo que tendremos que hacer es crear un nuevo archivo dentro del sistema de archivos de nuestro sistema operativo, en una carpeta de nuestra elección, y pondremos al archivo un nombre, intentando evitar espacios, acentos, Eñes, y otros caracteres similares.

Para que más adelante el archivo sea correctamente reconocido por el compilador, deberá tener la extensión. C.

una vez creado el archivo, podremos abrirlo dentro del programa de edición de Block de Notas que estemos utilizando, donde es importante notar que deben evitarse programas que introduzcan formateo adicional al texto, tales por algo como por ejemplo Microsoft Word.

una vez dentro del archivo, tenemos que escribir el siguiente código:

main.c
#include <stdio.h>
int main(int argc, char *argv[]) {
printf(«Hola Mundo \n»); return 0;
}

En el caso del lenguaje de programación concreto que estamos tratando en esta publicación, como podemos comprobar, tenemos que importar una librería inicial que nos permite realizar operaciones de entrada y de salida.

A continuación, introducimos una función principal, que contiene el código que vayamos a ejecutar.

Por último, dentro de las llaves, especificamos cuál es el texto, en forma de instrucciones, que se va a ejecutar.

en este caso es importante notar que el nombre de la función no puede variar, ya que es una palabra reservada dentro del lenguaje.

Dentro de un programa podremos tener tantas funciones como queramos, pero sin embargo siempre deberá haber una, y solo una, llamada a Medellín.

Cuando el programa se ejecute, siempre lo hará partiendo desde esta función, como punto de partida, y si es necesario, llamará a todas las demás.

En el ejemplo que nos ocupa en esta sección, estamos desarrollando un programa llamado hola mundo.

Cuando empezamos en un lenguaje de programación, es muy común, es típico entre la comunidad de desarrolladores, utilizar esta sencilla frase, simplemente para comprobar que todo funciona como debe, y que el programa está respondiendo a nuestras instrucciones.

Aplicando lo que hemos visto hasta el momento sobre el ejercicio del curso:

A continuación, una vez que ya hemos realizado el ejercicio teórico de esta unidad didáctica, es el momento de arrancar el ejercicio práctico que vamos a ir desarrollando poco a poco a lo largo de la publicación, hasta obtener un programa funcionalmente completo.

Para crear este programa, simplemente, lo único que tenemos que hacer, de la misma forma que anteriormente hemos creado un archivo con la extensión C, es crear un archivo llamado agenda. C.

Una vez que hayamos creado el archivo, lo abrimos con un editor de texto, introduciremos el siguiente contenido:

Al ejecutar el programa, cómo podremos comprobar, el programa básicamente devuelve los créditos iniciales, indicando que es el programa de agenda, que está en la versión 1.0, invitándonos a seleccionar una opción de un supuesto menú de opciones.

Evidentemente, en este momento, el menú no existe, ya que lo vamos a crear en las siguientes unidades didácticas.

Como veremos, por tanto, si bien a lo largo de las unidades didácticas se van a ir proponiendo una serie de ejercicios, y cada uno de los ejercicios se escribirá en un archivo diferente, como hemos comentado anteriormente en esta misma publicación, el ejercicio que ahora arrancamos es un ejercicio continuo que desarrollaremos a lo largo de todo el libro, para acabar generando un proyecto completo.

Es por esto que el código fuente que ahora acabamos de arrancar, será completado poco a poco, aplicando cada uno de los conocimientos teóricos que vayamos adquiriendo.

Por tanto, siempre estaremos trabajando sobre el archivo agenda. C, pero, sin embargo, recomiendo que, al aplicar cada uno de los contenidos teóricos de cada una de las unidades didácticas, no estemos trabajando sobre el mismo archivo de agenda, sino que creemos una copia de seguridad, una copia incremental sobre la que trabajar.

De hecho, mi recomendación es hacer exactamente lo mismo que puedes ver en los archivos descargados adjunto sale esta publicación, es que en cada una de las carpetas de cada una de las unidades didácticas, existe una versión incremental del proyecto.

Este, de hecho, es un consejo que no solo te ofrezco para el ejercicio de este curso, y no solo te ofrezco para trabajar en general con lenguajes de programación, sino que es algo que te recomiendo para cualquier proyecto informático que desarrolles, que es, en definitiva, el ir guardando copias periódicas de seguridad, tal que si en algún momento ocurre algún suceso, como que por ejemplo el código fuente se corrompa, aunque cometas algún error del cual no se paso salir, siempre tendrás, por lo menos, la versión anterior en funcionamiento, para en un caso extremo, poder volver atrás, pero en definitiva, poder volver a un paso del proyecto donde sabías que estaba funcionando.

agenda.c
#include <stdio.h>
int main(int argc, char *argv[]) {
printf(«Programa agenda v1.0 \n»);
printf(«Selecciona una opción \n»);
return 0;
}
Publicado el Deja un comentario

¿Cuál es la diferencia entre Big Data y Data Science?

Big Data, como tendencia, si nos fijamos, probablemente es un poco inevitable en el mundo en el que vivimos. En una época en la que todas las grandes y pequeñas corporaciones acumulan datos de forma masiva de un modo u otro, era simple cuestión de tiempo que estas mismas corporaciones comenzaran a intuir que, del análisis de esas grandes cantidades de información, podía extraerse contenido de valor.

No importa realmente si a ese conjunto de técnicas los llamamos Big Data o los llamamos por cualquier otro nombre, al final no es más que un término que representa un concepto. Y el concepto es lo que importa. Y, en este caso, el concepto consiste en aportar una serie de técnicas que nos permiten, primero, homogeneizar los datos, y segundo, empezar a realizar operaciones con ellos para, tercero, obtener resultados y previsiones a partir de los mismos.

Data Science, o la Ciencia de los Datos, no es más que la evolución lógica de Big Data. Si Big Data trata acerca de, precisamente, el tratamiento de datos masivos, la ciencia de los datos estudia, de una forma mucho más general, cómo tratar cantidades de datos para obtener información de valor de los mismos. Parece lo mismo, pero no lo es.

Por ejemplo, si tomamos como inicio Big Data, encontramos que trata, en primer lugar, de la recopilación de datos de forma masiva, para su posterior análisis. Y, en muchas ocasiones, para realizar este análisis de datos, requerimos técnicas como, por ejemplo, la inteligencia artificial. De esta forma, la IA no forma una parte intrínseca de Big Data, pero ambas disciplinas guardan una estrecha relación.

Otro segundo ejemplo que podamos tomar, es que cuando trabajamos con grandes cantidades de datos, generalmente nos es necesario contar con algún tipo de método para representar gráficamente la información que queremos comunicar. Sin embargo, la parte de comunicación, analítica y generación de gráficas de múltiples tipos, realmente no forma parte de las técnicas de Big Data, aunque finalmente tenemos que contar con alguna forma de representar nuestros datos de cara a nuestros clientes.

El término de Data Science se establece precisamente como un subconjunto superior con respecto a la concreción de Big Data, se establece como un concepto mucho más genérico, amplio y elevado, cuya misión es tratar los datos desde múltiples perspectivas, con el objetivo de ofrecer una perspectiva completa y global de lo que es el tratamiento, en cualquier forma y en cualquier estrato, de conjuntos de datos. De esta forma, podríamos decir que Big Data es un subconjunto de todo aquello que se trabaja en Data Science.

Poco a poco, el mundo va transicionando desde Big Data hasta Data Science. Los países, a medida que implementan técnicas de Big Data y, una vez implementadas, requieren profundizar más en estos conceptos, van tomando consciencia de la importancia del concepto de Data Science como conjunto más amplio que Big Data.

Una demostración fácil de este concepto la podemos obtener si realizamos una sencilla investigación en Google Trends. Si visualizamos los datos correspondientes a la comparación entre los dos términos, en un país que consideramos tecnológicamente más avanzado que España, encontramos lo siguiente:

Hace ya tiempo que Data Science ha sobrepasado a Big Data en cuanto a términos de búsqueda en internet.

Si analizamos esta misma tendencia en un país como por ejemplo Alemania:

Podemos ver claramente como Alemania se encuentra en la misma situación que USA, pero con un retraso de un año aproximadamente. Los mismos datos representados para Francia nos muestran:

Y es que Francia se encuentra en una situación parecida a Alemania. Por último, si realizamos la búsqueda en España, encontramos lo siguiente:

Y es que nos encontramos, tecnológicamente, en un punto anterior al que podemos encontrar en países que llevan más años implementando este tipo de técnicas. De esta forma, podemos predecir fácil e inevitablemente cual va a ser el futuro de este tipo de técnicas en nuestro país.

Poco a poco, iremos transicionando desde un escenario donde usamos técnicas concretas y locales como aquellas que nos ofrece el Big Data, para implementar una concepción de cómo tratar los datos mucho mas global, una perspectiva mucho más amplia, que nos permita llegar a conclusiones de más valor, y que nos permita obtener el máximo de nuestros datos.

Publicado el Deja un comentario

Analítica y Big Data para WhatsApp

Cualquier aplicación en la que exista una gran cantidad de datos, es susceptible de ser analizada, y a cualquiera de estas aplicaciones se le puede aplicar técnicas de prospección para poder sacar tendencias y poder extraer conclusiones de utilidad.

Las aplicaciones de mensajería guardan multitud de datos pero, al menos de cara al usuario, no nos permiten obtener informes y estadísticas de cuál ha sido el uso que les hemos dado.

Gracias a estas estadísticas, podemos obtener información de valor acerca de cómo utilizamos aplicaciones como WhatsApp, además de obtener información y tendencias de uso futuras.

En esta aplicación de demostración, he realizado una serie de análisis iniciales sobre una conversación de WhatsApp, para transformar esos análisis en informes fácilmente interpretables.

En estos informes, podrás conocer cual de las dos personas ha participado más en la conversación, los meses en los que más movimiento ha habido, los días de la semana con más mensajes, e incluso un calendario detallado con los días y las semanas en las que han habido más mensajes.

Si estas interesado en conocer más información acerca de este proyecto, no dejes de enviarme un correo de contacto.

Publicado el Deja un comentario

El lenguaje de programación R y su relación con Big Data

¿Por qué el lenguaje de programación R, que en principio es tan desconocido, tiene tanta repercusión en el mundo del análisis de datos?

Si buscamos una referencia en el índice TIOBE, veremos que, de hecho, el lenguaje de programación R ocupa un puesto más bien lejano de las primeras posiciones, pero sin embargo, tiene una importancia destacada en aplicaciones de análisis de datos. En este artículo vamos a ver por qué esto es así.

Para decirlo claramente: El lenguaje R es fácil, y tiene herramientas optimizadas para analizar grandes cantidades de datos, y presentar la información de una forma sencilla.

Esto es importante desde el punto de vista en el que tenemos que tener en cuenta no solo las capacidades del lenguaje, sino las personas que lo usan. Qué es lo que hace falta para poder empezar a realizar análisis de datos masivos?

Generalmente, para realizar análisis con grandes cantidades de datos hacen falta varios componentes: Un conjunto de contenedores de bases de datos que proporcionen potencia suficiente como para almacenar y servir eficientemente los datos, un lenguaje de programación tal que nos permita versatilidad a la hora de realizar consultas a los datos, un sistema de interfaz de usuario mediante el cual podamos introducir información y recibir feedback, y probablemente una librería de generación de informes y gráficas sencillo…

Todos estos y algunos componentes más hacen que la introduccion a este mundo, la aproximación a realizar este tipo de extracciones de información sea dura para personas o profesionales que no tengan conocimientos previos de programación.

El lenguaje R provee un sistema ya preparado que ofrece al usuario una interfaz gráfica con la que empezar a programar de forma sencilla, una sintaxis clara que hace que programar sea asequible, y un entorno gráfico mediante el cual podemos obtener informes y gráficas de nuestras peticiones de una forma sencilla y clara.

Por tanto, ¿es el lenguaje R más potente, como muchas veces se dice, para realizar análisis extensos de grandes cantidades de datos? No es el más potente en absoluto, sino el más sencillo para empezar, para personas o profesionales sin conocimientos previos de programación. De hecho R tiene bindings para combinar su ejecución con C++, para aquellas aplicaciones que necesiten de un rendimiento mayor

Debemos tener en cuenta que esta ventaja puede convertirse en un obstáculo a medio plazo: El lenguaje R es muy concreto de un entorno de escritorio, y los programas que desarrollamos en el, o los resultados, no son directamente exportables en tiempo real a otras plataformas (si que lo son, pero con trabajo de conversión e integración, luego lo fácil que resulta al principio, puede ser complejo en un segundo término)

Finalmente, es imprescindible usar el lenguaje R para proyectos de Big Data? Si el equipo está compuesto por personal sin experiencia previa, R puede ser un buen candidato para empezar a obtener resultados con poco esfuerzo desde el punto de vista de la programación. Si en el equipo de análisis hay programadores informáticos, probablemente puede ser incluso más eficiente usar otros lenguajes de programación más asentados.

Publicado el Deja un comentario

¿Qué es el diseño generativo?

Antes de empezar a explicar este concepto que es tan sencillo como complejo de entender, voy a poner un símil, que a su vez es un antecedente, que explica cómo funciona el diseño generativo.

El diseño generativo como biodiseño

En la naturaleza, las especies evolucionan en base a cambios en su secuencia genética. Al reproducirse un individuo, y al pasar la información genética a la siguiente generación, se producen diversos cambios que causan modificaciones en cada uno de estos nuevos miembros de la especie. Y de todos es conocido que los miembros más adaptados o preparados para su entorno, acaban sobreviviendo, y los menos adaptados, no continúan la especie. Este proceso se repite una y otra vez, hasta que los individuos se adaptan lo mejor posible al entorno que les rodea.

El objetivo del diseño generativo es aplicar los mismos principios a la creación de productos o de bienes de consumo. Cuando un diseñador crea un producto, puede no estar eligiendo la mejor combinación de parámetros para esa creación – pero un diseño no es un ser vivo, no se reproduce, y no tiene un código genético – ¿o si?

¿Qué es el diseño generativo, entonces?

Cualquier producto se diseña y se crea en base a parámetros. Altura, anchura, grosor, radios, longitudes y dimensiones, cualquier bien de consumo finalmente está creado en base a unos parámetros que pueden ser modificables. Esos parámetros conformarían algo así como el ADN del producto. De esta forma, dado que el producto no puede cambiar sus propios parámetros, es el propio diseñador el que puede realizar múltiples versiones de un producto, puede alterar sus parámetros, y puede evaluar cada una de esas variaciones en busca de la mejor combinación.

Todo esto está muy bien en la teoría pero, que ocurre en la práctica? Somos humanos y tenemos limitaciones. El tiempo de un ser humano es limitado, y no puede realizar millones (si, literalmente millones) de variaciones sobre un diseño, y luego evaluarlas, porque ese trabajo, realizado de forma manual, podría llevarle toda su vida.

El diseño generativo no es un concepto nuevo, lleva entre nosotros poco menos de 30 años. Pero ahora tenemos una ventaja que no existía hace 30 años: potencia de cálculo. Un ser humano no puede realizar de forma manual millones de variaciones de un producto, pero una máquina correctamente entrenada sí que puede hacerlo, y en mucho menos tiempo. Una máquina puede generar todas esas variaciones, puede evaluarlas, y puede darle al diseñador la mejor alternativa. Luego puede seleccionar las mejores alternativas, puede seguir variándolas, y puede obtener nuevas selecciones, iterando el proceso tantas veces como se quiera, en busca del mejor diseño, de forma evolutiva.

Gracias a este proceso, ¿son las máquinas las que diseñan a espaldas de los humanos? Al menos de momento, no. Estamos entrando en la era de la inteligencia artificial, donde parece que los seres humanos corremos el riesgo de ser reemplazados por máquinas. El diseño generativo no plantea que sean las máquinas las que diseñen, sino que son los seres humanos los que realizan un diseño inicial, los que tienen que decidir cuales son los parámetros sobre los cuales trabaja la máquina, y la máquina realiza una serie de variaciones y mediciones sobre las variaciones.

Si que está claro que en el diseño paramétrico interviene la inteligencia artificial. Durante el proceso de generar las variaciones, la máquina aprende y se realimenta con lo que mejor funciona, y descarta lo que peor funciona. Es decir, se aplican de lleno conceptos de la inteligencia artificial y el big data (el análisis masivo de datos en busca de patrones), por lo que podemos decir que el diseño generativo es una de las muchas aplicaciones presentes y futuras de estas dos tecnologías.

¿Qué supone el diseño generativo para el diseñador humano?

Es, a la vez, una herramienta y un cambio de paradigma.

Como herramienta, el diseño generativo debe ser considerado como un arma más de la que dispone el diseñador para hacer su trabajo. Al igual que el lápiz, o la tinta, o más adelante la informática, la parte técnica, la parte computacional del diseño generativo no es más que una ayuda más, de caracter técnico, informático en este caso, para que el diseñador pueda plasmar sus ideas. De hecho las herramientas informaticas de diseño generativo pueden considerarse la evolución lógica de las herramientas de diseño asistido por ordenador.

Sin embargo, también puede considerarse que el diseño generativo supone un cambio de paradigma. A diferencia de cómo ha funcionado el diseño hasta el momento, no se considera como un objetivo que el diseñador tenga que buscar la solución al problema propuesto inicialmente a partir de su diseño. Con el paradigma del diseño generativo, se espera del diseñador que sepa parametrizar el problema, y que sepa introducirlo en un sistema, tal que el sistema pueda trabajar sobre cada una de las evaluaciones propuestas.

El diseño generativo como tendencia

Inevitablemente, de la misma forma que la inteligencia artificial y la aplicación de técnicas de gestión de datos masivos (big data) son tendencias imparables no ya de futuro, sino del mismo presente, lo mismo ocurre con el diseño generativo. Una rápida búsqueda en cualquier sistema de detección de tendencias, como por ejemplo Google Trends, nos revela fácil y rápidamente que el diseño generativo es una tendencia claramente al alza

Fuente: https://trends.google.com/trends/explore?date=today%205-y&q=generative%20design

De cara al futuro

Un sistema generativo puede encontrar soluciones mejores en mucho menos tiempo del que usaría un ser humano. Por tanto, desde el punto de vista de la competitividad, finalmente los sistemas generativos serán mucho más eficientes que aquellos flujos de trabajo que no los incorporen, en términos de que podrán producir soluciones mucho mejores, desde el punto de vista estético, estructural, y de costes de materiales, entre otros.

Los diseñadores actuales deben conocer la existencia de esta tendencia del diseño, ya que es cuestión de tiempo que este tipo de metodologías de diseño acaben imponiéndose en los mercados. Para cuando llegue ese momento, los profesionales del diseño tendrán que poder aprovechar al máximo este tipo de tecnologías, o perderán competitividad en favor de otros profesionales que si que les saquen partido.

Publicado el Deja un comentario

¿Qué es la inteligencia artificial?

La inteligencia artificial, que en años anteriores parecía ser terreno de la ciencia ficción, ya es una realidad que está entre nosotros. Cuando nuestro dispositivo movil reconoce nuestro rostro o nuestra voz para desbloquear el terminal y para saber lo que queremos, hay una inteligencia artificial detrás. Cuando el correo electrónico cada vez filtra mejor el correo no deseado, hay una inteligencia artificial detrás. Cuando la tienda online en la que compramos no solo es capaz de recordar lo que compramos anteriormente, sino que adivina de forma cada vez más eficaz lo que vamos a querer a continuación, hay una inteligencia artificial detrás.

Parece que, al menos hasta el momento, la inteligencia artificial es patrimonio exclusivo de las grandes corporaciones, y su uso y explotación, como usuarios, está lejos de nuestro alcance. Nos beneficiamos de ella, pero no podemos controlarla: otros la controlan por nosotros.

¿Qué es exactamente la inteligencia artificial?

Los lenguajes de programación clásicos se dedican a realizar tareas plenamente previsibles desde el punto de vista de la mecánica: El programador le dice al programa lo que tiene que hacer, y cómo tiene que hacerlo, y el programa lo hace, sin más. Por otra parte, los lenguajes de programación clásicos se basan en el uso extensivo de la lógica booleana: algo es cierto, o es falso.

Este paradigma clásico de programación no está desfasado, es tremendamente útil y seguirá en vigor durante muchos años más para la realización de una gran cantidad de tareas informáticas.

Sin embargo, hay otros tipos de tarea, donde se requiere que las aplicaciones informáticas tengan un comportamiento mucho más adaptativo, que sean capaces de llegar a sus propias conclusiones, y que sean capaces de aprender y afinar su comportamiento, donde la logica tradicional de «verdadero-falso» no proporciona soluciones concretas y útil. La inteligencia artificial consiste en la aplicación de una serie de metodologías que, desde la base, cambian completamente el paradigma de cómo crear aplicaciones informáticas.

Las aplicaciones informáticas basadas en inteligencia artificial simulan, para su funcionamiento, los procesos naturales mediante los cuales los seres humanos pensamos y aprendemos. Un ejemplo de esto es el uso de redes neuronales para una gran cantidad de procesos de inteligencia artificial.

De esta forma, a la inteligencia artificial le pasa exactamente igual que a los seres humanos cuando nacen y cuando crecen: las aplicaciones de IA son bastante poco inteligentes al principio, pero mediante la iteración y el auto aprendizaje, son capaces de refinar su comportamiento, mediante poca o ninguna asistencia por parte del ser humano, hasta tener un rendimiento superior a cualquier otro tipo de aplicación informática

Inteligencia artificial amplia y estrecha

Uno de los clichés más románticos de la inteligencia artificial es que simula completamente cómo funciona la consciencia humana. Este tópico frecuentemente es alimentado por la ciencia ficción y la cinematografía. Sin negar que ese puede llegar a ser un objetivo y una realidad en un futuro, la realidad de la inteligencia artificial es mucho más práctica y terrenal a día de hoy.

La inteligencia artificial se usa para resolver problemas muy concretos del día a día de una empresa, de un negocio, o de cualquiera de nuestras vidas como usuarios de aplicaciones. Por esto, es por lo que muy frecuentemente a las aplicaciones de inteligencia artificial se les entrena para tareas muy concretas: por ejemplo, reconocer caras de personas a partir de fotografías. Que un programa de inteligencia artificial sepa diferenciar caras humanas, no quiere decir, ni de lejos, que tenga algo parecido a una consciencia humana o sea capaz de «pensar» por si misma. Esto es lo que se conoce como Inteligencia Artificial Estrecha.

Mediante la inteligencia artificial amplia o ancha, el sistema tiene una serie de habilidades en diferentes campos de conocimiento, teniendo un grado mayor de libertad para tomar decisiones en base a la adquisición de información desde varias fuentes. Pero, una vez más, todavía estamos hablando de un escenario donde las aplicaciones no son capaces de imitar a la mente humana al completo. No porque no sea posible, sino porque simplemente no es conveniente, o porque el sistema en concreto se ha diseñado para resolver un problema concreto, y por tanto tratar de emular una mente humana completo no sería ni siquiera útil.

La inteligencia artificial como herramienta

La inteligencia artificial, finalmente, es una herramienta más, dentro del catálogo de herramientas del que dispone el ser humano, para resolver problemas. Finalmente, la idea de la inteligencia artificial es complementar a la inteligencia humana, para ayudarle a tomar mejores decisiones.

La inteligencia humana es muy versatil, extremadamente maleable, pero ineficiente en ciertos tipos de circunstancias. Por ejemplo, la inteligencia humana es muy buena extrapolando o interpolando datos: lo hacemos todos, todos los días, sin darnos cuenta, ya que está en nuestra naturaleza. Pero, sin embargo, nos es realmente difícil trabajar con grandes cantidades de datos. A la inteligencia artificial le pasa lo contrario, generalmente es buena en aquello que nosotros no lo somos.

La idea, finalmente, de la inteligencia artificial es que, correctamente enfocada, puede ser un complemento, una ayuda a la inteligencia humana.

La inteligencia artificial en la empresa

La inteligencia artificial ayuda a tomar decisiones de una forma automatizada. Permite tomar decisiones en base a parámetros, de una forma más rápida de la que lo podría hacer el ser humano, aunque por supuesto, detrás cada inteligencia suele haber uno o más seres humanos, orientando y dirigiendo lo que la inteligencia artificial debe calcular.

Las empresas requieren de tomas de decisiones constantes, y es por esto que la inteligencia artificial tiene cabida en el sector empresarial, desde el punto de vista en el que permite ayudar a los equipos a tomar mejores decisiones, o permite a las empresas ofrecer servicios que antes no era posible ofrecer.

Publicado el Deja un comentario

Big Data: Qué es y cómo funciona

Big data es uno de esos términos que se están popularizando en los últimos años, que aparecen, de forma cada vez más frecuente, en los medios, pero que muchas veces no acabamos de entender su significado. O, peor todavía, no acabamos de entender su utilidad.

Como usuarios, se nos dice que nuestros datos, y toda nuestra actividad, se almacena y se analiza en servidores remotos para realizar predicciones sobre nuestro comportamiento. Por ejemplo: Todo aquello que compramos en la red es analizado para ofrecernos nuevas sugerencias de compra adaptadas a nuestras necesidades. Esto es algo que todos sabemos, aunque no comprendamos exactamente cómo funciona. Y, como usuarios, es posible que ni siquiera sea necesario que comprendamos cómo funciona, aunque evidentemente nos preocupe.

Pero, como empresarios, oimos que las grandes corporaciones hacen uso de esos datos, y nos sentimos excluidos, ya que estas grandes corporaciones sacan un partido real (económico) del uso de los datos de los usuarios. Quizás en ese punto no nos preocupamos, por que el poder de grandes corporaciones como Google o como Apple nos parece muy lejano con respecto a nuestras posibilidades. Sin embargo, cuando nos llegan noticias de que algunas empresas de nuestro entorno empiezan a aplicar esas mismas técnicas para aumentar sus beneficios, es cuando nos empezamos a preocupar realmente: ¿Y si nos estamos perdiendo algo importante? ¿Y si nuestros competidores nos toman la delantera de forma silenciosa mediante la aplicación de esta tecnología de gestión de datos? ¿Y si para cuando nos demos cuenta de lo que ha ocurrido, ya es demasiado tarde?

¿Qué es el Big Data?

Vivimos en plena era de la información. Cualquier actividad que realizan los usuarios de la red puede ser registrada y almacenada, y no solo por las grandes corporaciones, sino por cualquier pequeña y mediana empresa que provea servicios en internet. Cuando se produce una interacción por parte de muchos usuarios en una pequeña franja de tiempo, la cantidad de datos recogidos por parte de la empresa es, sencillamente, demasiado grande y demasiado compleja para ser analizada mediante técnicas convencionales. El término anglosajón Big Data hace referencia a una serie de técnicas consideradas no convencionales para tratar grandes cantidades de datos, y obtener información útil de ellas.

¿Cómo afecta el Big Data a las empresas?

Si lo queremos, podemos recoger grandes cantidades de datos de toda la actividad de nuestros usuarios, dentro de los sitios web, las intranets, o en definitiva de cualquier servicio online que prestemos a nuestros clientes. Esta información puede ser analizada y, de ella, se pueden extraer conclusiones de importancia para la empresa. La limpieza de la información de partida y su estructuración para ser analizada, son dos de las primeras fases del big data. Pero lo realmente interesante ocurre después:

Mediante el cruzado de datos a través de diferentes técnicas, podemos obtener patrones de comportamiento, y podemos realizar incluso predicciones acerca de cómo se van a comportar nuestros usuarios.

El Big Data va más allá de la analítica web, pero la analítica sería una base, un pilar sobre el cual podemos fundamentar un análisis de grandes datos. Por ejemplo, una aplicación de analítica nos puede decir, sobre una tienda online, los productos más comprados, las horas del día a las que se producen más compras, o los días de la semana en los que los clientes están más activos. O un panel de control nos puede decir qué productos ha comprado cada cliente, no solo en su último pedido, sino en todos los pedidos que ha realizado.

Un análisis de big data va mucho más allá. Independientemente del volumen de datos, pero siempre que la muestra de datos sea suficientemente grande como para ser representativa, realiza un cruce de datos, combinando todas las compras de todos los clientes (siguiendo con el ejemplo de la tienda online) para, no solo analizar lo que se ha comprado, sino prever lo que se va a ser comprado.

Por ejemplo: En una tienda de ropa, si encontramos que la mayoría de los clientes que compran un pantalón y una camisa, a continuación compran unos zapatos, a cualquier cliente que compre, a continuación, un pantalón y una camisa, le ofreceremos comprar unos zapatos. Y, de esta forma, podremos aumentar nuestras ventas, ofreciendo a nuestros clientes el producto que quieren comprar, justo en el momento en el que lo quieren comprar.

Este ejemplo y su resultado, podría ser extraído, con mayor o menor esfuerzo, de los datos de ventas de una tienda online. Es más: cualquier propietario de tienda online podría saber las costumbres globales de sus clientes sólo con prestar un poco de atención a las ventas. Pero si multiplicamos este ejemplo, nos daremos cuenta de que, en cualquier tienda online, no solo se da el caso de que el cliente que compra una camisa (producto A) y un pantalón (producto B) a continuación compra unos zapatos (producto C): Si empezamos a cruzar un catálogo de productos de cientos o de miles de referencias, con una base de datos de clientes de decenas o centenares de miles, con diferentes hábitos de compra según su edad, su género, u otros muchos parámetros, nos daremos cuenta de que no sólo hay una secuencia A->B->C, sino que hay D->E->F, hay G->H->I, y millones de combinaciones más, de forma simultánea.

Y es entonces cuando tenemos una masa de datos tan grande que, pese a que intuimos que dentro de ella podríamos encontrar información de gran valor, finalmente no tenemos los medios o las metodologías para extraer patrones a partir de esa información, adaptar esos patrones a nuestros procesos de venta, y obtener resultados positivos. Para hablar claramente: no solo vender más, sino también vender mejor.

¿Cómo funciona el Big Data?

Una vez que hemos comprendido los beneficios de analizar estas grandes cantidades de datos y extraer información de utilidad de ese análisis, es cuando nos preguntamos: ¿Qué es lo que tengo que hacer para poder acceder a esa información?

A día de hoy, el Big Data es algo tan nuevo y cambiante, que no existe todavía un estándar, ni herramientas a nivel de usuario, para poder extraer información de una forma unificada y predecible. Hoy en día, cada proyecto de Big Data se diseña a medida de las necesidades de cada empresa, teniendo en cuenta dos factores clave: la entrada y la salida. La salida representa las conclusiones a las que se quiere llegar, los patrones que se están buscando (aunque en ocasiones ocurre que los análisis de Big Data proporcionan incluso más información de la que se esperaba obtener). La entrada representa toda aquella información que se está capturando y que, evidentemente, debe contener los parámetros necesarios para poder obtener la salida esperada.

A partir de ahi, entre la entrada y la salida, se aplican una serie de técnicas de análisis matemático y estadístico, que nos permiten obtener los resultados esperados. El problema para concretar esa serie de técnicas es que dependen, en gran medida, de la naturaleza de la información de entrada.

Por ejemplo: Un análisis de Big Data se podría realizar tanto en los hábitos de compra de los clientes de una tienda online (es decir, estaríamos cruzando los datos de clientes, con los datos de productos, con los datos de compras) cuando buscamos predicciones de compras, y por tanto mejorar los resultados económicos de una empresa, como en miles o decenas de miles de imágenes de resonancias magnéticas de pacientes, cuando buscamos predecir la evolución de ciertas enfermedades, y por tanto mejorar la salud de nuestros ciudadanos.

La idea es que el Big Data se puede aplicar con éxito en una cantidad innumerable de campos, proporcionando beneficios de múltiples tipos. Pero, actualmente, ante tal cantidad diferente de tipos de datos de entrada, y ante tal cantidad de tipos de resultado, no existe un conjunto de herramientas estándar, como alguna vez me han preguntado: un «Excel para Big Data» (aunque es probable que en el futuro si que llegue a existir algo así)

El mañana es hoy

Que no existan estas herramientas a nivel de usuario, no quiere decir que no podamos empezar a sacar partido del análisis de Big Data. Mientras que nosotros no lo hagamos, nuestra competencia lo habrá empezado a hacer ya, serán capaces de obtener mejores resultados, de vender de forma más eficiente, y de planificar sus procesos de empresa de forma más productiva, consiguiendo trabajar de forma más inteligente, y, finalmente, siendo más competitivos, obteniendo mayores beneficios.

Es por esto que, cualquier empresa que ya esté capturando un cierto volumen de datos, o que esté en disposición de hacerlo, debería considerar introducir dentro de sus procesos los análisis de Big Data.

Publicado el Deja un comentario

Reconocimiento de formas mediante redes neuronales

Una de las aplicaciones más conocidas y más fácilmente comprensibles de los modelos computacionales basados en redes neuronales es la identificación de formas en una imagen o vídeo, haciendo posible no sólo que las máquinas sean capaces de ver, sino también de identificar los elementos presentes en lo que están viendo.

El modelo de redes neuronales basa su funcionamiento en el procesamiento paralelo y concurrente por parte de varias unidades independientes, que llamamos neuronas en analogía al modelo fisiológico en el que está basado este modelo, que evidentemente es el cerebro animal. En computación, las neuronas no dejan de ser pequeños programas informáticos admiten una información de entrada, realizan un procesamiento relativamente sencillo, y devuelven una salida, de la misma forma que suponemos que funcionan las neuronas humanas.

A diferencia del desarrollo de programas informáticos tradicionales, donde disponemos de programas monolíticos con capacidades de cálculo avanzadas, el modelo de redes neuronales divide la complejidad en un número virtualmente infinito, y cuanto menos extenso, de unidades neuronales. Así, cada neurona se encarga de una tarea diferente, y todas trabajan en conjunto. De forma que, según los datos de entrada, se activarán unas neuronas u otras. En base a las combinaciones de neuronas activadas, el resultado global será uno u otro.

Este es un concepto complejo en un principio, y que a todos los estudiantes de inteligencia artificial se les atraganta al principio, pero que tiene un gran sentido.

Redes neurales sencillas

Supongamos que tenemos, por simplificar mucho el cálculo, un sistema de cuatro neuronas. Ese sistema, como cualquier otro sistema neuronal, debe ser entrenado antes de ser puesto en funcionamiento. Esto quiere decir que, a diferencia de la programación clásica, nosotros no podemos (o no debemos) preprogramar a un sistema neuronal para reconocer, por ejemplo, un ojo. Lo que debemos hacer es mostrarle al sistema una cantidad grande de ojos.

Volviendo a nuestro sistema neural de 4 neuronas, supongamos que, tras enseñarle 100 ojos, siempre se activan las neuronas 1 y 3, permaneciendo las neuronas 2 y 4 desactivadas. De esta forma, el sistema aprende que, siempre que, al recibir un estímulo visual, se activan las neuronas 1 y 3 y no se activan las neuronas 2 y 4, es muy posible que lo que esté viendo sea un ojo.

Redes neurales profundas

Este modelo se puede ampliar para mejorar su eficiencia en un modelo mediante el cual las neuronas se agrupan por capas, en un esquema, una vez más simplificado, como el siguiente:

La información de entrada está en la capa amarilla. La información de salida, es decir el resultado, está en la capa roja. En el medio, pueden existir una serie de capas intermedias, llamadas ocultas ya que el resultado que arrojan no es de utilidad para el usuario de la aplicación, pero si que es de utilidad como información que alimenta a la capa siguiente.

Por ejemplo, supongamos que tomamos como entrada la siguiente imagen:

En lugar de procesar la imagen completa, buscando adivinar si dentro de la imagen existe una cara, podemos intentar dividir un reto tan grande, genérico y complejo en retos más pequeños y específicos, como por ejemplo buscar si en la imagen hay lineas rectas (horizontales, verticales y diagonales, por ejemplo), como estas:

Estas lineas se usan para compararlas contra la imagen original. El resultado de la primera capa de computación es numérica, pero podría ser representada de un modo parecido a este:

Reconocer si en la imagen se encuentra una cara podría ser complejo, aunque posible perfectamente en la teoría, mediante la comparación relativa del número de horizontales, verticales y diagonales.

Sin embargo, en un modelo de varias capas, esa información se pasa a la siguiente capa. En la siguiente capa solo se evalúa la posibilidad de que haya objetos un poco mas complejos que una línea recta, como un círculo o una forma de esquina (una «L»)

De esta forma, cada una de las capas va proporcionando información cada vez más compleja a la capa superior, de tal forma que unas pocas capas más adelante podemos encontrar conceptos más elevados como «ojo», «nariz», u «oreja», y por tanto en la última capa encontraríamos el concepto más elevado, que sería «cara» (si se disparan las neuronas correspondientes a «ojo» dos veces, «nariz» una vez, y «oreja» dos veces, es muy probable que la imagen contenga una cara.

Conclusión:

La solución de problemas computacionales mediante redes neuronales no es recomendable para todo tipo de problemas, pero sin embargo es una estrategia muy eficiente en aquellas situaciones en las que disponemos de unos datos de entrada complejos, como imágenes, y deseamos realizar tareas complejas como reconocimiento de formas.

 

Cómo profundizar más en el conocimiento de las redes neuronales

Actualmente estamos produciendo un curso para aprender a desarrollar aplicaciones de inteligencia artificial. Si quieres saber más, haz click aqui:

Curso de inteligencia artificial

 

 

 

Publicado el Deja un comentario

Visión estereoscópica e inteligencia artificial

Proyecto de visión stereo.

En este desarrollo se aplica un algoritmo de cálculo mediante el cual, a partir de un par de vistas estereoscópicas, se obtiene un cálculo de la profundidad de cada uno de los puntos de la imagen. En este proyecto se presenta el cálculo de las distancias como un mapa de profundidad, una imagen en la que los puntos más claros son los más cercanos a la cámara, y los más oscuros son los más lejanos.

La visión estereoscópica es importante en el contexto de la inteligencia artificial, ya que permite a los sistemas inteligentes conocer su entorno y saber con precisión qué es lo que tienen delante, de forma previa a su procesamiento y toma de decisiones.

Este proyecto forma parte de los ejercicios del curso de inteligencia artificial – https://jocarsa.com/curso-de-inteligencia-artificial

Publicado el Deja un comentario

Nuevo curso publicado en Linkedin Learning

Ya está publicado el último grupo de cursos que he grabado hasta el momento para LinkedIn learning en sus oficinas de gratz, en Austria

 

el grupo consiste en cuatro cursos en los cuales, nuestro paso a paso cómo generar, configurar, y animar personajes en tres dimensiones

 

estos personajes pueden servir para un gran número de fines, como por ejemplo generar animaciones o servir de base para la presentación mediante personajes virtuales interactivos en realidad virtual

Publicado el Deja un comentario

Curso de robótica: Construye tu propio robot con Arduino e impresión 3D

Ya puedes matricularte en el curso de robótica que imparto de forma online

El objetivo del curso es construir un robot autónomo, usando básicamente dos subsistemas, un primer subsistema electromecánico, basado en la construcción de un ensamblaje de componentes en arruino, compuesto tanto por la placa, como por sensores y actuadores, y un segundo subsistema compuesto por las piezas del chasis, las ruedas, y la tapa. Este segundo subsistema está desarrollado usando tecnologías de diseño asistido por ordenador en 3D e impresión 3D.

En primer lugar, dentro de lo que es el curso, comenzamos explicando los fundamentos de los sistemas electromecánicos usando Arduino, con ejemplos tales como por ejemplo los siguientes:

  

En estos ejemplos, podrás ver como se muestra de forma simultánea tanto las piezas reales con las que se está trabajando, como el código fuente de programación que hace funcionar al sistema.

A continuación, una vez que se han adquirido una serie de fundamentos acerca del funcionamiento de Arduino, comenzamos el proyecto del curso.
Para ello, realizamos un estudio y un análisis del ensamblaje que queremos desarrollar, empezando con bocetos a papel.

Una vez que tenemos el boceto, lo convertimos a tres de usando un software de diseño asistido por ordenador, basado en polígonos, que nos permite generar formas orgánicas de forma muy fácil y eficiente, a diferencia de otros sistemas que en principio parecen avanzados, pero que fallan al generar justo este tipo de geometría.

A continuación, pasamos a separar el diseño conceptual en varias piezas, que más adelante serán impresas en 3D.

El siguiente paso es mostrar un software que nos permite simular cómo sería la impresión en 3D, especificando la estructura interior de los objetos, la calidad de la impresión, una simulación del recorrido del cabezal, etc.

Una vez que hemos realizado estas simulaciones, es cuando enviamos las piezas realmente a impresión. En este bloque del curso, mostramos el propio proceso de impresión, y vamos realizando comentarios acerca de cuáles son las mejores técnicas y las más recomendadas para realizar una impresión con impresora de plástico 3D.

De forma paralela a la impresión en 3D de las piezas del chasis y las ruedas del robot, vamos aplicando los conocimientos adquiridos al principio del curso para el desarrollo del sistema completo electromecánico usando, una vez más, Arduino. De esta forma, no nos centramos en explicar el funcionamiento de un solo componente como hemos hecho la primera parte del curso, sino que nos preocupamos de crear un proyecto completo y complejo.

Llegado este momento del curso, es cuando obtenemos las piezas salidas de la impresora 3D, y las preparamos en primer lugar para su ensamblaje.

Una vez que están ensambladas, integramos dentro del conjunto la parte electrónica, funcionando por fin las dos vertientes del producto, es decir, tanto la impresión 3D como el ensamblaje electromecánico.

Por último, tenemos un robot construido a partir, como he comentado anteriormente, de un ensamblaje realizado con técnicas de diseño asistido por ordenador el impreso con técnicas de impresión 3D y de prototipado, y de un sistema electromecánico creado a partir de piezas de Arduino.

Lo más importante de este curso, es que, a diferencia de otros, cuenta con soporte.

Es decir, en muchos otros cursos, donde se enseña a crear proyectos similares, no se cuenta con soporte, y por tanto, estás obligado a desarrollar un proyecto de características iguales o similares al que se está mostrando en el curso.
En este curso, en cambio, cuentas con soporte vía correo electrónico, y si fuera necesario, vía Skype, para solucionar todas aquellas dudas que te pueden surgir a lo largo del desarrollo no ya del proyecto del curso, sino de tu propio proyecto, en el que desarrollarás tu creatividad para crear un robot no exactamente igual al que se muestra en los videos, sino uno que crearás tú mismo, en base a tus propios diseños.

De esta forma, es completamente normal que, al desarrollar un diseño personalizado, te surjan muchas dudas acerca de cómo aproximar tanto la parte electrónica, como la parte del diseño 3D.
Por ello es importante que cuentes con alguien que te pueda resolver las dudas y que te pueda permitir finalizar tu proyecto de forma exitosa, uniendo de esta forma lo mejor de la formación online con lo mejor de la formación presencial, es decir, tienes la ventaja de la formación online, y es que puedes realizar el curso completamente a tu ritmo, pero también tienes la ventaja de la formación presencial, y es que tienes a alguien experto para poder ayudarte y asesorarte en el momento en el que puedas atascarte.

El desarrollo de un proyecto completamente personalizado es otro de los motivos por los cuales este curso no incluye ni los materiales electrónicos, ni la impresión 3D.
El número de componentes electrónicos que finalmente acabes usando, dependerá mucho del proyecto que elijas realizar, y por tanto, evidentemente, el presupuesto de estos componentes también dependerá del número de ellos que hayas elegido.
Y con la impresión 3D, ocurre exactamente lo mismo, y es que el coste de la inversión dependerá del diseño que finalmente realices.

 

Para obtener más información sobre el curso, puedes hacerlo rellenando el siguiente formulario:

Curso de robotica con Arduino e impresión 3D

Contenido del curso

Unidad 1: robotica

Subunidad 1: Actuadores:

Lección 1: Modificacion del programa

Lección 2: Sonido en altavoz

Lección 3: Alarma con altavoz

Lección 4: Alarma en bucle

Lección 5: Servomotor 180 grados

Lección 6: Servomotor continuo

Lección 7: Leds externos

Lección 8: Varios leds

Subunidad 2: Sensores:

Lección 1: Fotorresistor y buzzer

Lección 2: Ultrasonidos

Lección 3: Programacion ultrasonidos

Lección 4: Ultrasonidos y buzzer

Subunidad 3: Ejercicio:

Lección 1: Buzzer

Lección 2: LED

Lección 3: Fotorresistor

Lección 4: Segundo fotorresistor

Lección 5: Calibracion

Lección 6: Servomotor

Lección 7: Alimentacion externa

Lección 8: Conectar cable USB

Lección 9: Segundo servomotor

Lección 10: LED encendido

Lección 11: Igualacion de resistencias

Lección 12: Sensores luz

Lección 13: Arduino Shield

Lección 14: Arduino shield 2

Subunidad 4: Fundamentos_programacion:

Lección 1: Comentarios

Lección 2: Plantilla

Lección 3: Memoria en placa

Lección 4: Variables

Lección 5: Tipos de datos

Lección 6: Puerto serie

Lección 7: Cadenas de caracteres

Lección 8: Incrementos

Lección 9: Estructura IF

Lección 10: Estructura SWITCH

Lección 11: Estructura FOR

Lección 12: While

Lección 13: Do while

Lección 14: Funciones

Lección 15: Funciones con parametros

Lección 16: Ambito de variables

Subunidad 5: Desarrollo_de_las_vistas:

Lección 1: Propuesta cilindrica

Lección 2: Desarrollo del cubo

Lección 3: Esfera y variacion

Lección 4: Despiece

Lección 5: Desarrollo del concepto

Lección 6: Desarrollo de las vistas

Lección 7: Desarrollo de las vistas parte 2

Subunidad 6: Esbozo3D:

Lección 1: Importar componentes

Lección 2: Importar sensor

Lección 3: Importar portapilas

Lección 4: Aproximaciones del modelo

Lección 5: Representacion conceptual

Subunidad 7: Partes:

Lección 1: Ultrasonidos

Lección 2: distribucion

Lección 3: Suavizado

Lección 4: Separacion

Lección 5: Proporciones

Lección 6: Interior

Lección 7: Rueda delante

Lección 8: Colocacion

Lección 9: Ruedas

Lección 10: Desarrollo rueda

Lección 11: Comprobacion

Lección 12: Prueba validacion

Lección 13: Valida rueda

Lección 14: Tapa

Subunidad 8: Alimentacon:

Lección 1: Regular

Lección 2: Componentes

Lección 3: Soldar conector

Lección 4: Soldar portapilas

Lección 5: Segundo portapilas

Lección 6: Soldar

Lección 7: Resultado

Lección 8: Retirar pilas

Subunidad 9: CURA:

Lección 1: Rueda y soporte

Lección 2: CURA

Lección 3: Caja

Lección 4: Esfera

Lección 5: Rueda

Lección 6: Cuerpo

Lección 7: Hueco rueda

Lección 8: Eje y problema

Subunidad 10: Impresion3D:

Lección 1:

Lección 2:

Lección 3:

Lección 4:

Lección 5:

Lección 6:

Lección 7:

Lección 8:

Lección 9:

Subunidad 11: CURAfinal:

Lección 1: analisis ruedas

Lección 2: Analisis tapa

Subunidad 12: Revision_piezas:

Lección 1: Retirar soporte

Lección 2: Soporte tapa

Lección 3: Montaje con gomas

Lección 4: Atar ruedas

Subunidad 13: Premontaje:

Lección 1: Premontaje rueda

Subunidad 14: Montaje:

Lección 1: Mas lijado

Lección 2: Lima para servo

Lección 3: Fijar ruedas

Lección 4: Fijar otra rueda

Lección 5: Analisis

Lección 6: Ubicacion componentes

Lección 7: Alimentacion

Subunidad 15: Tapa:

Lección 1: Retirar soporte

Lección 2: Lijado

Lección 3: Limado

Subunidad 18: Anexo_aceleracion_servomotor:

Lección 1: Puesta en movimiento

Lección 2: Menos velocidad

Lección 3: Bucle for

Subunidad 19: Fritzing:

Lección 1: Servo

Lección 2: Ejercicios LEDs

Lección 3: Fotorresistor

Lección 4: Resistencia y buzzer

Lección 5: Descargar ultrasonidos

Lección 6: Ultrasonidos

Lección 7: Buzzer

Subunidad 20: Fritzing_Arduino_Proyecto_Curso:

Lección 1: Buzzer

Lección 2: LED

Lección 3: Fotorresistor

Lección 4:

Lección 5: Servo 1

Publicado el Deja un comentario

Desarrollo de proyectos gráficos y mockups con Photoshop

La presentación es un factor muy importante del desarrollo de cualquier proyecto. Nos preocupamos de generar el mejor material gráfico para presentar correctamente cualquier tipo de proyecto.

Utilizamos tecnologías tanto 2d cómo 3D que nos permiten generar imágenes y fotomontajes realistas, mediante los cuales pueden realizarse simulaciones del aspecto final de un producto o servicio

Publicado el Deja un comentario

Desarrollo de presentaciones 3D para el sector cerámico

Utilizando las últimas tecnologías en cuanto a generación de presentaciones 3D, creamos completas simulaciones fotorrealistas que nos permiten ofrecer a nuestros clientes una amplia gama de simulaciones de producto.

Gracias a estas imágenes simuladas en tres dimensiones, nuestros clientes pueden evaluar sus diseños de una forma mucho más rápida y precisa, ahorrando tiempos y costes en el desarrollo de prototipos reales

Publicado el Deja un comentario

Modelado 3D de proyectos arquitectónicos

Para aquellos proyectos arquitectónicos de interiorismo en los cuales se dispone únicamente de vistas bidimensionales de planta o alzado, ofrecemos una serie de servicios del modelado arquitectónico tridimensional, a través de los cuales nuestros clientes pueden obtener las volumetrías digitales necesarias para poder construir en base a ellas.

Ofrecemos todo tipo de servicios, desde el modelado de volúmenes tridimensionales para que luego nuestros clientes puedan continuar trabajando con ellos, hasta servicios integrales en los cuales desarrollamos el proyecto desde el principio hasta el final, ofreciendo completas presentaciones tanto en formato de imagen, como en formato de vídeo animado, como en formato interactivo realidad Virtual

Publicado el Deja un comentario

Dia de aviones

Cuando acaba un viaje Del trabajo, llega el momento de volver a casa. Y si el trabajo se ha realizado lejos, lo más probable es acabar pasando un día entero de aeropuerto en aeropuerto.

Sin embargo, aunque las ganas de estar de vuelta en casa son muchas, en ocasiones hay que disfrutar del camino mientras se llega al destino

El ambiente de los aeropuertos es único, y cada aeropuerto tiene su encanto. Los días de aeropuerto son extraños, pero a la vez, son especiales.

Publicado el Deja un comentario

Grabando trailers de los nuevos cursos en Linkedin

Dentro de poco estarán disponibles los nuevos cursos que he grabado para LinkedIn Learning.

Mientras ese momento llega, estoy finalizando las grabaciones con el rodaje de los tráilers correspondientes a cada uno de los cursos.

Cada vez que veis un tráiler mío en la primera parte del curso, realmente, probablemente os estáis perdiendo mucho de lo que ocurre fuera de la cámara, así que quiero compartir esta imagen para que, de alguna manera, podéis vivir el momento de la forma más parecida a como yo lo vivo.

Gracias a todos los miembros de LinkedIn Learning por hacer que el trabajo de los formadores sea lo más ameno y lo más productivo posible

Publicado el Deja un comentario

De visita por Linkedin para grabar nuevos cursos

Ya estoy de nuevo en las instalaciones de LinkedIn Learning en la ciudad austriaca de Gratz.

Este año han estrenado unas fabulosas nuevas instalaciones, que incluyen un rincón mítico en el cual es prácticamente obligado fotografiarse.

Quiero compartir con vosotros esta fotografía, realizada por el gran Tommy, para dar fe de que tengo el inmenso placer de poder colaborar con LinkedIn Learning en el desarrollo de acciones formativas online para su portal

Publicado el Deja un comentario

De viaje hacia Frankfurt

En el inicio de un viaje de trabajo es normal tener que coger unos cuantos vuelos.

El inicio de cualquier proyecto siempre es emocionante, y probablemente no hay mejor forma de iniciarlo que con un vuelo.

En este caso, me dirijo hacia las oficinas en Austria de LinkedIn Learning para un nuevo proyecto formativo consistente en la realización de una serie de cursos de carácter tecnológico que saldrán publicados en breve

Publicado el Deja un comentario

Desarrollo de aplicaciones de realidad virtual

Desarrollamos presentaciones, aplicaciones y proyectos utilizando las últimas tecnologías de realidad Virtual disponibles en el mercado.

Estas tecnologías permiten a nuestros clientes, en prácticamente cualquier sector, previsualización tanto productos como servicios, y de esta forma, ahorrar costes y ahorrar tiempo de desarrollo.

La realidad Virtual es uno de los elementos clave en el futuro tecnológico a medio plazo en nuestro país, y por tanto es de vital importancia utilizar estas tecnologías para asegurar la competitividad de nuestros clientes

Publicado el Deja un comentario

Conferencia en la Heroes Comic Con

El fin de semana pasado estuve en la feria de muestras de Valencia, participando en una conferencia divulgativa para dar a conocer las metodologías que hay detrás de la parte de programación en cualquier videojuego.

Tuve la suerte de contar con un grupo de alumnos del master que actualmente estoy impartiendo, que permitieron que la conferencia tuviera varios puntos de vista, no solo el mío, sino también el de aquellas personas que en estos momentos están en pleno proceso de aprendizaje de las tecnologías necesarias para poder programar correctamente cualquier tipo de videojuego

Publicado el Deja un comentario

Desarrollo de proyectos de realidad virtual

Desarrollamos proyectos de realidad virtual de realidad aumentada utilizando el estado del arte de la tecnología. Las presentaciones de realidad virtual permite a nuestros clientes generar contenido vanguardista y ahorrar tiempos y costes de desarrollo, simulando el estado del proyecto final y pudiendo realizar correcciones tempranas.

Publicado el Deja un comentario

Nuevo curso en Linkedin Learning: Modelado y animación de personajes 3D

Ya está publicado el último curso que he realizado hasta la fecha para Linkedin Learning, en el que muestro los procesos necesarios para modelar, preparar, animar y poner pelo a un personaje.

 

A través de este curso los alumnos pueden aprender las metodologías necesarias para animar sus propios personajes usando el programa 3D Studio MAX

Publicado el Deja un comentario

Diseño generativo aplicado al sector de la iluminación

El diseño generativo, asociado con el diseño basado en el machine learning y la inteligencia artificial, es clave para entender el futuro de la producción industrial.

 

El diseño generativo permite que, una vez que se han realizado una serie de restricciones de base, el sistema informático pueda generar una serie de variaciones y evoluciones de forma automática en el diseño del producto.

Esto permite obtener un número muy amplio de diseños de forma automatizada, aumentando tanto la productividad como la calidad del producto final.

 

Gracias a los servicios que ofrecemos, que combinan el diseño con la inteligencia artificial, podemos ofrecer a nuestros clientes soluciones que les permitirán estar al día con la aplicación de las nuevas tecnologías de inteligencia artificial a su empresa

Publicado el Deja un comentario

Diseño paramétrico y generativo aplicado al sector de la iluminación

El diseño generativo, asociado con el diseño basado en el machine learning y la inteligencia artificial, es clave para entender el futuro de la producción industrial.

 

El diseño generativo permite que, una vez que se han realizado una serie de restricciones de base, el sistema informático pueda generar una serie de variaciones y evoluciones de forma automática en el diseño del producto.

Esto permite obtener un número muy amplio de diseños de forma automatizada, aumentando tanto la productividad como la calidad del producto final.

 

Gracias a los servicios que ofrecemos, que combinan el diseño con la inteligencia artificial, podemos ofrecer a nuestros clientes soluciones que les permitirán estar al día con la aplicación de las nuevas tecnologías de inteligencia artificial a su empresa

Publicado el Deja un comentario

Representación 3D de proyectos de joyería

Aplicamos las últimas tecnologías disponibles en cuanto a representación tridimensional, para generar prototipos visuales de proyectos en el sector de la joyería

 

estos prototipos nos permiten realizar evaluaciones y modificaciones en fases bastante iniciales de un proyecto coma pudiendo realizar correcciones a tiempo, y ahorrando por tanto costes y tiempos de desarrollo

 

trabajamos con los motores de representación más punteros del mercado para generar representaciones completamente fotorealistas, en ocasiones indistinguibles con respecto al producto final

Publicado el Deja un comentario

Desarrollo de productos industriales

Desarrollamos productos industriales utilizando tecnologías generativas y aplicando las últimas técnicas disponibles en cuanto a la aplicación de la inteligencia artificial para la generación de propuestas genéticas

 

gracias a la inteligencia artificial, nuestros sistemas generan multitud de variaciones de un diseño y seleccionan automáticamente las mejores versiones coma para de esta manera coma generar un número de evoluciones en un tiempo muy concreto que, a un ser humano, le resultarían muy difíciles de generar

Publicado el Deja un comentario

Creación de modelos de joyería usando software generativo

Aplicamos las últimas tecnologías disponibles en cuanto a software generativo e inteligencia artificial para aplicarlo a diferentes sectores, como por ejemplo en este caso el sector de la joyería

 

gracias a este tipo de tecnologías, podemos parametrizar las condiciones de entrada de un proyecto, y obtener un número elevado de propuestas que, el propio software, es capaz de evaluar y validar obteniendo de esta forma el diseño ideal en el menor tiempo posible

 

las tecnologías relacionadas con la inteligencia artificial permiten a nuestros clientes ser más productivos y obtener mejores diseños en menor tiempo, reduciendo los costes, y maximizando su inversión

Publicado el Deja un comentario

Impartición de un taller de robótica en la UPV

Esta mañana he estado impartiendo un taller de robótica en la Escuela Técnica Superior de Ingeniería del diseño en la Universidad Politécnica de Valencia

 

el objetivo del taller era mostrar las tecnologías de prototipado electrónico e impresión 3D disponibles, así como sus ventajas y sus bajos costes, para que los alumnos del grado de diseño industrial puedan sacar partido de estas tecnologías e incorporarlas a sus proyectos

 

a lo largo del primer semestre, los alumnos estarán desarrollando diferentes proyectos basados en estas tecnologías, para tener una perspectiva más completa, más allá de utilizar únicamente recursos basados en el diseño industrial, sino también incorporar elementos de otras disciplinas

Publicado el Deja un comentario

Grabación de nuevos cursos en Linkedin Learning

Esta última semana de agosto y la primera semana de septiembre estoy grabando una serie de nuevos cursos en las oficinas de Linkedin learning, en Austria punto

 

al finalizar cada una de las grabaciones, grabamos un completo tráiler en el cual explico y resumo cuáles son los objetivos y los contenidos que se van a mostrar en cada uno de los cursos

 

el momento de grabar cada uno de estos vídeos, cada uno de estos trailers, es bastante excitante y como puede verse en la imagen, bastante espectacular

Publicado el Deja un comentario

Montaje de máquinas de impresión 3D

Esta semana estoy en el Departamento de Proyectos en la ingeniería en la Universidad Politécnica de valencia, ayudando en el montaje de una impresora 3D de gama baja

 

el objetivo de esta impresora es mostrar a los alumnos del grado de diseño industrial de la Escuela Técnica Superior de Ingeniería del diseño, las tecnologías que tienen a su alcance, y el bajo coste que puede suponer montar una de estas impresoras y los beneficios que pueden encontrar en términos de poder imprimir sus propios diseños

Publicado el Deja un comentario

Testeando aplicaciones de realidad virtual

Las aplicaciones de realidad virtual no sólo están basadas en el uso de gafas estereoscópicas, sino que también incluyen dos mandos, que nos permiten interactuar de una forma mucho más íntima con el mundo 3D en el que nos movemos en ese tipo de presentaciones

 

estos mandos son de una importancia vital, ya que son nuestras manos dentro de la realidad virtual, y nos permiten no solo ser espectadores, si no interactuar realmente con el entorno virtual que nos rodea

 

en esta foto un alumno me ha capturado en el momento en el que estaba mostrando cómo realizar ese tipo de interacciones en una presentación de realidad virtual

Publicado el Deja un comentario

Creación de interfaces de usuario en realidad virtual

En el momento en el que empezamos a trabajar con presentaciones de realidad virtual, muchas veces echamos de menos metodologias de interacción que nos permitan introducir información, y por tanto, controlar el entorno con el que estamos trabajando

 

por ejemplo, muchas veces acabamos echando en falta dispositivos de entrada tales como teclados y ratones

 

sin embargo, nuestro objetivo no es replicar estas interfaces de entrada pensadas para un escritorio, sino diseñar interfaces de usuario completamente innovadoras y que exploten al máximo el potencial y las posibilidades que nos brindan los nuevos medios inmersivos e interactivos

 

en este vídeo y en esta fotografía muestra un ejemplo del desarrollo de una interfaz de usuario basada en algo parecido a la paleta de un pintor, mediante la cual los usuarios pueden interactuar y pueden realizar elecciones en un mundo virtual de una forma muy sencilla

Publicado el Deja un comentario

Desarrollos con realidad aumentada

Entre la realidad virtual y la realidad mixta, encontramos un paso intermedio consistente en el desarrollo de proyectos de realidad aumentada

 

la Realidad Aumentada permite a nuestros clientes mezclar presentaciones o elementos en 3d, con formas y fondos de la vida real

 

es de esta forma como la propia realidad, se ve aumentada y mejorada incluyendo elementos tridimensionales virtuales qué tal forma que la parte virtual obtiene un retorno mucho más rápido, al verse completamente integrada con la parte real, en el mismo momento

 

estos tipos de presentaciones permiten a nuestros clientes evaluar sus diseños, y realizar correcciones en fases tempranas de desarrollo, con el consiguiente ahorro en costes y en tiempos

Publicado el Deja un comentario

Aplicación de la realidad virtual al sector de los videojuegos

Las tecnologías de realidad virtual no solo tienen aplicación en el campo empresarial, sino que también pueden ser aplicadas a campos relacionados con el ocio, como por ejemplo el desarrollo de videojuegos y otros tipos de aplicaciones interactivas orientadas al sector lúdico

 

esta mañana he estado desarrollando un proyecto en el cual realizaba una integración de las tecnologías de realidad virtual, con un juego basado en la aniquilación de zombies en una nave espacial futurista

 

es una pena que la imagen no haga justicia al efecto inmersivo y tridimensional que hemos podido encontrar durante el desarrollo del proyecto

Publicado el Deja un comentario

Desarrollo de presentaciones interactivas con realidad virtual

Utilizando el estado del arte de la tecnología podemos generar presentaciones vanguardistas de realidad virtual.

 

estás presentaciones permiten a nuestros clientes interactuar con sus productos mucho antes de que hayan sido fabricados, siendo capaces, de esta forma, de generar un número mucho mayor del que anteriormente eran capaces de prototipos y soluciones, ide, en definitiva, ahorrar costes y tiempos de desarrollo

Publicado el Deja un comentario

Reconocimiento de gestos de mano con Leap Motion

Esta mañana hemos estado testeando el uso de un dispositivo llamado Leap Motion, que nos permite interactuar directamente con los 10 dedos de nuestras manos en las aplicaciones de realidad virtual y realidad aumentada que podemos desarrollar

 

este dispositivo tiene una relación entre prestaciones y precio bastante beneficiosa, ya que por menos de 100 € podemos introducir nuestras manos dentro de los proyectos de realidad virtual y realidad aumentada, y de esta forma, podemos obtener una interacción con el mundo virtual mucho más precisa y mucho más basada en lo que podríamos realizar en la vida real

Publicado el Deja un comentario

Desarrollo de aplicaciones de realidad virtual

En nuestra empresa desarrollamos aplicaciones de realidad virtual, que permiten en nuestros clientes visualizar sus proyectos de una forma mucho más inmersiva e interactiva

 

aplicando el estado del arte de la tecnología, generamos soluciones concretas y eficientes utilizando los mínimos recursos posibles, y obteniendo el máximo resultado posible

Publicado el Deja un comentario

Desarrollo de productos industriales

En nuestra empresa desarrollamos productos industriales mediante la integración de tecnologías basadas en el machine learning, la inteligencia artificial, y en el uso del Big Data

 

gracias a estas tecnologías podemos innovar en cuanto a los procesos tradicionales de desarrollo de productos industriales, aplicando los beneficios de la inteligencia artificial para la generación automática de un elevado número de propuestas, y de su validación de forma automatizada, creando diseños genéticos que permiten a nuestros clientes obtener un mayor número de variaciones, al tiempo que una mayor eficiencia y una mucha mejor optimización