English Русский 中文 Deutsch 日本語 Português
Cadenas de caracteres: La tabla de caracteres ASCII y su utilización

Cadenas de caracteres: La tabla de caracteres ASCII y su utilización

MetaTrader 4Ejemplos | 8 marzo 2016, 12:57
8 155 0
Antoniuk Oleg
Antoniuk Oleg

Introducción

En este artículo analizaremos la tabla de caracteres ASCII y cómo se puede utilizar. Veremos también algunas funciones nuevas, cuyo funcionamiento se basa en las características de la tabla ASCII, y luego crearemos una librería nueva que incluirá estas funciones del lenguaje MQL4. Son bastante conocidas en otros lenguajes de programación, pero no están incluidas en MQL4. Además, analizaremos en detalle los conceptos básicos del uso de las cadenas de caracteres. Por lo que creo que sin duda aprenderá algo nuevo sobre este tipo muy útil de datos.


¿Qué es ASCII?

ASCII es el Código Estándar Estadounidense para el Intercambio de Información (acrónimo inglés de American Standard Code for Information Interchange). Este estándar está basado en el alfabeto inglés. Se usan los códigos ASCII para representar los textos en ordenadores, equipos de comunicación y otros dispositivos que funcionan con textos. El código ASCII fue creado en 1963, pero fue publicado como estándar por primera vez en 1967 y fue actualizado por última vez en 1986. Puede obtener información más detallada sobre el código ASCII en: https://en.wikipedia.org/wiki/ASCII. Después veremos cómo se pueden mostrar los caracteres ASCI mediante las opciones de MQL4, pero veamos primero los conceptos básicos para trabajar con cadenas de texto.


Fundamentos de escritura de una librería

Para escribir una librería de este tipo, tenemos que entender algunos puntos clave. En primer lugar, vamos a ver la forma de "recorrer" los caracteres, como se hace con las matrices de datos. En cualquier función, se repiten siempre las partes iguales del código destinadas al procesamiento de la conversión de los caracteres. Como ejemplo, vamos a escribir un script sencillo que muestra primero una cadena normal de caracteres y una procesada, donde se separa cada carácter por un espacio.

//+------------------------------------------------------------------+
//|                                          StringExpereriment1.mq4 |
//|         Copyright © 2007, Antonio Banderass. All rights reserved |
//|                                               banderassa@ukr.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, Antonio Banderass. All rights reserved"
#property link      "banderassa@ukr.net"
//+------------------------------------------------------------------+
//| start                                                            |
//+------------------------------------------------------------------+
int start()
  {
   string s1 = "Just_a_string", s2, symbol = "s";
   int lenght = StringLen(s1);
   MessageBox(s1);
   for(int x = 0; x < lenght; x++)
     {
       symbol = StringSetChar(symbol, 0, StringGetChar(s1, x));
       s2 = s2 + symbol + " ";
     }
   MessageBox(s2);
   return(0);
  }
//+------------------------------------------------------------------+

Analicemos el valor de cada cadena de caracteres.

string s1 = "Just_a_string", s2, symbol = "s";

Determina tres variables de tipo cadena de caracteres:

  • s1 - la cadena inicial que queremos procesar;
  • s2 - la cadena que contendrá el resultado;
  • symbol - la cadena que se usa para el almacenamiento temporal de cada carácter.

Tenga en cuenta que se inicializa mediante un carácter. Si no hacemos esto, obtendremos como resultado una cadena sin el primer carácter. Necesitamos por lo menos un carácter para un funcionamiento normal por el hecho de que la función estándar StringGetChar() que está incluida en MQL4 modifica los caracteres ya creados.

int lenght = StringLen(s1);

Determina la variable de tipo entero para almacenar la longitud de la cadena. Para determinar la longitud de la cadena llama a la función estándar StringLen() que tiene un sólo parámetro, y es la cadena cuya longitud necesitamos averiguar.

MessageBox(s1);

Mostrar la cadena sin procesar.

for(int x = 0; x < lenght; x++)

Determina el bucle en el que tendrá lugar el procesamiento de conversión de caracteres. Tenga en cuenta que el contador se inicializa con cero ya que la indexación de los caracteres empieza con cero, al igual que en las matrices. Se usa el operador "menos" durante la ejecución del bucle puesto que la posición de la longitud del último carácter es 1.

symbol = StringSetChar(symbol, 0, StringGetChar(s1, x));

Se usan dos funciones estándar en esta cadena: StringSetChar() y StringGetChar(). La primera nos permite sustituir uno de los caracteres de la cadena y la segunda permite obtener el código del carácter en la posición indicada. La función StringSetChar() tiene tres parámetros:

  • la cadena en la que hay que sustituir el carácter;
  • la posición del carácter que hay que sustituir (recuerde que las cadenas están indexadas a partir de cero, como en las matrices).
  • el código del carácter que sustituirá al otro.

La función devuelve el resultado en forma de una cadena modificada. Otra función importante es StringGetChar. Tiene dos parámetros:

  • la cadena con un carácter cuyo código hay que identificar;
  • la posición del carácter cuyo código hay que identificar.

La función devuelve el código del carácter. Puesto que la función StringGetChar devuelve el código del carácter, he colocado su llamada en el lugar del parámetro de la función StringSetChar. Así que mediante esta función memorizamos la posición actual del carácter para su posterior procesamiento. Durante la ejecución del bucle se asignará cada carácter de la cadena s1 a una variable.

s2 = s2 + symbol + " ";

Podemos unir fácilmente las cadenas (concatenación) mediante la operación suma (+). A continuación añadimos en cada iteración un carácter y un espacio a la cadena resultante.

MessageBox(s2);

Mostrar el resultado. Tenga en cuenta que hemos leído cada carácter empezando desde el primero, aunque se puede hacer a la inversa. En este caso obtenemos un código más corto y con menos variables. Si no importa a partir de que lado se empieza el procesamiento, use la siguiente opción:

//+------------------------------------------------------------------+
//|                                            StringExperiment2.mq4 |
//|         Copyright © 2007, Antonio Banderass. All rights reserved |
//|                                               banderassa@ukr.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, Antonio Banderass. All rights reserved"
#property link      "banderassa@ukr.net"
//+------------------------------------------------------------------+
//| start                                                            |
//+------------------------------------------------------------------+
int start()
  {
   string s1 = "Just_a_string", s2, symbol = "s";
   int lenght = StringLen(s1) - 1;
   MessageBox(s1);
   while(lenght >= 0)
     {
       symbol = StringSetChar(symbol, 0, StringGetChar(s1, lenght));
       s2 = s2 + symbol + " ";
       lenght--;
     }
   MessageBox(s2);
   return(0);
  }
//+------------------------------------------------------------------+

Como puede observar, en lugar del bucle "for" usamos "while", lo que permite deshacerse del contador x. Para ello, usamos la variable length (longitud). Más adelante, usaremos una de las dos plantillas para escribir funciones, dependiendo de si importa la secuencia del procesamiento o no. En nuestro caso, obtenemos la cadena con los caracteres en el orden inverso, es decir, la secuencia de procesamiento es muy importante aquí.


Mostrar todos los caracteres ASCII

Vamos a tratar de mostrar todos los caracteres ASCII. Recuerde las funciones StringSetChar() y StringGetChar(), que respectivamente insertan un carácter ASCII, según el código, en la posición indicada y devuelven el código según el carácter. StringSetChar() tiene tres parámetros con valores de tipo "int" (enteros). Este es un código de la tabla de caracteres ASCII. Vamos a escribir un script especial para determinar el código de cada carácter:

//+------------------------------------------------------------------+
//|                                            StringExperiment3.mq4 |
//|         Copyright © 2007, Antonio Banderass. All rights reserved |
//|                                               banderassa@ukr.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, Antonio Banderass. All rights reserved"
#property link      "banderassa@ukr.net"
//+------------------------------------------------------------------+
//| start                                                            |
//+------------------------------------------------------------------+
int start()
  {
   string s, symbol = "s";
   for(int x = 0; x < 256; x++)
    {
      symbol = StringSetChar(symbol, 0, x);
      s = s + x + " = " + symbol + " \t";
      if(x % 10 == 0)
          s = s + " \n";
    }
   MessageBox(s);
   return(0);
  }
//+------------------------------------------------------------------+

El script usa las funciones incluidas en MQL4, además de las constantes de cadena para una nueva cadena y la tabulación para la presentación visual de la tabla. Compile el script y ejecútelo ahora. Debería ver la tabla de caracteres ASCII:


Mírela con detenimiento. Verá absolutamente todos los caracteres que puedan hacer falta, desde números y letras hasta caracteres especiales, y puede que algunos son nuevos para usted. Primero se ve el código y justo después del signo "=" está el propio carácter. He marcado algunos conjuntos importantes de caracteres:

Preste atención a la disposición de las letras. Están ordenadas alfabéticamente. Se usará más adelante esta característica para escribir algunas funciones, por ejemplo, para convertir las letras de una cadena en mayúsculas o minúsculas.

Ahora vamos a tratar de abordar las nuevas funciones y finalmente crear una librería basada en ellas.


StringUpperCase y StringLowerCase

Estas son dos funciones muy conocidas para la conversión de una cadena en mayúsculas o minúsculas. Se basa su implementación en el hecho de que el código de cada letra en mayúscula disminuye en 32 para la misma letra en minúscula. Se puede ver esto en la tabla. En la práctica, si tratamos por ejemplo de averiguar los códigos de los caracteres "A", "Z", "a" y "z" mediante este código:

string s = "AZaz";
MessageBox("A = " + StringGetChar(s, 0));
MessageBox("Z = " + StringGetChar(s, 1));
MessageBox("a = " + StringGetChar(s, 2));
MessageBox("z = " + StringGetChar(s, 3));

obtendremos los siguientes resultados: A= 65, Z= 90, a= 97, z= 122 respectivamente. Así que debemos tener esta característica en cuenta. Veamos el código fuente de la función:

//+------------------------------------------------------------------+
//| StringUpperCase                                                  |
//+------------------------------------------------------------------+
string StringUpperCase(string str)
  {
   string s = str;
   int lenght = StringLen(str) - 1, symbol;
   while(lenght >= 0)
     {
       symbol = StringGetChar(s, lenght);
       if((symbol > 96 && symbol < 123) || (symbol > 223 && symbol < 256))
           s = StringSetChar(s, lenght, symbol - 32);
       else 
           if(symbol > -33 && symbol < 0)
               s = StringSetChar(s, lenght, symbol + 224);
       lenght--;
     }
   return(s);
  }
//+------------------------------------------------------------------+
//| StringLowerCase                                                  |
//+------------------------------------------------------------------+
string StringLowerCase(string str)
  {
   string s = str;
   int lenght = StringLen(str) - 1, symbol;
   while(lenght >= 0)
     {
       symbol = StringGetChar(s, lenght);
       if((symbol > 64 && symbol < 91) || (symbol > 191 && symbol < 224))
           s = StringSetChar(s, lenght, symbol + 32);
       else 
           if(symbol > -65 && symbol < -32)
               s = StringSetChar(s, lenght, symbol + 288);
       lenght--;
     }
   return(s);
  }

Puesto que la secuencia de procesamiento no importa, usaremos un bucle "while". El uso de esta función es muy sencillo y su único parámetro es la cadena que hay que convertir a mayúscula o minúscula.

string s1 = "UPPER_REGISTER_STRING";
  string s2 = "lower_register_string";
   
  MessageBox(StringLowerCase(s1)); // upper_register_string
  MessageBox(StringUpperCase(s2)); // LOWER_REGISTER_STRING


StringCompare

Se implementa la comparación en MQL4 a nivel de operadores mediante "==". Es interesante señalar que la comparación es sensible a las mayúsculas y minúsculas, es decir, las cadenas "STRING" y "string" son distintas:

if("STRING" == "string") // FALSE
      MessageBox("TRUE");
   else
      MessageBox("FALSE");

Si queremos comparar dos cadenas teniendo en cuenta mayúsculas y minúsculas, usaremos la función StringCompare(). Devuelve valores de tipo booleano, al igual que el operador de comparación. La implementación es sencilla. Compara cadenas que han sido previamente convertidas a minúsculas.

//+------------------------------------------------------------------+
//| StringCompare                                                    |
//+------------------------------------------------------------------+
bool StringCompare(string s1, string s2)
  {
    return(StringLowerCase(s1) == StringLowerCase(s2));
  }

Ejemplo de uso:

if(StringCompare("STRING", "string")) // TRUE
      MessageBox("TRUE");
   else
      MessageBox("FALSE");


StringIsDigit

Esta función comprueba el contenido de una cadena. Si la cadena solo contiene números, devuelve true, de lo contrario, devuelve false. Su implementación es bastante sencilla y se basa en la disposición de los caracteres una serie de números y sus códigos van desde 48 hasta 58.

//+------------------------------------------------------------------+
//| StringIsDigit                                                    |
//+------------------------------------------------------------------+
bool StringIsDigit(string str)
  {
   bool result = true;
   string s = str;
   int lenght = StringLen(str) - 1, symbol;
   while(lenght > 0)
     {
       symbol = StringGetChar(s, lenght);
       if(!(symbol > 47 && symbol < 58))
         {
           result = false;
           break;
         }
       lenght--;
     }
   return(result);
  }

Ejemplo de uso:

if(StringIsDigit("1234567890")) // TRUE
      MessageBox("TRUE");
  else
      MessageBox("FALSE");
 
  if(StringIsDigit("1234notdigit")) // FALSE
      MessageBox("TRUE");
  else
      MessageBox("FALSE");


StringIsAlpha

Al igual que la anterior, esta función permite averiguar si la cadena contiene sólo letras. Su implementación es similar:

//+------------------------------------------------------------------+
//| StringIsAlpha                                                    |
//+------------------------------------------------------------------+
bool StringIsAlpha(string str)
  {
   bool result = false;
   string s = str;
   int lenght = StringLen(str) - 1, symbol;
   while(lenght > 0)
     {
       symbol = StringGetChar(s, lenght);
       if((symbol > 96  && symbol < 123) || (symbol > 64 && symbol < 91) ||
          (symbol > 191 && symbol < 256) || (symbol > -65 && symbol < 0))
 
         {
           result = true;
           break;
         }
       lenght--;
     }
   return(result);
  }

Ejemplo de uso:

if(StringIsAlpha("thereAreSomeLetters")) // TRUE
      MessageBox("TRUE");
  else
      MessageBox("FALSE");
 
  if(StringIsAlpha("thereAreSomeDigits12345")) // FALSE
      MessageBox("TRUE");
  else
      MessageBox("FALSE");


Crear un librería

Vamos a poner ahora todas estas funciones en una librería. Para hacerlo en MetaEditor 4, pulse "Archivo -> Nuevo -> Biblioteca -> Siguiente". En el campo del nombre ponga stringProcess y pulse Finalizar. A continuación inserte el código de las funciones anteriores y guarde el archivo. Después, hay que crear un archivo con los prototipos de las funciones pulsando "Archivo -> Nuevo -> Incluir(*. mqh) -> Siguiente". En el campo del nombre ponga stringProcess y pulse Finalizar. Inserte ahora los prototipos de todas las nuevas funciones e indique la directriz para la importación.

//+------------------------------------------------------------------+ 
//|                                                stringProcess.mqh |
//|                               Antonio Banderass Copyright © 2007 | 
//|                                               banderassa@ukr.net |
//+------------------------------------------------------------------+ 
#property copyright "Antonio Banderass Copyright © 2007"
#property link      "banderassa@ukr.net"
//+--- 
#import "stringProcess.ex4"
//+------------------------------------------------------------------+
//| prototypes                                                       | 
//+------------------------------------------------------------------+
string StringUpperCase(string str); 
string StringLowerCase(string str);
bool StringCompare(string s1, string s2);
bool StringIsDigit(string str);
bool StringIsAlpha(string str);

Uso de la librería stringProcess

Para utilizar la librería, incluya el archivo de cabecera con los prototipos de las funciones, esto le permitirá llamar a las funciones que hagan falta. A continuación se muestra un ejemplo de uso de un script:

//+------------------------------------------------------------------+
//|                                     stringProcessLibraryTest.mq4 |
//|                               Antonio Banderass Copyright © 2007 |
//|                                               banderassa@ukr.net |
//+------------------------------------------------------------------+
#property copyright "Antonio Banderass Copyright © 2007"
#property link      "banderassa@ukr.net"
 
#include <stringProcess.mqh>
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
   if(StringIsDigit("1234567890")) // TRUE
       MessageBox("TRUE");
   else
       MessageBox("FALSE");
   if(StringIsDigit("1234notdigit")) // FALSE
       MessageBox("TRUE");
   else
       MessageBox("FALSE");
   return(0);
  }


Conclusión

Así que ya sabe lo que es una tabla de caracteres ASCII y cómo utilizar sus características para implementar nuevas funciones. Ha escrito nuevas funciones que son muy populares en otros programas pero que las incluye MQL4. A partir de estas funciones, ha creado una pequeña librería para el procesamiento de las cadenas. Creo que no se puede utilizar esta librería durante el trading, pero sí al recibir los resultados. Por ejemplo, si está desarrollando su propio sistema de informes para su Asesor Experto, algunas funciones le resultarán muy útiles. Además, se podrán utilizar en muchos otros campos que tal vez desconozco. ¡Le deseo mucha suerte y muchas ganancias!

Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/1474

Interfaces gráficas II: Controles "Línea separadora" y "Menú contextual" (Capítulo 2) Interfaces gráficas II: Controles "Línea separadora" y "Menú contextual" (Capítulo 2)
En este artículo nos ocuparemos de la creación del control llamado “Línea separadora”. Se podrá utilizarlo no sólo como un elemento independiente de la interfaz, sino también como parte de otros controles. Después de eso, tendremos todo lo necesario para desarrollar la clase del menú contextual, que también será considerado al detalle en el presente artículo. Además, vamos a introducir adiciones necesarias en la clase que sirve de base para almacenar los punteros a todos los controles de la interfaz gráfica de la aplicación.
Encuesta: Lo que opinan los traders del Terminal móvil Encuesta: Lo que opinan los traders del Terminal móvil
Desafortunadamente, todavía no hay previsiones claras acerca del futuro del trading móvil. Sin embargo, hay muchos rumores entorno a esta cuestión. En nuestro intento de disipar las dudas, hemos decidido realizar una encuesta entre los traders para averiguar sus opiniones acerca de los terminales móviles. Por medio de esta encuesta, hemos conseguido establecer una imagen clara de lo que piensan nuestros traders del producto en este momento, así como sus propuestas y expectativas para los futuros desarrollos de nuestros terminales móviles.
Aplicación práctica de indicadores cluster en FOREX Aplicación práctica de indicadores cluster en FOREX
Los indicadores cluster son conjuntos de indicadores que separan el par de divisas en dos divisas distintas. Estos indicadores permiten seguir la fluctuación relativa de las divisas, determinar la posibilidad de aparición de nuevas tendencias de las divisas, recibir señales de trading y seguir las posiciones de medio y largo plazo.
ZUP - ZigZag universal con Patrones de Pesavento. Primera parte ZUP - ZigZag universal con Patrones de Pesavento. Primera parte
Este artículo proporciona una breve descripción de las ideas en las que se basa el indicador ZUP - ZigZag universal con Patrones de Pesavento. El artículo describe también los indicadores ZigZag incluidos en el indicador ZUP.