Download MetaTrader 5

Strings: Table of ASCII Symbols and Its Use

27 July 2007, 13:04
Antoniuk Oleg
1
2 500

Introduction

In this article we will analyze the table of symbols ASCII and the ways it can be used. We will also deal with some new functions, the principle of operation of which is based on the peculiarities of the ASCII table, and then we will create a new library, which will include these functions of MQL4 language. They are quite popular in other programming languages, but they are not included into the list of built-in functions. Besides, we will examine in details the basics of working with strings. So, I think you will certainly learn something new about this useful type of data.


What is ASCII ?

ASCII is the American coding standard for information interchange (American Standard Code for Information Interchange). This standard is based on the English alphabet. ASCII codes present a text in computers, communication equipment and other devices, which work with texts. ASCII was created in 1963, but published as a standard first in 1967. The last amendments were made in 1986. More detailed information about ASCII can be found here: http://en.wikipedia.org/wiki/ASCII. Further we will see, how we can display ASCII using MQL4 options, but first let us examine the basis of working with strings.



Principles of Writing a Library

To write a library of this kind, let us understand some essential moments. First let us see how we can go through all symbols, like the procedures with data arrays. Alike code parts will be always repeated in any function, intended for symbolwise processing. As an example, let us write a simple script, which first shows a common string and then a processed one, where each symbol is divided by a space.

//+------------------------------------------------------------------+
//|                                          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);
  }
//+------------------------------------------------------------------+

Let us analyze the value of each string.

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

Determine three variables of a string type:

  • s1 - initial string, which we want to process;
  • s2 - string that will contain the result;
  • symbol - string used for temporary storing of each symbol.

Note, that it is initialized by one symbol. If we do not do this, we will get as a result a string without the first symbol. The matter is, the standard MQL4 function StringGetChar() changes already created symbols, that is why we need at least one symbol for regular operation.

int lenght = StringLen(s1);
Determine the variable of integer type to store the string length. For this purpose call the standard function for determination of the string length StringLen(), which has a single parameter - the string, the length of which we need to know.

MessageBox(s1);
Display MessageBox.

for(int x = 0; x < lenght; x++)
Determine the cycle, in which the simbolwise processing will take place. Note that the counter is initialized by zero, because symbols in the string are indexed from zero like in arrays. In the conditions of cycle execution the comparison operator "less" is used, because the last symbol's length position is 1.

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

In this string two standard functions are used: StringSetChar() and StringGetChar(). The first one allows replacing one of the symbols of the string, the second one - getting the symbol code in the indicated position. The function StringSetChar() has three parameters:

  • string, in which a symbol should be replaced;
  • position of the symbol, which should be replaced (remember that strings are indexed from zero like in arrays);
  • code of the symbol, which will replace.

The function returns the result in the form of a changed string. One more important function - StringGetChar. It has two parameters:

  • string with a symbol, the code of which should be recognized;
  • position of the symbol, the code of which should be recognize.

The function returns the symbol code. While the function StringGetChar returns the symbol code, I located its calling in the place of the parameter of the function StringSetChar. Therefore using this function we remember the current symbol for further processing. During the execution of the cycle, each symbol of the string s1 will be assigned to the variable.

s2 = s2 + symbol + " ";
We can easily bind strings (concatenation) using addition operation (+). Here at each cycle iteration we add to the resulting string a symbol and a space.
MessageBox(s2);
Show the result. Note, that we read each symbol starting from the first one, though it can be done vice versa. In this case we have a shorter code and fewer variables. If in string processing it does not matter, from which side to begin, use the following variant:
//+------------------------------------------------------------------+
//|                                            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);
  }
//+------------------------------------------------------------------+

You see, now instead of the cycle 'for' we use 'while', which allows omitting the counter x. For this purpose we use the variable length. Further we will use one of the two templates for writing functions, depending on the fact, whether the processing sequence matters or not. In our case we get the string with the symbols in the reverse order, i.e. here the processing sequence matters much.


Show All Symbols ASCII

Now let us try to show all ASCII symbols. Remember the functions StringSetChar() and StringGetChar(), which accordingly insert into the indicated position a symbol from ASCII upon the code and return the code upon the symbol. StringSetChar() has the third parameter int value. This is a code from the table of ASCII symbols. Let us write a special script, to determine the code of each symbol:

//+------------------------------------------------------------------+
//|                                            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);
  }
//+------------------------------------------------------------------+

The script uses in-built MQL4 functions, and string constants of a new string and tabulation for the visualization of the table. Now compile and start it. You will see the table of ASCII symbols:



Look at it very attentively. You will see absolutely all symbols, which can be needed, from numbers and letters to special symbols, some of them can be new for you. First comes a code, and then after the sign "=" comes the symbol itself. I marked some important sets of symbols:



Pay attention to the arrangement of letters. They are arranged in the alphabetical order. This characteristic will later be used for writing some functions, for example, for transferring letters from the string of the upper case into the lower one and vice versa.

And now let us deal with new functions and in the end create a library based on them.



StringUpperCase and StringLowerCase

These are two very popular functions for transferring a string into the upper or lower case. Their implementation is based on the fact that all codes of the upper case letters symbols are shifted by 32 from the letters of the lower case. It is seen from the table. In practice, if we try to find the codes of symbols 'A', 'Z', 'a', 'z', for example using this code:

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

the results will be the following: A= 65, Z= 90, a= 97, z= 122 accordingly. So we should take into account this peculiarity. Let us view the source code of the function:

//+------------------------------------------------------------------+
//| 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);
  }
While the sequence of processing does not matter, use the cycle while. It is very easy to use the function, the only parameter is the string, which should be transferred into the proper case:
string s1 = "UPPER_REGISTER_STRING";
  string s2 = "lower_register_string";
   
  MessageBox(StringLowerCase(s1)); // upper_register_string
  MessageBox(StringUpperCase(s2)); // LOWER_REGISTER_STRING


StringCompare

In MQL4 the comparison of strings is performed on the level of operators using "==". Interesting is the fact that comparison is case-dependant, i.e. strings "STRING" and "string" are different:

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

If we need to compare two string without ignoring case, use the function StringCompare(). It returns bool type values like the operator of comparison. The implementation is easy. It compares strings that are beforehand transferred into lower case:

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

Example of use:

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

StringIsDigit

This function checks the contents of the string. If the string contains only numbers, it returns true, otherwise - false. The implementation is quite easy and is based on the fact, that the symbols of numbers are in one raw and have codes from 48 to 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);
  }

Example of use:

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

StringIsAlpha

This function, like the previous one, allows determining whether the string contains only letters. Its implementation is analogous:

//+------------------------------------------------------------------+
//| 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);
  }

Example of use:

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

Creating a Library

Now let us gather all these functions into one library. For this purpose in MetaEditor 4 click 'File -> New -> Library -> Next'. In the field name write stringProcess and click OK. Then insert the code of the above described functions and save. Then create a file with the functions prototypes, clicking 'File -> New -> Include(*. MQH) -> OK'. In the field name write stringProcess, -> OK. Now insert the prototypes of all new functions, and indicate the directive for import:

//+------------------------------------------------------------------+ 
//|                                                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);

Using the Library stringProcess

To use the library, include the header file with the prototypes of functions, after that you can call necessary functions. Here is the example of using in a 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);
  }

Conclusion

So, you have learned about the table of ASCII symbols and how you can use the peculiarities of its construction for the design of new functions. You have written new functions, which are very popular in other programming languages, but which MQ4L does not include. Based on them you have created a small library for string processing. I think this library will be used not during trading, but at the receipt of results. For example, if you are developing your own system of reports for your Expert Advisor, then some of the functions will be useful for you. Besides you will find many areas of use, which I may not know. Good luck and profits to you!

Last comments | Go to discussion (1)
bejglee
bejglee | 4 Jun 2013 at 09:29

Hi,

I think, it would be better:

bool StringIsDigit(string str)
{
   bool result = true;
   int lenght = StringLen(str);
   if(lenght == 0) return(false);            <-- if it is not here, than result is true. Because while-condition (up) will be false.
   for(int i=0; i < lenght; i++)
   {
       int symbol = StringGetChar(str, i);
       if(symbol < 48 || symbol > 57)
       {
           result = false;
           break;
       }
   }
   return(result);
} 
Step on New Rails: Custom Indicators in MQL5 Step on New Rails: Custom Indicators in MQL5

I will not list all of the new possibilities and features of the new terminal and language. They are numerous, and some novelties are worth the discussion in a separate article. Also there is no code here, written with object-oriented programming, it is a too serous topic to be simply mentioned in a context as additional advantages for developers. In this article we will consider the indicators, their structure, drawing, types and their programming details, as compared to MQL4. I hope that this article will be useful both for beginners and experienced developers, maybe some of them will find something new.

Here Comes the New MetaTrader 5 and MQL5 Here Comes the New MetaTrader 5 and MQL5

This is just a brief review of MetaTrader 5. I can't describe all the system's new features for such a short time period - the testing started on 2009.09.09. This is a symbolical date, and I am sure it will be a lucky number. A few days have passed since I got the beta version of the MetaTrader 5 terminal and MQL5. I haven't managed to try all its features, but I am already impressed.

Portfolio trading in MetaTrader 4 Portfolio trading in MetaTrader 4

The article reveals the portfolio trading principles and their application to Forex market. A few simple mathematical portfolio arrangement models are considered. The article contains examples of practical implementation of the portfolio trading in MetaTrader 4: portfolio indicator and Expert Advisor for semi-automated trading. The elements of trading strategies, as well as their advantages and pitfalls are described.

False trigger protection for Trading Robot False trigger protection for Trading Robot

Profitability of trading systems is defined not only by logic and precision of analyzing the financial instrument dynamics, but also by the quality of the performance algorithm of this logic. False trigger is typical for low quality performance of the main logic of a trading robot. Ways of solving the specified problem are considered in this article.