Скачать MetaTrader 5

Проблема: StringSubstr усекает строку на 4095

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Stanislav Korotky
20303
Stanislav Korotky  
Всем привет. Обнаружил баг. Имеется текст длиной (в частном случае) 7587 символа. Описан как string Text, заполняется из винды. В начале обработки там содержится то, что нужно - проверял и длину через StringLen, и выводил начало и конец через Print. Этот текст в цикле разбивается на строки по символам \r\n такой конструкцией: line = StringSubstr(ls, 0, pos); ls = StringSubstr(ls, pos + StringLen(separator)), где ls - локальная копия изначально равная Text, pos - позиция где найден сепаратор \r\n. Так вот после вызова оператора ls = ... длина текста усекается до 4095. Вывел в лог все переменные, так что могу утверждать, что "чудо" происходит именно при вызове StringSubstr, а не в mql-коде. Пробовал также явно указывать длину подстроки через третий параметр (а-ля, ls = StringSubstr(ls, pos + StringLen(separator), StringLen(ls) - pos - StringLen(separator))) - то же самое. Что за фигня? Если действительо есть проблемы с StringSubstr, расскажите плиз кто что использует взамен - наверняка есть готовые скрипты. Заранее спасибо.
Stanislav Korotky
20303
Stanislav Korotky  

Дополнение. Написал в лоб для StringSubstr функцию-замену вот такую:

string StringSubstrX(string ls, int pos)
{
  string result;
  int len = StringLen(ls);
  for(int i = 0; i < len - pos + 1; i++)
  {
    result = StringConcatenate(result, CharToStr(StringGetChar(ls, pos + i)));
  }
  return(result);
}

С ней весь скрипт работает нормально, хотя и тормозит.

Rustamzhan Salidzhanov
7792
Stanislav Korotky
20303
Stanislav Korotky  
И что? Документацию я читал. Там нет ни слова об ограничении длины строки (не путать с литералом). Длинное целое, зарезервированное внутри под длину строки, явно не равно 4096.
Alexey Navoykov
4324
Alexey Navoykov  

Вы бы для начала привели ЦЕЛИКОМ тот кусок кода, который приводит к описанной проблеме. А то по вашему словесному описанию трудно что-то понять. Да и вообще попытка описать код словами выглядит весьма странно. Программист поймёт всё и без слов.

Я лично никаких проблем со StringSubstr не испытываю, хотя иногда использую (и получаю) там строки и по 100К.

Но судя по вашей приведённой функции-замене, я догадываюсь что в исходном коде у вас была такая же ошибка, как и в этой функции: строковая переменная ничем не проинициализирована. Инициализацию надо делать обязательно, иначе проблем не оберёшься. Обычно делают так: string result="";

Slava
Модератор
6927
Slava  

Посмотрите код ошибки, возвращаемый GetLastError. Скорее всего это ERR_TOO_LONG_STRING (4011) - не хватает места во внутреннем буфере.

Изначально внутренний буфер распределён на 4096 символов с учётом терминирующего нуля. В некоторых случаях этот буфер может быть перераспределён автоматически. Одним из таких случаев может быть функция StringConcatenate

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

Stanislav Korotky
20303
Stanislav Korotky  
Meat:

Но судя по вашей приведённой функции-замене, я догадываюсь что в исходном коде у вас была такая же ошибка, как и в этой функции: строковая переменная ничем не проинициализирована. Инициализацию надо делать обязательно, иначе проблем не оберёшься. Обычно делают так: string result="";

Делал инициализацию пустой строкой - не помогло. В общем, stringo пролил свет, но пока я оставил "затычку".
. ... Rick D. ... .
1181
. ... Rick D. ... .  

Наткнулся на похожую проблему.

Было:

string item = "";
item = StringSubstr(str, pos1, pos2-pos1);

При большой длине str не работало - часть текста отсекалась.

Заменил на:

string item = "";
if (pos2-pos1 >= 4096) item = str;
      
item = StringSubstr(str, pos1, pos2-pos1);
Теперь item предварительно инициализируется большой строкой и StringSubstr заработал правильно.
Алексей Тарабанов
7326
Алексей Тарабанов  

Встретились два друга, один - другому: давай выпьем? - нет, мне врач запретил. Да ладно, я своему 100 баксов дал - все разрешил.

Это не оффтопик, а призыв не пользоваться строковыми переменными длинною более 256 байт :)

Mikhail Dovbakh
4806
Mikhail Dovbakh  
tara:

Встретились два друга, один - другому: давай выпьем? - нет, мне врач запретил. Да ладно, я своему 100 баксов дал - все разрешил.

Это не оффтопик, а призыв не пользоваться строковыми переменными длинною более 256 байт :)

следуя Вашему методу "призывов" - не больше 128!

Надёжней!

А еще лучше не больше 64...

:)

---

Чем обоснуете, если не секрет свой "призыв"?

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий