
Del básico al intermedio: Directiva Include
Introducción
El contenido expuesto aquí tiene un propósito puramente didáctico. En ningún caso debe considerarse como una aplicación final cuyo propósito no sea el estudio de los conceptos mostrados.
En el artículo anterior, "Del básico al intermedio: Comandos BREAK y CONTINUE", nos centramos principalmente en entender cómo controlar el flujo de ejecución dentro de bucles que hacen uso de los comandos WHILE y del dúo DO WHILE. Sin embargo, aunque imagino que tú, estimado lector, ya estés lo suficientemente preparado para que podamos explicar el bucle con el comando FOR, aquí haré una breve pausa en el tema de los bucles. Esto se debe a que es bueno tomar un descanso explorando otros temas antes de continuar con más comandos de control de flujo.
Así, en este artículo, veremos un tema que podrá ayudarte bastante. Al menos, una vez que se haya explicado, podré comenzar a mostrar códigos un poco más elaborados. Dado que, hasta este momento, ha sido bastante desafiante para mí crear códigos sin utilizar ciertos recursos disponibles en MQL5. Aunque algunos de ustedes puedan pensar que ha sido fácil para mí, lo cierto es que escribir códigos sin emplear ciertos recursos resulta muy desafiante. Pero ahora, añadiremos algunos elementos a la lista de lo que ya podemos hacer.
El recurso al que me refiero son las directivas de compilación. Sin estas directivas, mucho de lo que podemos lograr queda bastante limitado, obligándonos a escribir mucho más código del que realmente sería necesario en un entorno de programación real.
Las directivas de compilación, contrariamente a lo que muchos podrían pensar, no hacen el código más confuso. Al contrario. Su objetivo principal es simplificar, agilizar y facilitar el manejo y la modificación del código. El problema es que muchos principiantes las ignoran o no se esfuerzan por aprender a utilizarlas de manera adecuada. Quizás porque algunas lenguas de programación no cuentan con este recurso en su repertorio. Algunos ejemplos de lenguas que no poseen directivas de compilación son JavaScript y Python. Aunque son bastante populares entre programadores ocasionales, no son adecuadas para desarrollar ciertos tipos de aplicaciones. Sin embargo, aquí el objetivo no es hablar de dichas lenguas, sino de MQL5. Así que empecemos con lo que será el primer tema de este artículo.
¿Por qué usar directivas de compilación?
Aunque las directivas de compilación presentes en MQL5 son adecuadas para la mayoría de los casos, en ocasiones siento que faltan otras directivas. Esto ocurre porque MQL5 proviene esencialmente de una modificación muy bien elaborada de C/C++. Sin embargo, en C/C++ existen algunas directivas que no están presentes en MQL5. Una de estas directivas es #ifdef, que, aunque parezca poco interesante, en ciertos momentos nos ayuda mucho a controlar ciertas partes de la versión en la que estamos trabajando.
No obstante, aunque esta directiva no esté presente en MQL5, al menos no hasta el momento en que escribo este artículo, su ausencia no será un problema aquí. Solo mencioné este detalle para que tú, estimado lector, que quizás en el futuro te intereses en aprender C/C++, sepas que hay ciertos aspectos que diferencian C/C++ de MQL5. Aunque todo, o al menos la mayor parte de lo que se muestra aquí, también puede servir como una vía de acceso a C/C++.
Básicamente, las directivas de compilación sirven para dos propósitos, dicho de manera muy resumida. El primero es dirigir la implementación hacia un modelo de código más eficiente. El segundo propósito es permitir que crees diferentes versiones de un mismo código sin borrar ni perder fragmentos anteriores.
Sé que para muchos de ustedes estas ideas pueden parecer absurdas. Esto se debe a que los programadores principiantes tienden a borrar un fragmento de código para intentar crear uno nuevo. Esto, en un esfuerzo por corregir posibles errores o mejorar la manera en que se realizan ciertas factorizaciones.
Sin embargo, este tipo de práctica solo es necesaria en lenguajes donde NO EXISTEN directivas de compilación. Los lenguajes que permiten y cuentan con este recurso pueden manejar diversas mini versiones de un mismo código al mismo tiempo. Y la forma de seleccionar entre una versión y otra es, precisamente, mediante el uso de directivas, de manera inteligente y bien organizada.
Como parte de esta organización exige cierta experiencia por parte del programador, aquí y en este preciso momento, empezaremos desde el principio. Es decir, asumiré que tú, mi querido y estimado lector, NO sabes absolutamente nada sobre cómo trabajar, manejar e implementar un código que haga uso de directivas de compilación.
Sin embargo, a medida que se publiquen los próximos artículos, te iré mostrando poco a poco cómo integrar nuestras actividades relacionadas con las directivas de compilación. Muy probablemente no escribiré un artículo enfocado exclusivamente en este tema específico. Este simplemente busca introducir el tema, de modo que puedas tener una idea general de qué es una directiva de compilación.
Muy bien, habiendo dado esta introducción general al tema, comencemos revisando la directiva más común en los códigos MQL5. Pero para ello, avancemos al siguiente tema.
Directiva #INCLUDE
Muy probablemente, esta será la directiva de compilación que tú, estimado lector, más encontrarás en los códigos, especialmente en MQL5 y en los estilos C/C++. ¿Por qué ocurre esto? El motivo es que la mayoría, por no decir todos, los programadores más experimentados NO prefieren colocar todo en un único código. Normalmente, y con el tiempo lo entenderás, los programadores experimentados dividen sus códigos en pequeños bloques. Estos, con el tiempo, terminan configurando lo que sería una biblioteca de funciones, procedimientos, estructuras y clases, todos organizados de manera completamente lógica. Esto permite que la programación, incluso de códigos nuevos e inéditos, sea algo extremadamente rápido de realizar, con una cantidad mínima de modificaciones necesarias para adaptar el código original, ya catalogado desde hace tiempo, a un nuevo proyecto.
Y tú, mientras tanto, escribiendo código constantemente para hacer siempre las mismas cosas.
Pero organizar tus códigos de modo que aproveches esta directiva es algo que no voy a enseñarte cómo hacer. En realidad, NADIE te enseñará cómo hacerlo, ya que este tipo de cosas solo tiene sentido cuando quien mantiene dichos códigos realiza una selección cuidadosa y meticulosa de dónde quedará cada cosa. Sin embargo, aunque no te enseñaré cómo organizarlo, sí puedo explicarte cómo acceder a los códigos que has creado con tanto esmero y dedicación. Ese es precisamente el objetivo de esta directiva en particular: permitirte acceder a las cosas de manera natural y práctica.
Aquí no existe un flujo de ejecución, aunque hay detalles que deben observarse. Sin embargo, los abordaremos poco a poco para que sean comprendidos de manera bastante natural por cada uno de ustedes.
Primero, tomaremos uno de los códigos vistos en los artículos anteriores. Esto hará que lo que veremos aquí sea más natural. Para ello, utilizaremos y configuraremos un pequeño código inicial. Este puede verse a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. ulong value; 07. 08. Print("Factorial of 5: ", Factorial(5)); 09. Print("Factorial of 3: ", Factorial(3)); 10. Print(One_Radian()); 11. do 12. { 13. value = Tic_Tac(); 14. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", value); 15. }while (value < 3); 16. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac(true)); 17. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac()); 18. } 19. //+------------------------------------------------------------------+ 20. double One_Radian() 21. { 22. return 180. / M_PI; 23. } 24. //+------------------------------------------------------------------+ 25. ulong Tic_Tac(bool reset = false) 26. { 27. static ulong Tic_Tac = 0; 28. 29. if (reset) 30. Tic_Tac = 0; 31. else 32. Tic_Tac = Tic_Tac + 1; 33. 34. return Tic_Tac; 35. } 36. //+------------------------------------------------------------------+ 37. ulong Factorial(uchar who) 38. { 39. static uchar counter = 0; 40. static ulong value = 1; 41. 42. if (who) who = who - 1; 43. else 44. { 45. counter = 0; 46. value = 1; 47. } 48. while (counter < who) 49. { 50. counter = counter + 1; 51. value = value * counter; 52. }; 53. while (counter > who) 54. { 55. value = value / counter; 56. counter = counter - 1; 57. }; 58. counter = counter + 1; 59. return (value = value * counter); 60. } 61. //+------------------------------------------------------------------+
Código 01
Tú, estimado lector, debes obligatoriamente ser capaz de entender este código 01. Este es un requisito previo para que podamos continuar a partir de aquí. Si no logras comprender este código, por favor, detente en este momento y regresa a los artículos anteriores. Esto se debe a que este código es muy simple y no debería, de ninguna manera, ser algo confuso o difícil de entender.
Bien, al ejecutarlo, este código generará la siguiente salida en el terminal de MetaTrader 5.
Imagen 01
Esto es algo que estamos haciendo únicamente para verificar si realmente funciona. Como podemos notar claramente que funciona, podemos empezar a hablar sobre cómo utilizar la directiva de compilación aquí. Quizás debería haber comenzado con otra directiva, pero está bien. Dado que la directiva #include es mucho más utilizada que todas las demás, no tiene mucho sentido empezar con otra. Así que sigamos adelante.
La primera cosa que debes entender, antes de hacer cualquier otra cosa, es cómo decidirás dividir las cosas. Puede parecer algo trivial, pero no lo es. Si no diseñas un método que sea adecuado y perfectamente utilizable para ti, con el tiempo terminarás enfrentando serios problemas al crear nuevos códigos. Sin embargo, si desarrollas una forma que para ti sea adecuada, lograrás avanzar mucho.
Como aquí el objetivo es puramente didáctico, haremos lo siguiente: dividiremos las cosas en tres archivos diferentes. Cada uno contendrá una función o procedimiento que originalmente aparece en este código 01.
Con esto en mente, podrías pensar: "Ok, voy a crear los archivos entonces". Pero este no es el segundo paso que debes dar, estimado lector. De hecho, hay un paso previo que debes completar antes de hacer eso. Este segundo paso consiste en responder la siguiente pregunta: ¿En qué directorio colocaré los archivos que serán creados? Espera un momento. ¿El directorio no debería ser el directorio include? Esta es una cuestión mucho más personal que cualquier otra cosa. Esto se debe a que, no siempre el mejor lugar será el directorio include. Si no tienes claro de qué estoy hablando, basta con ir a la carpeta de MQL5 a través de MetaEditor, como se muestra en la imagen a continuación.
Imagen 02
Al hacer esto, verás una carpeta llamada include dentro del directorio MQL5. Este es el directorio predeterminado para los archivos del tipo que estaremos creando, comúnmente conocidos como archivos de encabezado. Sin embargo, como mencioné anteriormente, no siempre es la mejor elección. Dependiendo del proyecto o del objetivo que pretendas alcanzar, colocar todos tus archivos de encabezado en el directorio include podría terminar perjudicándote. Esto ocurre porque versiones ligeramente diferentes de un mismo procedimiento o función podrían entrar en conflicto con otras versiones que, posiblemente, estén o deban estar dentro de esa carpeta include.
No obstante, muchos podrían cuestionar esta idea diciendo algo como: "¿No podríamos crear subdirectorios para organizar mejor nuestros archivos de encabezado?". Sí, esta es, de hecho, una de las prácticas más comunes. Sin embargo, incluso utilizando subdirectorios dentro de la carpeta include, hay momentos en los que esto no es adecuado.
Antes de que algunos comiencen a preocuparse, sí te mostraré cómo puedes hacer esto, estimado lector. Esto con el propósito de que organices tus códigos de la mejor manera posible. Como dije antes, nadie puede enseñarte exactamente cómo hacerlo, pero, conociendo las opciones disponibles, podrás crear tu propia organización.
Por ahora, hagamos algo completamente diferente. Crearemos un subdirectorio dentro de la carpeta Scripts. Este subdirectorio contendrá cada una de las funciones vistas en el código 01. Pero, para separar las cosas adecuadamente, abordemos esto en partes, comenzando con lo que llamaremos la solución número 1.
Solución número 1
La primera solución para separar las funciones vistas en el código 01 consiste en colocar cada una en un archivo de encabezado. Estos archivos estarán ubicados en una carpeta dentro del directorio Scripts. Un detalle importante: siempre procura utilizar la extensión MQH para los archivos de encabezado que crees. De esta manera, será más fácil identificar de qué se trata solo observando el explorador de archivos del sistema operativo. Dicho esto, hacemos la división, y esta separa los archivos de manera que cada uno contenga lo siguiente.
1. //+------------------------------------------------------------------+ 2. #property copyright "Daniel Jose" 3. //+------------------------------------------------------------------+ 4. double One_Radian() 5. { 6. return 180. / M_PI; 7. } 8. //+------------------------------------------------------------------+
Archivo 01
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. ulong Tic_Tac(bool reset = false) 05. { 06. static ulong Tic_Tac = 0; 07. 08. if (reset) 09. Tic_Tac = 0; 10. else 11. Tic_Tac = Tic_Tac + 1; 12. 13. return Tic_Tac; 14. } 15. //+------------------------------------------------------------------+
Archivo 02
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. ulong Factorial(uchar who) 05. { 06. static uchar counter = 0; 07. static ulong value = 1; 08. 09. if (who) who = who - 1; 10. else 11. { 12. counter = 0; 13. value = 1; 14. } 15. while (counter < who) 16. { 17. counter = counter + 1; 18. value = value * counter; 19. }; 20. while (counter > who) 21. { 22. value = value / counter; 23. counter = counter - 1; 24. }; 25. counter = counter + 1; 26. return (value = value * counter); 27. } 28. //+------------------------------------------------------------------+
Archivo 03
Un detalle importante: una vez realizada esta división, la decisión sobre dónde quedarán las cosas depende de ti, así como también los nombres de cada archivo. Aquí no hay ningún tipo de imposición. Eres libre de hacer tus propias elecciones.
Ahora que los códigos han sido extraídos del código 01 y colocados en archivos separados, tendrás como resultado un código similar al que se muestra a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. void OnStart(void) 05. { 06. ulong value; 07. 08. Print("Factorial of 5: ", Factorial(5)); 09. Print("Factorial of 3: ", Factorial(3)); 10. Print(One_Radian()); 11. do 12. { 13. value = Tic_Tac(); 14. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", value); 15. }while (value < 3); 16. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac(true)); 17. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac()); 18. } 19. //+------------------------------------------------------------------+
Código 02
Genial, parece mucho más simple que el código 01. Es cierto, estimado lector. Sin embargo, si intentas compilar este código 02, obtendrás una gran cantidad de errores reportados por el compilador. Estos errores, que puedes observar en la imagen a continuación, indican que el compilador no logró interpretar el código.
Imagen 03
Bueno, en realidad no es que el compilador no haya entendido el código. El problema es que el compilador NO SABE cómo resolver las llamadas a los procedimientos y funciones que aparecen en el código. ¿Cómo es eso? A diferencia de lo que muchos piensan o imaginan sobre una lengua de programación, en realidad existen dos componentes principales en ella. El primero se conoce como biblioteca estándar. Esta biblioteca define las funciones, procedimientos, palabras reservadas, constantes, entre otros elementos que utilizamos para crear lo que sería el código a nivel de usuario.
Tú, como programador que utilizas cualquier lenguaje, NO PUEDES modificar cómo funciona la biblioteca estándar. Pero sí puedes usar lo que está definido en ella para crear tus propias soluciones. Todo lo que pertenece a la biblioteca estándar puede ser utilizado sin necesidad de ninguna operación especial. Sin embargo, cualquier cosa que esté fuera de esta biblioteca deberá ser añadida explícitamente al código. Esto permite que el compilador sepa cómo resolver cada una de las llamadas que surjan. Por eso, cuando intentas compilar el código 02, que aunque se parece al código 01, no puedes hacerlo.
Para lograrlo, deberás indicar al compilador qué archivos deben incluirse en la compilación. Es por eso que esta directiva se llama directiva de compilación y tiene un nombre bastante sugestivo: #include. Es decir, incluye este archivo durante la compilación de este código. ¿Lo comprendes, estimado lector?
Si realmente lograste comprender esto, serás capaz de hacer cosas que antes no podías. Incluso cuando intentabas aprender programación, había conceptos que parecían carecer de un sentido claro y real. Pero hablaremos de eso en otro momento. No quiero desorientarte presentándote una gran cantidad de información de golpe. Mi objetivo es que comprendas y asimiles adecuadamente lo que se explica y muestra en cada uno de estos artículos.
Bien, si el código 02 no puede ser compilado precisamente porque el compilador no sabe cómo acceder a la información necesaria, ¿cómo podemos resolver este problema? ¿Deberíamos ir a los archivos que creamos hace un momento, copiar y pegar cada una de las funciones o procedimientos en el código 02, para que vuelva a parecerse al código 01? Después de todo, si el código 01 podía ser compilado, eso indicaba que estaba correcto. Pero esta solución no parece tener mucho sentido. He visto otros códigos funcionando sin necesidad de copiar y pegar fragmentos completos dentro del código final. Ahora me he quedado con curiosidad. ¿Cómo resolver este problema? Esta es la parte fácil, estimado lector. Basta con que crees algo parecido a lo que se muestra en el código a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #include "Tutorial\File 01.mqh" 05. #include "Tutorial\File 02.mqh" 06. #include "Tutorial\File 03.mqh" 07. //+------------------------------------------------------------------+ 08. void OnStart(void) 09. { 10. ulong value; 11. 12. Print("Factorial of 5: ", Factorial(5)); 13. Print("Factorial of 3: ", Factorial(3)); 14. Print(One_Radian()); 15. do 16. { 17. value = Tic_Tac(); 18. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", value); 19. }while (value < 3); 20. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac(true)); 21. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac()); 22. } 23. //+------------------------------------------------------------------+
Código 03
Ahora viene la parte interesante. Cuando intentes compilar este código 03, obtendrás una respuesta similar a la que se observa a continuación.
Imagen 04
Es decir, ¡éxito! Pero, ¿cómo es posible? El motivo se encuentra en las líneas cuatro, cinco y seis presentes en este código 03. Estas líneas pueden colocarse en cualquier parte del código. Sin embargo, por razones de organización, normalmente las ponemos al principio. Existen situaciones en las que pueden aparecer en otros lugares del código, pero son casos bastante raros y responden a motivos muy específicos, lo cual no viene al caso en este momento. Aun así, es algo maravilloso el simple hecho de poder organizar las cosas en un formato mucho más limpio y práctico.
Sin embargo, hay un detalle aquí, y es muy importante que lo comprendas, al menos en lo más básico. En otros artículos exploraremos esto de una forma más profunda. Se trata de cómo estamos declarando cada una de las directivas #include presentes en este código 03.
En este momento, no voy a explicarlo. Prefiero que consultes la documentación. Esto se debe a que, si intento explicarlo ahora mismo, es posible que no logres entender por qué se hace de la forma en que aparece en este código 03. Peor aún, podrías terminar más confundido que aclarado sobre los motivos de que la declaración aparezca de una forma en algunos casos y de otra en otros.
En la documentación, puedes buscar esto bajo el título: Inclusión de archivos (#include). Pero quienes ya me han acompañado durante un tiempo saben perfectamente que hay un motivo detrás de la forma en que se declaran las líneas cuatro, cinco y seis en el código 03.
De cualquier manera, cuando ejecutes el código 03, obtendrás el mismo resultado que se muestra en la imagen 01. Ahora vamos al segundo tipo de solución. Pero para separarlo de esta primera, avancemos a un nuevo tema.
Solución número 2
Esta segunda solución sigue el principio de la usabilidad. Es decir, creas algo que expande la propia capacidad de MQL5 para generar nuevos códigos o para hacerlo de manera más rápida. No es raro ver a otros programadores distribuyendo archivos de encabezado que ya están presentes en la instalación de MetaTrader 5, pero que han sido modificados de alguna manera. Personalmente, considero que estas distribuciones son bastante válidas, ya que muchas veces algunas de estas modificaciones son muy interesantes. El problema surge en decidir dónde, estimado lector, colocarás estos archivos.
Esto se debe a que, periódicamente, MetaTrader 5 se actualiza. Si tienes uno de estos archivos de encabezado modificado, incluso si lo has hecho tú mismo, y resulta ser muy práctico y útil para lo que te gusta desarrollar, sería un gran error dejarlo en cualquier lugar. Si este archivo se encuentra dentro del directorio include de la carpeta MQL5, cuando MetaTrader 5 actualice sus datos, ese archivo podría ser sobrescrito. Si eso llegara a suceder, habrás perdido un archivo de encabezado excelente.
Sin embargo, existe una solución para este problema: darle un nuevo nombre al archivo de encabezado. También puedes utilizar lo que se mostró en el tema anterior. En ambos casos, funcionará. Sin embargo, en el caso anterior, al principio estarás limitado en algunos aspectos. Por ejemplo, será más difícil acceder a los archivos de encabezado que creaste fuera del directorio actual. No es que sea imposible, pero resulta un poco más complicado debido a algo que tendrás que hacer.
Precisamente por este motivo, cuando queremos usar un mismo archivo de encabezado en diversas aplicaciones completamente diferentes entre sí, es preferible colocarlo en un único lugar. En este caso, dentro del directorio include. Sin embargo, asegúrate siempre de realizar copias de seguridad de manera periódica. En cualquier caso, lo mejor es utilizar una herramienta de control de versiones.
En este caso, sugiero usar GIT. Puedes aprender más sobre esta herramienta leyendo otro artículo mío: GIT. ¿Pero qué es esto? Esto te evitará muchas molestias y horas de sueño perdido, siempre y cuando estudies y utilices la herramienta de forma adecuada.
Pero volvamos a nuestra cuestión. Ahora podemos usar los mismos archivos mostrados en el tema anterior y colocarlos dentro del directorio include. Con esto, podremos manejar dos versiones diferentes del mismo archivo: una que será fácilmente accesible por cualquier aplicación que desees crear, y otra accesible exclusivamente para una aplicación en particular. Para hacer esto evidente y demostrar que es posible, modificaremos uno de los archivos vistos en el tema anterior. En realidad, ahora tendremos dos versiones de ese archivo: una accesible únicamente para el código que estamos creando aquí y otra que podrá ser utilizada por cualquier otro código que quieras implementar. Este archivo se muestra a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. double One_Radian() 05. { 06. return 180. / M_PI; 07. } 08. //+------------------------------------------------------------------+ 09. double ToRadians(double angle) 10. { 11. return angle / One_Radian(); 12. } 13. //+------------------------------------------------------------------+ 14. double ToDegrees(double angle) 15. { 16. return angle * One_Radian(); 17. } 18. //+------------------------------------------------------------------+
Archivo 04
Como estamos comenzando desde lo básico, no mostraré ciertas cosas que podríamos hacer. Solo quiero enfocarme en cómo puedes trabajar con un archivo de encabezado. Así que ahora tenemos dos archivos que contienen dos versiones idénticas de una misma función, en este caso, la función One_Radians. Aunque por ahora parezca algo simple y trivial, que podría ser ignorado, a medida que profundicemos y mostremos nuevas cosas, veremos que este tipo de situación puede resultar útil. Pero todo a su debido tiempo.
Ahora queremos que este archivo 04 sea utilizado en lugar del archivo 01. Esto se debe a que contiene otras funciones que queremos usar, debido al código que se muestra a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #include "Tutorial\File 01.mqh" 05. #include "Tutorial\File 02.mqh" 06. #include "Tutorial\File 03.mqh" 07. //+------------------------------------------------------------------+ 08. void OnStart(void) 09. { 10. ulong value; 11. 12. Print("Factorial of 5: ", Factorial(5)); 13. Print("Factorial of 3: ", Factorial(3)); 14. Print(One_Radian()); 15. Print(ToRadians(90)); 16. do 17. { 18. value = Tic_Tac(); 19. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", value); 20. }while (value < 3); 21. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac(true)); 22. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac()); 23. } 24. //+------------------------------------------------------------------+
Código 04
Si intentas compilar este código 04, obtendrás como resultado la imagen que se muestra a continuación.
Imagen 05
Esto demuestra que hay un error aquí. Sin embargo, resolver este error es algo simple, aunque requiere de ti, como programador, un cierto nivel de atención. Esto se debe a que podrías estar trabajando con archivos de encabezado donde existen versiones diferentes de una función o procedimiento con el mismo nombre. Y esta es la parte complicada que necesitarás dominar por ti mismo. No hay una forma universal de explicar o enseñar cómo manejar esto, y el motivo es simple: todo depende de cómo te hayas organizado con el tiempo. Más allá de esta cuestión, y considerando que nuestro objetivo aquí es puramente didáctico, la solución es bastante sencilla y directa. De hecho, el error reportado se debe simplemente a la ausencia de la función que debería estar en la línea 15. Como esta función no existe en ninguno de los archivos de encabezado incluidos en el código 04, la compilación siempre fallará. Por eso, necesitamos decirle al compilador dónde se encuentra el archivo correcto que contiene el código necesario para que la línea 15 funcione. Para solucionarlo, simplemente cambiaremos el código al código 05, que se muestra a continuación.
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #include <Tutorial\File 01.mqh> 05. #include "Tutorial\File 02.mqh" 06. #include "Tutorial\File 03.mqh" 07. //+------------------------------------------------------------------+ 08. void OnStart(void) 09. { 10. ulong value; 11. 12. Print("Factorial of 5: ", Factorial(5)); 13. Print("Factorial of 3: ", Factorial(3)); 14. Print(One_Radian()); 15. Print(ToRadians(90)); 16. do 17. { 18. value = Tic_Tac(); 19. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", value); 20. }while (value < 3); 21. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac(true)); 22. Print(__FUNCTION__, " ", __LINE__, " Tic Tac: ", Tic_Tac()); 23. } 24. //+------------------------------------------------------------------+
Código 05
Observa que, aparentemente, el cambio fue muy pequeño. Sin embargo, esta modificación es deliberadamente mínima, sirviendo precisamente para mostrarte, estimado lector, que es necesario practicar y dedicarte a comprender cómo funcionan las cosas en la práctica. Al pedir al compilador que procese este código 05, el resultado será el que se muestra a continuación.
Imagen 06
Con esto, podemos notar que el archivo que estamos incluyendo en la línea cuatro está, de hecho, ubicado en el directorio include. En el anexo, podrás ver esto ilustrado, permitiéndote entender cómo deberían organizarse y estructurarse las cosas en la práctica. Como última cosa a mostrar en este artículo, observemos el resultado de la ejecución del código 05.
Imagen 07
Consideraciones finales
En este artículo, hemos aprendido a utilizar una de las directivas de compilación más comunes. Aunque nos enfocamos en un único aspecto, no fue, o mejor dicho, no es posible explicar todo lo que se puede hacer con esta directiva en un solo artículo. Incluso si redactáramos más artículos exclusivamente para explicar esta directiva, aún así no podríamos abordar ciertos aspectos. Esto se debe a que, para que alguien se convierta realmente en un buen programador, no basta con saber organizar un código para que produzca algún resultado. Es igualmente importante saber organizar tu propia identidad como programador, creando y catalogando en archivos de encabezado las partes más interesantes y útiles de los códigos que utilizas en tu día a día.
Aprender cómo hacer esto no es algo que nadie pueda enseñarte completamente. Es algo que solo podrás dominar con la práctica y con el tiempo. Sin embargo, es necesario dar el primer paso. Y este artículo tiene precisamente como objetivo ayudarte a dar ese primer paso. Espero que te haya resultado útil, estimado lector. En el próximo artículo, trataremos otro comando de control de flujo. ¡Nos vemos allí!
Traducción del portugués realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/pt/articles/15383
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso
Otra vez las tonterias del autor. Quote:" Pero hay algunas directivas en C/C++ que no están disponibles en MQL5. Una de ellas es #ifdef, que aunque pueda parecer poco interesante, en algunos momentos nos ayuda mucho a controlar ciertas partes de la versión en la que estamos trabajando. "
#ifdef ha estado en MQL4 y MQL5 durante mucho tiempo.
¿Por qué estás leyendo esto? 🤦♀️
Otra vez las tonterias del autor. Quote:" Pero hay algunas directivas en C/C++ que no están disponibles en MQL5. Una de ellas es #ifdef, que aunque pueda parecer poco interesante, en algunos momentos nos ayuda mucho a controlar ciertas partes de la versión en la que estamos trabajando. "
#ifdef ha estado en MQL4 y MQL5 durante mucho tiempo.
¿Por qué estás leyendo esto? 🤦♀️
¡¡¡Su apodo en la base es vDev - este es su tema!!!
¡¡¡¡Lekha - vamos a cuero cabelludo prueba!!!! )
El autor no está haciendo nada nuevo. Cita: " Pero en C/C++ hay algunas directivas que no están en MQL5. Una de ellas es el #ifdef, que, aunque pueda parecer desinteresante, en algunos puntos realmente nos ayuda a controlar ciertas partes de la versión en la que estamos trabajando. "
#ifdef está en MQL4 y MQL5 desde hace mucho tiempo.
Lo siento. Sin embargo, fue un error de mi parte referirme a la directiva en el texto. Mi intención era referirme a la directiva #if, porque la directiva #ifdef es el equivalente de la directiva #if defined presente en C y C++. Pero para generalizarlo aqui en MQL5, usamos #ifdef, que tambien esta presente en C y C++. De nuevo, el propósito será hacer referencia a la directiva #if, que tiene un propósito completamente diferente e incluso se puede utilizar para comprobar los valores de las definiciones. Pero debido a mi error de escritura, acabé poniendo #ifdef y no me di cuenta. Pido disculpas por este descuido por mi parte. 👍
Lo siento. Sin embargo, hubo un error por mi parte al referirme a la directiva en el texto. Mi propósito era hacer referencia a la directiva #if, porque la directiva #ifdef es el equivalente de la directiva #if defined, que está presente en C y C++. Pero para generalizarlo aqui en MQL5, usamos #ifdef, que tambien esta presente en C y C++. De nuevo, el propósito será hacer referencia a la directiva #if, que tiene un propósito completamente diferente e incluso se puede utilizar para comprobar los valores de las definiciones. Pero debido a mi error de escritura, acabé poniendo #ifdef y no me di cuenta. Pido disculpas por este descuido por mi parte. 👍
No pasa nada, cada uno tiene sus momentos )
¿Por qué estás leyendo esto? 🤦♀️
Me encontré con este artículo por accidente, el sitio lo dio en los enlaces.