Перевод string в часы и минуты - страница 4

 
Vitaly Muzichenko:

Ну уж на явных дебилов не стоит ориентироваться. Если он не умеет ввести формат времени в строку, то скорее всего он не сможет запустить программу в терминале.

Речь на самом деле не о человеке, а о некой абстрактной программерской задачке школьного уровня. "Дети, есть строка, нужно получить ЧЧ:MM."

Решение предоставил, но оно будет пропущено. Иллюзия того, что чем-то полезным занят, бывает важнее.

 
Vladimir Karputov:

В секунды никто не преобразует. После всех проверок можно будет идти двумя путями: 

  • или преобразовать проверенную строку в datetime
  • или преобразовать проверенную строку в две переменные объявленные на глобальном программном уровне - часы и минуты.

Ясно. Это типичная заморочка из анамнеза кодера - решает собственные задачи. Реальному пользователю ввод времени вместо даты нужен для другого, поэтому оптимальное решение будет другим

 
Vladimir Karputov:

Когда встаёт задача задать во входных параметрах время в формате ЧЧ:ММ, приходится решать дилему: удобство пользователя при вводе значений или удобство программирования.

Вариант 1:

Самый известный способ ввода:

Плюсы:

* "человеческий" внешний вид значения: 


Минусы:

* довольно много проверок, для того, чтобы корректно перевести эту строку в целый тип или в datetime.

* не предназначено для оптимизации в тестере.


Самая первая проверка (которая уже ставит пользователя в ограничительные рамки) - требование придерживаться формата именно ЧЧ:ММ (например 04:09), а не Ч:ММ (например 4:09) или Ч:М (например 4:9).

И даже здесь уже распутье: а может разрешить пользователю ввод в формате Ч:ММ (например 4:09) или Ч:М (например 4:9)?

...


Шаг третий: проверка является ли символ цифрой.

//+------------------------------------------------------------------+
//| Check HH:MM To Time                                              |
//+------------------------------------------------------------------+
bool CheckHHMMToTime(string text)
  {
   bool result=true;
//--- step 1: the number of characters must be at least 3 and not more than 5
   StringTrimRight(text);           // delete spaces to the right
   StringTrimLeft(text);            // delete spaces to the left 
   if(StringLen(text)<3 || StringLen(text)>5)
     {
      Print("Length of the text can't be less than 3 and more than 5");
      return(false);
     }
//--- step 2: search for a separator ":"
   StringReplace(text,"-",":");     // search and replacement of symbol "-"
   StringReplace(text,"_",":");     // search and replacement of symbol "_"
   int search_results=0;
   for(int i=0;i<StringLen(text);i++)
      if(text[i]==':')
         search_results++;
   if(search_results==0)
     {
      Print("Divider \":\" it isn't found");
      return(false);
     }
   if(search_results>1)
     {
      Print("More than one divider \":\" are found");
      return(false);
     }
//--- step 3: single character verification
   for(int i=0;i<StringLen(text);i++)
     {
      if(text[i]==':')
         continue;
      if(!IsNumeral(text[i]))
        {
         Print("You have to use only figure from \"0\" to \"9\"");
         return(false);
        }
     }
//---
   return(result);
  }
//+------------------------------------------------------------------+
//| Is numeral                                                       |
//+------------------------------------------------------------------+
bool IsNumeral(const ushort symbol)
  {
//--- single character verification
   bool result=false;
   ushort arr_numerals[10]={48,49,50,51,52,53,54,55,56,57};
   for(int i=0;i<ArraySize(arr_numerals);i++)
      if(symbol==arr_numerals[i])
         return(true);
//---
   return(result);
  }


На следующем шаге нужно будет проверить выход значения ЧЧ за пределы от "0" до "23" и выход значения ММ за пределы от "0" до "59" ...

 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Перевод string в часы и минуты

Vladimir Karputov, 2017.09.07 09:11

Шаг третий: проверка является ли символ цифрой.

//+------------------------------------------------------------------+
//| Is numeral                                                       |
//+------------------------------------------------------------------+
bool IsNumeral(const ushort symbol)
  {
//--- single character verification
   bool result=false;
   ushort arr_numerals[10]={48,49,50,51,52,53,54,55,56,57};
   for(int i=0;i<ArraySize(arr_numerals);i++)
      if(symbol==arr_numerals[i])
         return(true);
//---
   return(result);
  }
Это ужасный код!


На следующем шаге нужно будет проверить выход значения ЧЧ за пределы от "0" до "23" и выход значения ММ за пределы от "0" до "59" ...

Зачем человека ограничивать?! А если хочется ограничений, то StringToTime умеет все делать.
 
Vladimir Karputov:

Когда встаёт задача задать во входных параметрах время в формате ЧЧ:ММ, приходится решать дилему: удобство пользователя при вводе значений или удобство программирования.

Вариант 1:

Самый известный способ ввода:

Плюсы:

* "человеческий" внешний вид значения: 


Минусы:

* довольно много проверок, для того, чтобы корректно перевести эту строку в целый тип или в datetime.

* не предназначено для оптимизации в тестере.


Самая первая проверка (которая уже ставит пользователя в ограничительные рамки) - требование придерживаться формата именно ЧЧ:ММ (например 04:09), а не Ч:ММ (например 4:09) или Ч:М (например 4:9).

И даже здесь уже распутье: а может разрешить пользователю ввод в формате Ч:ММ (например 4:09) или Ч:М (например 4:9)?

...


Окончательный вариант функции CheckHHMMToTime 

CheckHHMMToTime

Проверяет указанную строку на соответствие временного формата ЧЧ:ММ и преобразовывает строку в число типа datetime.

bool CheckHHMMToTime(
                     string text,   // строка содержащая время
                     datetime &time // переменная типа datetime в которую записывается время
                     )

Параметры

text

[in]  Строка, содержащая время.

time

[out]  Переменная переданная по ссылке, в которую записывается время.

Возвращаемое значение

[true] если удалось преобразовать строку во время, при этом время записывается в переменную time.

[false] если не удалось преобразовать строку во время, при этом в переменной time значение не определено.


Пример:

//+------------------------------------------------------------------+
//|                                                      Test_en.mq5 |
//|                                      Copyright 2012, CompanyName |
//|                                       http://www.companyname.net |
//+------------------------------------------------------------------+
#property script_show_inputs
//--- input parameters
input string CloseTime="20:50";  // Время
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+ 
void OnStart()
  {
   datetime input_time=0;
   if(CheckHHMMToTime(CloseTime,input_time))
      Print(TimeToString(input_time,TIME_MINUTES));
  }
//+------------------------------------------------------------------+
//| Check HH:MM To Time                                              |
//+------------------------------------------------------------------+
bool CheckHHMMToTime(string text,datetime &time)
  {
   bool result=true;
//--- step 1: the number of characters must be at least 3 and not more than 5
   StringTrimRight(text);           // delete spaces to the right
   StringTrimLeft(text);            // delete spaces to the left 
   if(StringLen(text)<3 || StringLen(text)>5)
     {
      Print("Length of the text can't be less than 3 and more than 5");
      return(false);
     }
//--- step 2: search for a separator ":"
   StringReplace(text,"-",":");     // search and replacement of symbol "-"
   StringReplace(text,"_",":");     // search and replacement of symbol "_"
   int search_results=0;
   for(int i=0;i<StringLen(text);i++)
      if(text[i]==':')
         search_results++;
   if(search_results==0)
     {
      Print("Divider \":\" it isn't found");
      return(false);
     }
   if(search_results>1)
     {
      Print("More than one divider \":\" are found");
      return(false);
     }
//--- step 3: single character verification
   for(int i=0;i<StringLen(text);i++)
     {
      if(text[i]==':')
         continue;
      if(!IsNumeral(text[i]))
        {
         Print("You have to use only figure from \"0\" to \"9\"");
         return(false);
        }
     }
//--- step 4: check of correctness of hours and minutes
   string sep=":";
   string split_result[];
   StringSplit(text,StringGetCharacter(sep,0),split_result);
   if(StringToInteger(split_result[0])>23) // check hours
     {
      Print("Hours can't be more \"23\"");
      return(false);
     }
   if(StringToInteger(split_result[1])>59) // check minutes
     {
      Print("Minutes can't be more \"59\"");
      return(false);
     }
//---
   time=StringToTime(text);
//---
   return(result);
  }
//+------------------------------------------------------------------+
//| Is numeral                                                       |
//+------------------------------------------------------------------+
bool IsNumeral(const ushort symbol)
  {
//--- single character verification
   bool result=false;
   ushort arr_numerals[10]={48,49,50,51,52,53,54,55,56,57};
   for(int i=0;i<ArraySize(arr_numerals);i++)
      if(symbol==arr_numerals[i])
         return(true);
//---
   return(result);
  }
//+------------------------------------------------------------------+

ds

Файлы:
Test_en.mq5  7 kb
 

Вариант 2.

Использовать две переменные: одна для указания часов, вторая для минут. 

А вот переменные - это перечисления. Например для часов:

//+------------------------------------------------------------------+
//| ENUM HOUR                                                        |
//+------------------------------------------------------------------+
enum ENUM_HOUR
  {
   HOUR_00 = 0,         // 00
   HOUR_01 = 1,         // 01
   HOUR_02 = 2,         // 02
   HOUR_03 = 3,         // 03
   HOUR_04 = 4,         // 04
   HOUR_05 = 5,         // 05
   HOUR_06 = 6,         // 06
   HOUR_07 = 7,         // 07
   HOUR_08 = 8,         // 08
   HOUR_09 = 9,         // 09
   HOUR_10 = 10,        // 10
   HOUR_11 = 11,        // 11
   HOUR_12 = 12,        // 12
   HOUR_13 = 13,        // 13
   HOUR_14 = 14,        // 14
   HOUR_15 = 15,        // 15
   HOUR_16 = 16,        // 16
   HOUR_17 = 17,        // 17
   HOUR_18 = 48,        // 18
   HOUR_19 = 19,        // 19
   HOUR_20 = 20,        // 20
   HOUR_21 = 21,        // 21
   HOUR_22 = 22,        // 22
   HOUR_23 = 23,        // 23
   HOUR_24 = 24         // 24
  };

для минут соответственно будет портянка побольше :).


Плюсы:

* вводить ничего не нужно - достаточно кликать мышкой

* такие входные параметры можно оптимизировать в тестере стратегий

Минусы:

* большая портянка для указания часов