Bibliotheken: TypeToBytes - Seite 3

 
ja
 
Drei Zeilen zum selben Thema
Color = (color)ColorToARGB(Color, Alpha);

Color = (color)((Color & 0xFFFFFF) + (Alpha << 24));

_W(Color)[3] = Alpha;
 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Fragen von Neulingen zu MQL4, Hilfe und Diskussion über Algorithmen und Codes

fxsaber, 2017.03.07 13:55

#include <TypeToBytes.mqh>

template <typename T>
void Swap( T &Value1, T &Value2 )
{
  const T Tmp = Value1;
  
  Value1 = Value2;
  Value2 = Tmp;
}

// Sortieren eines Arrays eines beliebigen einfachen Typs
template <typename T>
bool MyArraySort( T &Array[] )
{
  if (!ArraySort(Array))
  {
    const int Size = ArraySize(Array);
    
    for (int i = 0; i < Size - 1; i++)
    {
      const T Tmp = Array[i];
      
      for (int j = i + 1; j < Size; j++)
        if (_R(Tmp) == Array[j]) // TypeToBytes.mqh
        {
          Swap(Array[i + 1], Array[j]);
          
          i++;
        }
    }      
  }
  
  return(true);
}
 
Byte-für-Byte-Operation auch mit Arrays hinzugefügt
// Arbeiten mit Arrays
  short Array[] = {1, 2, 3};
  ArrayPrint(_R(Array).Bytes);           // Byte-für-Byte-Darstellung des Array-Arrays ausgeben

  PRINT((_R(Array) == _R(Array).Bytes))  // Stellen Sie sicher, dass der Byte-für-Byte-Array-Vergleich funktioniert.

  _W(Color) = Array;                     // Byteweises Schreiben von Array-Array in Farbe
  PRINT(Color)                           // Stellen Sie sicher, dass Farbe jetzt C'1,0,2' ist.
  ArrayPrint(_R(Color).Bytes);           // Byteweise Darstellung der Farbe drucken

  uchar Array2[];
  ArrayCopy(Array2, _R(Tick).Bytes);     // Schreiben der Byte-Darstellung von Tick in Array2
  PRINT((_R(Tick) == Array2))            // Sicherstellen, dass Tick und Array2 Byte für Byte übereinstimmen

  MqlTick Tick2 = {0};
  _W(Tick2) = Array2;                    // Array2-Array in Tick2 schreiben
  PRINT((_R(Tick) == Tick2))             // Stellen Sie sicher, dass Tick und Tick2 übereinstimmen.

  int Array3[] = {INT_MIN, INT_MAX};
  ArrayPrint(_R(Array3).Bytes);          // Byte-für-Byte-Darstellung des Array3-Arrays drucken
  ArrayPrint(_R(Array).Bytes);           // Byte-für-Byte-Darstellung des Array-Arrays ausgeben

  _ArrayCopy(Array3, Array);             // Array-Array byteweise in Array3-Array kopieren
  ArrayPrint(_R(Array3).Bytes);          // Stellen Sie sicher, dass die Byte-Darstellung des Array3-Arrays mit dem
 
Byte-für-Byte-Operation auch mit Strings hinzugefügt
// Arbeiten mit Zeichenketten
  string Str = "abcd";

  _W(i) = Str;                           // Schreiben der Zeichenkette in (int)i byteweise

  PRINT((_R(i) == Str))                  // Byte-für-Byte-Vergleich von int und sring

  ArrayPrint(_R(i).Bytes);               // Nachgeschlagene Bytes i
  ArrayPrint(_R(Str).Bytes);             // Betrachtet Str Bytes

  PRINT(_R(Str)[(short)1])               // Nahm den Kurzwert durch Mischen von 1 in Str

  PRINT(Str)
  _W(Str)[2] = "98765";                  // Byteweises Schreiben einer Zeichenkette in eine Zeichenkette an Offset 2
  PRINT(Str)

  string StrArray[] = {"123", "45", "6789"};
  _W(Str) = StrArray;                    // Schreiben eines String-Arrays in einen String
  PRINT(Str)

  _W(Str)[3] = (uchar)0;                 // Eine Null wird in das Byte bei Offset 3 geschrieben, wodurch die Zeichenkette abgeschnitten wird (Länge - 3 ANSI-Zeichen (4 Bytes)).
  PRINT(Str);
 

Forum zum Thema Handel, automatisierte Handelssysteme und Testen von Handelsstrategien

Bibliotheken: File Mapping ohne DLL

fxsaber, 2017.04.03 16:07

Danke an den Autor für die Bibliothek!

Ich habe Funktionen zum Übertragen beliebiger Daten erstellt. Untenstehendes Skript zeigt deren Arbeit am Beispiel von Ticks

#include <MemMapLib.mqh>
#include <TypeToBytes.mqh>

// Weist Speicher der angegebenen Länge für Daten zu 
template <typename T>
bool GetFileMemory( CMemMapFile* &FileMemory, const int Amount, const string FileName = "Local\\test" )
{
  FileMemory = new CMemMapFile;
    
  return(FileMemory.Open(FileName, sizeof(T) * Amount + sizeof(int) + HEAD_MEM, modeCreate) == 0);
}

// Schreibt Daten in den Speicher
template <typename T>
void DataSave( CMemMapFile* FileMemory, const T &Data[], const bool FromBegin = true  )
{
  const int Size = ArraySize(Data) * sizeof(T);
  uchar Bytes[];
  
  _ArrayCopy(Bytes, _R(Size).Bytes);              // Aufzeichnung der Menge 
  _ArrayCopy(Bytes, _R(Data).Bytes, sizeof(int)); // Aufzeichnung der Daten

  if (FromBegin)
    FileMemory.Seek(0, SEEK_SET);

  FileMemory.Write(Bytes, ArraySize(Bytes)); // Alles in den Speicher entladen
  
  return;
}

// Liest Daten aus dem Speicher
template <typename T>
int DataLoad( CMemMapFile* FileMemory, T &Data[], const bool FromBegin = true )
{
  if (FromBegin)
    FileMemory.Seek(0, SEEK_SET);

  uchar Bytes[];
          
  FileMemory.Read(Bytes, sizeof(int));  // Lesen der Datenmenge aus dem Speicher 
  FileMemory.Read(Bytes, _R(Bytes)[0]); // Ich habe die Daten selbst

  _ArrayCopy(Data, Bytes);              // Dumped die Daten in ein Array
  
  return(ArraySize(Data));
}

#define  AMOUNT 1000

#define  TOSTRING(A) #A + " = " + (string)(A) + " "

// Beispiel für die Übertragung von Zecken
void OnStart()
{  
  CMemMapFile* FileMemory;
  
  if (GetFileMemory<MqlTick>(FileMemory, AMOUNT))
  {
    MqlTick Ticks4Save[];    
    CopyTicks(_Symbol, Ticks4Save, COPY_TICKS_INFO, 0, AMOUNT);
    
    DataSave(FileMemory, Ticks4Save);
    
    MqlTick Ticks4Load[];    
    
    if (DataLoad(FileMemory, Ticks4Load) > 0)    
      Print(TOSTRING((_R(Ticks4Save) == Ticks4Load)) +
            TOSTRING(ArraySize(Ticks4Save)) +
            TOSTRING(ArraySize(Ticks4Load)));
     
    FileMemory.Close();   
  }
  
  delete FileMemory;
}


Ergebnis

(_R(Ticks4Save)==Ticks4Load) = true ArraySize(Ticks4Save) = 1000 ArraySize(Ticks4Load) = 1000

Ein Beispiel für eine mögliche praktische Anwendung der Neuerungen.

 
#include <TypeToBytes.mqh>

// Alle Array-Zeichenfolgen zu einer einzigen Zeichenfolge zusammenführen
string StringArrayConcatenate( const string &StrArray[] )
{
  string Str = "";
  const int Size = ArraySize(StrArray);
  
  for (int i = 0; i < Size; i++)
    Str += StrArray[i];
    
  return(Str);
}

void OnStart()
{
  string StrArray[] = {"abcd", "123", "zxc", "890", "qwert"};
  string Str1, Str2;

// Alle Array-Zeichenfolgen zu einer einzigen Zeichenfolge zusammenführen 
  Str1 = StringArrayConcatenate(StrArray);
  _W(Str2) = StrArray;
  
  Print(Str1);
  Print(Str2); 
}

Hervorgehoben - das gleiche Ergebnis auf sehr unterschiedliche Weise

abcd123zxc890qwert
abcd123zxc890qwert
 
Nach der Aktualisierung wird sie verfügbar sein
// Festlegen einer benutzerdefinierten Struktur
struct STRUCT
{
  int i;

  // Setzen Sie den Zuweisungsoperator
  void operator =( const STRUCT& ) {}
};

// Demonstration des Ergebnisses der Umgehung des benutzerdefinierten Zuweisungsoperators der _R-Struktur durch die Bibliotheksfunktion
  STRUCT Struct;                         // Ein Objekt mit einem benutzerdefinierten Zuweisungsoperator erstellt
  Struct.i = 1;

  ArrayPrint(_R(Struct).Bytes);          // Stellen Sie sicher, dass der Zuweisungsoperator
  PRINT(_R(Struct) == Struct)            // hat keinen Einfluss auf die _R-Funktionalität der Bibliothek

// Überprüfung der "Korrektheit" des Typzuweisungsoperators
  PRINT(_WRONG_ASSIGN_OPERATOR(int))     // Richtig
  PRINT(_WRONG_ASSIGN_OPERATOR(MqlTick)) // Richtig
  PRINT(_WRONG_ASSIGN_OPERATOR(STRUCT))  // Nicht korrekt
 
  • Определение корректности оператора присваивания структур.

Ein Beispiel dafür, wie diese Funktion bei der Erkennung potenzieller Fehler nützlich sein kann.

Schreiben Sie das Skript und führen Sie es aus.

#include <TypeToBytes.mqh>

struct STRUCT
{
  int i;
  
  STRUCT() : i(0) {}
  
  template <typename T>
  void operator =( T& ) {}
};

#define  PRINT(A) ::Print(#A + " = " + (string)(A));

void OnStart()
{
  PRINT(_WRONG_ASSIGN_OPERATOR(STRUCT))
}


Ergebnis.

_WRONG_ASSIGN_OPERATOR(STRUCT) = true

Dies zeigt an, dass der Zuweisungsoperator eine Struktur nicht in eine Struktur desselben Typs kopieren kann.


Wenn wir mehr zu der Struktur hinzufügen,

  void operator =( STRUCT &Value ) { this.i = 0; }

wird das Ergebnis dasselbe sein.


Es scheint, dass durch die Festlegung dieses Operators auf

  void operator =( STRUCT &Value ) { this.i = Value.i; }

alles richtig machen sollte, aber die Bibliothek sagt etwas anderes.


Dies ist vielleicht der subtilste Punkt dieses Beispiels.

Wir fixieren ihn auf

#include <TypeToBytes.mqh>

struct STRUCT
{
  int i;
  
  STRUCT() : i(0) {}
  
  template <typename T>
  void operator =( T& ) {}

  void operator =( const STRUCT &Value ) { this.i = Value.i; }
};

#define  PRINT(A) ::Print(#A + " = " + (string)(A));

void OnStart()
{
  PRINT(_WRONG_ASSIGN_OPERATOR(STRUCT))
}

und wir erhalten das Ergebnis

_WRONG_ASSIGN_OPERATOR(STRUCT) = false


Jetzt ist der Kopieroperator korrekt geschrieben!

Sie können die Korrektheit von Zuweisungs-/Kopieroperatoren beliebiger einfacher Strukturen auf ähnliche Weise überprüfen.

 
Was ist der Unterschied zwischen einer NULL-Zeichenfolge und einer leeren Zeichenfolge?
#include <TypeToBytes.mqh>

#define  PRINT(A) ::Print(#A + " = " + (string)(A));

void OnStart()
{  
  const string StrNull = NULL;
  
  PRINT(ArraySize(_R(StrNull).Bytes))
  PRINT(ArraySize(_R("").Bytes))
}

Ergebnis

ArraySize(_R(StrNull).Bytes) = 0
ArraySize(_R().Bytes) = 1

Eine NULL-Zeichenkette hat die Länge Null in Bytes. Eine leere Zeichenkette ist 1 Byte lang (wobei Null das Ende der Zeichenkette ist).