Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 1413

 
Alexey Viktorov:

Функции IntegerToString() и DoubleToString() всего лишь представляют число в виде строки которое передано в функцию. Вот в примере

как раз и происходит перевод числа r в строку и строки «складываются». Но перед этим значение r меняется.

Я не совсем понял вопрос, но если надо сделать чтобы выбрать из массива только чётные элементы, то цикл надо строить так


Спасибо за объяснение.

 
Alexey Viktorov:

Функции IntegerToString() и DoubleToString() всего лишь представляют число в виде строки которое передано в функцию. Вот в примере

как раз и происходит перевод числа r в строку и строки «складываются». Но перед этим значение r меняется.



Не могу понять процесс "складывания" значений строковых переменных. Я вижу 2 варианта "складывания" строк в моем коде.

1. Складываются значение строковой переменной текущей итерации со значением этой же строковой переменной из предыдущей итерации.

2. На текущей итерации складываются значения двух сроковых переменных , то есть,  IntegerToString(r) + DoubleToString(LoY[r],4)

Мне кажется, что Вы имели в виду первый вариант.

Но тогда .... значение  IntegerToString(r) на прошлой итерации = "0" , а на текущей = "1" . Результат сложения должен быть "01". 

Если на текущей итерации перед сложением значение   IntegerToString(r) с предыдущего значения  0 меняется на текущее  1 , тогда все равно получается двузначное строковое представление числа, то есть -  "11".

Если по этому же алгоритму складывать значения строковой переменной  DoubleToString(LoY[r],4), то тогда результатом сложения двух строк должны быть значения типа 1.61041.6105

Но Print() почему то печатает результаты сложения в виде других чисел (таких какие они и должны быть)
Что я недопонимаю.
Вот  Ваш пример того как складываются значения строковых переменных "...... а если складывать строки DoubleToString(2.3, 1)+ DoubleToString(3.6, 1) то будет 2.33.6 в виде строки." То есть до сложения строковое представление числа каждой переменной состояло из 2 символов, а после сложения двух строковых переменных - результат сложения стал строковым представлением числа из 4 символов. Почему в результате сложения в Вашем коде не получается число с удвоенным количеством символов?

 
Alexey Viktorov:


Я не совсем понял вопрос, но если надо сделать чтобы выбрать из массива только чётные элементы, то цикл надо строить так


На самом деле я вот что имел в виду.... Вот первоначальный код, дополненный БЛОКОМ N 2

int P1=0;
double LoY[31];
void OnTick()
{
if (P1==0)
{
for(int r=0; r<31;r++)
{
LoY[r]=1.6104+(r*2)*0.0001;
Print("-------------------------------------LoY[r]--------------=",  LoY[r]);
P1=1;
}
}
//*************************************************************  Б Л О К    N 2
for(int x=0; x<31;x++)
{
if (Bid < LoY[x] )
{
LoY[x]=Bid;
ArraySort(LoY,WHOLE_ARRAY,0,MODE_ASCEND);
Print("---LoY[0]--",  X, "---LoY[1]--" ,  X,   "---LoY[2]--" ,  X,  "---LoY[3]--" ,  X,  "---LoY[4]--" ,  X, ................  "---LoY[30]--" ,  X );
}
}
}

 Во втором блоке значения элементов массива уже не отличаются друг от друга на одинаковую дельту, как в первом блоке. Дельта между соседними элементами может быть разной и поэтому алгоритм коннектации строк из первого блока для второго блока не подходит....как мне кажется.

ВОПРОС   При помощи какой языковой конструкции на MQL4 или функции  на MQL4 во втором блоке  вышеприведенного кода функция  Print() по окончании работы цикла будет напечатана только 1 раз со всеми заполненными значениями элементов массива, которые будут расположены в одну строку , то есть , примут следующий вид

Print("---LoY[0]--",  Х, "---LoY[1]--" Х ,   "---LoY[2]--" Х ,  "---LoY[3]--" Х ,  "---LoY[4]--" Х , ................  "---LoY[30]--" Х  );

Не судите меня строго, но я не уверен, что пойму объяснения на словах, потому что во втором блоке все гораздо сложнее чем в первом....как мне кажется.
Спасибо за помощь.

 

При программировании очень много рутинной работы, во всяком случае в начале пути. Вы продумываете идею, затем пишите код, а затем отлаживаете его. Иногда время отладки занимает больше времени, чем всё остальное.

Часто бывает, что первоначальный замысел не работает. Начинаете смотреть сверху вниз по порядку, что не так.

Везде вставляете printf(), и смотрите, это то, что вы ожидаете или нет. Так быстрее придёт понимание, как работает код и где у Вас ошибка. Иначе понимание будет приходить долго.


Не моё дело, но пытайтесь писать красиво. Выберите для себя стиль, и придерживайтесь его. Скобки в скобках размещайте ступеньками, чтобы было видно вложения. Если используете пробелы между операциями, тогда используйте их везде, или наоборот везде не используйте.

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

if (Bid < LoY[x] )

Потом Вам будет легче читать собственный код.

-----------------

по второму блоку:

Во втором блоке строчная x и заглавная X разные переменные, код так как Вы хотите работать не будет.

Сортировать массив желательно не в цикле, а за его пределами.

В Print Вы много раз используете X, столько же раз Вы распечатаете одно и тоже число.

-----------------

По коду. Сложно понять вопрос, скажу как понял.

Если Вы в цикле напишите Print, то получите столько же выводов на печать, сколько итераций сделал этот цикл. Если Вам нужно сделать вывод один раз, то расположите Print после цикла.

При этом, чтобы собрать информацию, используйте переменную, в которую будете писать значения каждой итерации. Переменная у нас строковая, поэтому все числа переводите в строку.

Строковая переменная у нас из-за того, что функция Print принимает строку.

Что происходит:

Первый проход. Перед первым проходом до цикла у нас пустая переменная: string str="";
Дальше переменной мы присваиваем пустое значение плюс "--LoY["+IntegerToString(r)+"]--, "+DoubleToString(LoY[r],4)+", ";
здесь r равен 0 и фактически складываем несколько строк:

"--LoY["+

IntegerToString(0)+

"]--, "+

DoubleToString(LoY[0],4)+

", ";

Второй проход.

Ко всему этому, что имеем прибавляем ещё информацию второго элемента

"--LoY["+IntegerToString(1)+"]--, "+DoubleToString(LoY[1],4)+", ";

При этом строка от первого элемента уже не меняется.



Лучше объясните цель словами, что Вам нужно, а не то как Вы это делаете. А то мы так долго можем обсуждать Ваш код, а окажется, что Вашу цель можно решить другим способом.

 
ANDREY:

Не могу понять процесс "складывания" значений строковых переменных. Я вижу 2 варианта "складывания" строк в моем коде.

1. Складываются значение строковой переменной текущей итерации со значением этой же строковой переменной из предыдущей итерации.

2. На текущей итерации складываются значения двух сроковых переменных , то есть,  IntegerToString(r) + DoubleToString(LoY[r],4)

Мне кажется, что Вы имели в виду первый вариант.

Но тогда .... значение  IntegerToString(r) на прошлой итерации = "0" , а на текущей = "1" . Результат сложения должен быть "01". 

Если на текущей итерации перед сложением значение   IntegerToString(r) с предыдущего значения  0 меняется на текущее  1 , тогда все равно получается двузначное строковое представление числа, то есть -  "11".

Если по этому же алгоритму складывать значения строковой переменной  DoubleToString(LoY[r],4), то тогда результатом сложения двух строк должны быть значения типа 1.61041.6105

Но Print() почему то печатает результаты сложения в виде других чисел (таких какие они и должны быть)
Что я недопонимаю.
Вот  Ваш пример того как складываются значения строковых переменных "...... а если складывать строки DoubleToString(2.3, 1)+ DoubleToString(3.6, 1) то будет 2.33.6 в виде строки." То есть до сложения строковое представление числа каждой переменной состояло из 2 символов, а после сложения двух строковых переменных - результат сложения стал строковым представлением числа из 4 символов. Почему в результате сложения в Вашем коде не получается число с удвоенным количеством символов?

На самом деле это происходит ровно так-же как написание любого текста. Сначала имеем чистый лист, или лучше сказать пустую строку. Затем пишем первое слово, к нему приставляем второе и так далее……… А когда в тексте встречаются числа, то их мы пишем как символ строки. То-есть если мы складываем числа 2+5 то получим 7, а если просто пишем эти-же числа, то сначала пишем 2 и рядом 5… получаем подряд записанные две цифры 25. Я не знаю как ещё проще такое объяснить.

В принципе если не обращать внимание на предупреждения компилятора то перевод в строку значений r в вашем примере не обязателен. Вот проверьте два таких варианта

Print("Test 1 " + (string)1 + (string)2);
Print("Test 2 " + 1 + 2);
 
Aleksei Stepanenko:


Спасибо за помощь и советы.

 
Alexey Viktorov:

На самом деле это происходит ровно так-же как написание любого текста. Сначала имеем чистый лист, или лучше сказать пустую строку. Затем пишем первое слово, к нему приставляем второе и так далее……… А когда в тексте встречаются числа, то их мы пишем как символ строки. То-есть если мы складываем числа 2+5 то получим 7, а если просто пишем эти-же числа, то сначала пишем 2 и рядом 5… получаем подряд записанные две цифры 25. Я не знаю как ещё проще такое объяснить.

В принципе если не обращать внимание на предупреждения компилятора то перевод в строку значений r в вашем примере не обязателен. Вот проверьте два таких варианта

Спасибо за все

 
ANDREY:

На самом деле я вот что имел в виду.... Вот первоначальный код, дополненный БЛОКОМ N 2

 Во втором блоке значения элементов массива уже не отличаются друг от друга на одинаковую дельту, как в первом блоке. Дельта между соседними элементами может быть разной и поэтому алгоритм коннектации строк из первого блока для второго блока не подходит....как мне кажется.

ВОПРОС   При помощи какой языковой конструкции на MQL4 или функции  на MQL4 во втором блоке  вышеприведенного кода функция  Print() по окончании работы цикла будет напечатана только 1 раз со всеми заполненными значениями элементов массива, которые будут расположены в одну строку , то есть , примут следующий вид

Print("---LoY[0]--",  Х, "---LoY[1]--" Х ,   "---LoY[2]--" Х ,  "---LoY[3]--" Х ,  "---LoY[4]--" Х , ................  "---LoY[30]--" Х  );

Не судите меня строго, но я не уверен, что пойму объяснения на словах, потому что во втором блоке все гораздо сложнее чем в первом....как мне кажется.
Спасибо за помощь.

А зачем сортировать массив на каждой итерации цикла? Ведь если вы заменили значение 0-го элемента массива и после сортировки оно ушло в конец массива, то нулевым станет значение которое было первым, а первым станет то, что было вторым. Таким образом значение первого элемента массива будет пропущено и получается белиберда. В общем весь ваш код, это что-то с чем-то.

Зачем вам первый блок в котором вы заполняете массив? Заполните массив сразу нужными значениями и после заполнения отсортируйте. Правда придётся запустить ещё один цикл для заполнения строки и печати. Жаль что в mql4 не сделали ArrayPrint()… Но ведь это у вас эксперименты и в действительности распечатывать значения массива вам не надо будет.

 
Aleksei Stepanenko:

Лучше объясните цель словами, что Вам нужно, а не то как Вы это делаете. А то мы так долго можем обсуждать Ваш код, а окажется, что Вашу цель можно решить другим способом.

В процессе изучения mql4(и параллельно немного  mql5), я пишу различные коды. В том числе коды в которых используются массивы. Часто бывает нужно в том или ином месте кода проверить значения элементов массива. Я научился это делать, при помощи Print() в цикле. Но в этом случае  Print() печатается на каждой итерации. Когда итераций много - это неудобно как для программы так и для чтения. Вы правильно сказали, что  Print() нужно выносить за пределы цикла, что бы  Print() со значениями элементов массива печатался только один раз . Об этом я догадался и до Ваших слов.

Выносить  Print() за пределы цикла я научился очень быстро. А теперь я пытаюсь научиться заставить   Print() в одной строке печатать все значения элементов массива.

Мне объяснили как это делается применительно к первому блоку моего кода. Пока в  общих чертах , эту технологию я понял. Буду дальше ломать голову, что бы понять и детали этого метода.
Но во втором блоке моего кода, как мне кажется, метод из первого блока не подходит потому что , в отличии от первого блока , дельта между значениями элементов массива во втором блоке разная.
Если я прав и метод из первого блока не подходит ко второму, то буду Вам признателен если покажете как делается то же самое что делалось в первом блоке, но уже применительно ко второму блоку.

Я исправил второй блок. Вынес  Print() и ArraySort() за пределы цикла. Убрал из  Print()  переменную X что бы не вводить Вам в заблуждение.

int P1=0;
double LoY[31];
void OnTick()
{
if (P1==0)
{
for(int r=0; r<31;r++)
{
LoY[r]=1.6104+(r*2)*0.0001;
P1=1;
}
}
//*************************************************************  Б Л О К    N 2
for(int x=0; x<31;x++)
{
if (Bid < LoY[x] )
{
LoY[x]=Bid;
}
}
ArraySort(LoY,WHOLE_ARRAY,0,MODE_ASCEND);
Print("-LoY[0]-", (знач.эл.масс с инд.0), "---LoY[1]--" ,  (знач.эл.масс с инд.1),   "---LoY[2]--" ,  (знач.эл.масс с инд.2),  "---LoY[3]--" ,  (знач.эл.масс с инд.3),................  "---LoY[30]--" ,  (знач.эл.масс с инд.30) );
}
 
Print("-LoY[0]-", DoubleToString(LoY[0],4), "---LoY[1]--", DoubleToString(LoY[1],4), "---LoY[2]--" , DoubleToString(LoY[2],4), "---LoY[3]--" , DoubleToString(LoY[3],4),................  "---LoY[30]--" ,  DoubleToString(LoY[30],4) );

или сделать отдельную функцию печати массива:

void PrintArray(double &eArray)
   {
   string eStr="";
   int eSize=ArraySize(eArray);
   for(int i=0; i<eSize; i++)
      {
      eStr+=IntegerToString(i)+": "+DoubleToString(eArray[i],4)+", ";
      }
   Print(str);
   }

И вызывайте её из любого места

PrintArray(LoY);
Причина обращения: