Отсутствует номер ошибки

 

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

// Удаление всех объектов по имени. =======================================================================================================
void DrawGrafics::DeleteAllObjects (void)
{
   string objName = NULL;
   
   for (int obj = ObjectsTotal() - 1; obj >= 0; obj--)
   {
      objName = ObjectName (obj);
      
      if (StringSubstr (objName, 11, 12) == "OBJ_ARROW_UP")
      {
          ObjectDelete (objName);
          
          // Перерисуем объект
          WindowRedraw();
      }
      else
      {
         Logging::WriteLog (StringConcatenate (__FUNCTION__, ": Не удалось стереть объект с именем ", objName, ". Ошибка: ", IntegerToString(_LastError)), Logging::NeedLogs,
                            Logging::PrintUP, Logging::CommentUP);
      }
   }
}

 В журнале вижу такое:

2015.07.21 21:44:18.619	ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects: Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_4. Ошибка: 0
2015.07.21 21:44:18.620	ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects: Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_3. Ошибка: 0
2015.07.21 21:44:18.621	ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects: Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_2. Ошибка: 0
2015.07.21 21:44:18.622	ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects: Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_1. Ошибка: 0
2015.07.21 21:44:18.622	ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects: Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_0. Ошибка: 0
Почему в журнал не попадает никакой ошибки?
 

Добавил в условие обычный принт:

else
      {
         Print ("_LastError ", _LastError);
      }

 На выходе тоже самое... Т.е. всё дело в самом возврате _LastError, а не в моей функции логирования. Вот что вижу:

2015.07.21 22:19:14.755 ZZBaseVariant USDJPY,H1: _LastError 0
2015.07.21 22:19:14.755 ZZBaseVariant USDJPY,H1: _LastError 0
2015.07.21 22:19:14.755 ZZBaseVariant USDJPY,H1: _LastError 0
2015.07.21 22:19:14.755 ZZBaseVariant USDJPY,H1: _LastError 0
2015.07.21 22:19:14.755 ZZBaseVariant USDJPY,H1: _LastError 0
 

Значение _LastError изменяется после вызова каждой последующей функции. В приведенном коде код ошибки изменен после вызова StringSubstr.

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

objName = ObjectName (obj);
int error = GetLastError(); // или _LastError
      
      if (StringSubstr (objName, 11, 12) == "OBJ_ARROW_UP")
      {
          ObjectDelete (objName);
          
          // Перерисуем объект
          WindowRedraw();
      }
      else
      {
         Logging::WriteLog (StringConcatenate (__FUNCTION__, ": Не удалось стереть объект с именем ", objName, ". Ошибка: ", IntegerToString(error)), Logging::NeedLogs,
                            Logging::PrintUP, Logging::CommentUP);
      }
 

Что-то не помогло. Вот функция:

// Удаление всех объектов по имени. =======================================================================================================
void DrawGrafics::DeleteAllObjects (void)
{
   string objName = NULL;
   
   for (int obj = ObjectsTotal() - 1; obj >= 0; obj--)
   {
      objName = ObjectName (obj);
      int err = GetLastError();
      
      if (StringSubstr (objName, 11, 10) == "BJ_BUTTON")
      {
          ObjectDelete (objName);
          
          // Перерисуем объект
          WindowRedraw();
      }
      else
      {
         Print ("err: " ,err);
         Logging::WriteLog (StringConcatenate (__FUNCTION__, " => Не удалось стереть объект с именем: ", objName, ". Ошибка № ", err),
                            Logging::NeedLogs, Logging::PrintUP, Logging::CommentUP);
      }
   }
}

 В журнале:

2015.07.22 00:13:32.770 ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects => Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_0. Ошибка: 0
2015.07.22 00:13:32.769 ZZBaseVariant USDJPY,H1: err: 0
2015.07.22 00:13:32.769 ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects => Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_1. Ошибка: 0
2015.07.22 00:13:32.768 ZZBaseVariant USDJPY,H1: err: 0
2015.07.22 00:13:32.768 ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects => Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_2. Ошибка: 0
2015.07.22 00:13:32.767 ZZBaseVariant USDJPY,H1: err: 0
2015.07.22 00:13:32.767 ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects => Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_3. Ошибка: 0
2015.07.22 00:13:32.766 ZZBaseVariant USDJPY,H1: err: 0
2015.07.22 00:13:32.766 ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects => Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_4. Ошибка: 0
2015.07.22 00:13:32.765 ZZBaseVariant USDJPY,H1: err: 0
 
shanty:

Что-то не помогло. Вот функция:

 В журнале:

 

У вас вывод сообщения об ошибке за пределами заданного условия для удаления и, соответственно, самого удаления объектов.

Поскольку есть возможность воспользоваться тем, что ObjectDelete имеет тип bool, попробуйте так:

if(StringSubstr(objName,11,10)=="BJ_BUTTON")
  {
   ResetLastError();

   if(!ObjectDelete(chart_ID,objName))
     {
      Logging::WriteLog(StringConcatenate(__FUNCTION__," => Не удалось стереть объект с именем: ",objName,". Ошибка № ",GetLastError()),
                        Logging::NeedLogs,Logging::PrintUP,Logging::CommentUP);
     }
   ChartRedraw();
  }
P./S.: Параметр chart_ID - из второго варианта ObjectDelete.
 

А этот блок в вашем коде тогда не потребуется:

  else
      {
         Print ("err: " ,err);
         Logging::WriteLog (StringConcatenate (__FUNCTION__, " => Не удалось стереть объект с именем: ", objName, ". Ошибка № ", err),
                            Logging::NeedLogs, Logging::PrintUP, Logging::CommentUP);
      }

(если, конечно, не будете его применять для прописки каких-либо других свои условий/вывода сообщений).

 
shanty:

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

 В журнале вижу такое:

Почему в журнал не попадает никакой ошибки?

Лог не от этого кода.

В коде:

Logging::WriteLog (StringConcatenate (__FUNCTION__, " => Не удалось стереть объект с именем: ", objName, ". Ошибка № ", err),Logging::NeedLogs, Logging::PrintUP, Logging::CommentUP);

 Видим в логе:

 2015.07.22 00:13:32.770 ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects => Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_0. Ошибка: 0

 
Mislaid:

Лог не от этого кода.

В коде:

 Видим в логе:

 2015.07.22 00:13:32.770 ZZBaseVariant USDJPY,H1: DrawGrafics::DeleteAllObjects => Не удалось снести объект с именем USDJPY_H1 _OBJ_BUTTON_0. Ошибка: 0

 

Это вы верно подметили.

Однако, на всякий случай всё-таки скажу, что в этом сравнении у него:

if (StringSubstr (objName, 11, 10) == "BJ_BUTTON")

задаётся условие, при котором будет удалён объект и, если оно совпадает, то объект удаляется в блоке кода этого сравнения.

А вывод сообщения об ошибке при удалении объекта, у него в другом блоке. В else условия выше. То бишь, тогда, когда нет удаления объекта. Поэтому и ошибка равна 0.

 

Кроме того, вместо:

if (StringSubstr (objName, 11, 10) == "BJ_BUTTON")

с моей точки зрения, вот такую замену можно ещё произвести:

  string name=StringSubstr(objName,11,10);

         if(StringCompare(name,"BJ_BUTTON",true)==0)
           {
...
P./S.: Это не в связи с вопросом темы. Это просто дополнение из-за того, что как-то мне не нравится, что в if идёт вызов StringSubstr.
 
DiPach:

Однако, на всякий случай всё-таки скажу, что в этом сравнении у него:

задаётся условие, при котором будет удалён объект и, если оно совпадает, то объект удаляется в блоке кода этого сравнения.

А вывод сообщения об ошибке при удалении объекта, у него в другом блоке. В else условия выше. То бишь, тогда, когда нет удаления объекта. Поэтому и ошибка равна 0.

Согласен, условие вышло какое-то не продуманное и нелогичное. Теперь понял в чём косяк. Ошибка то получается в другом контексте...

 

DiPach:

P./S.: Это не в связи с вопросом темы. Это просто дополнение из-за того, что как-то мне не нравится, что в if идёт вызов StringSubstr.

 Ну а как тогда быть? Ещё не всё прооптимизировал и не всё дореализовал т.к. там будет под любой объект использоваться. Но суть не в том. А мы о том, что не нравится условие такое... в if имеется вызов StringSubstr. Как тут иначе? Ведь суть в том, что происходит проверка того что объект всё-таки выбран. Иначе дальше не резон двигаться. Поэтому, лично я не наблюдаю вариантов.

Какие будут соображения на этот счёт?

На данный момент, реализация вот такая:

void DrawGrafics::DeleteAllObjects (void)
{
   string objName = NULL;
   
   for (int obj = ObjectsTotal(); obj >= 0; obj--)
   {
      objName = ObjectName (obj);
      
      if (StringSubstr (objName, 11, 10) != "BJ_BUTTON")
      {
          ResetLastError();
          
          if (!ObjectDelete (objName))
          {
             Logging::WriteLog (StringConcatenate (__FUNCTION__, " => Не удалось стереть объект с именем: ", objName, ". Ошибка № ", _LastError),
                               Logging::NeedLogs, Logging::PrintUP, Logging::CommentUP);
          }
          
          // Перерисуем объект
          WindowRedraw();
      }
   }
}
 
shanty:

 Ну а как тогда быть? Ещё не всё прооптимизировал и не всё дореализовал т.к. там будет под любой объект использоваться. Но суть не в том. А мы о том, что не нравится условие такое... в if имеется вызов StringSubstr. Как тут иначе? Ведь суть в том, что происходит проверка того что объект всё-таки выбран. Иначе дальше не резон двигаться. Поэтому, лично я не наблюдаю вариантов.

Какие будут соображения на этот счёт?

На данный момент, реализация вот такая:

Так я вам и предложила здесь пооптимальнее условия проверки. ) В том числе, исходя из костяка схемы кода и предполагая, что в дальнейшем он будет видоизменяться и/или дополняться. Эти функции - и есть под любой объект и разнообразные условия (в контексте вашего кода). Включая, когда будут заменены переменными эти значения: 10, 11, "BJ_BUTTON" и true, при необходимости.

В том числе, StringCompare - всё-таки поуниверсальнее в дальнейшем применении, чем (образно) просто: if (x=="abc"). Плюс, эта функция специально предназначена для сравнений строк.

Вывод её результата сравнения в виде числа может пригодиться и при постановке определённых условий (то есть, снова образный пример: если 0, удаляем объект; если -1, то делаем то; если 1, то другое).

/*И эту функцию, в принципе, можно из условий сравнения сначала в переменную вывести, а затем уже переменную - в if или switch, где дальнейшие условия будут определяться на основе значений этой переменной.*/


P./S.: А не нравится StringSubstr в if, поскольку итак строковые данные обрабатываются дольше всего.  Да и обработка функций в самом условии условного оператора if, подольше вроде как.

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

Как-то так.

Причина обращения: