Невозможно нормально объединить условия в операторе if в vbscript

Я пытаюсь определить, между полуднем и часом ночи. Вот мой оператор if:

If InStr(Time,"12") AND InStr(Time,"AM") Then 
    ' Do something
Else
    ' Do something else
End If

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

If InStr(Time,"12") Then
    If InStr(Time,"AM") Then
        ' Do something
...

И это работает. Это тоже работает

If InStr(Time,"12")<>0 AND InStr(Time,"AM")<>0 Then
    ' Do something
...

Но если он работает как вложенное if, почему я не могу протестировать оба вложенных условия if в одном операторе if?

Я заменил вызовы функций InStr значениями, которые они возвращают

If 1 AND 10 Then
    ' Do something
Else
    ' Do something else
End If

И произошло то же самое: оператор if был оценен как ложный, и вместо него были выполнены команды «Сделать что-нибудь еще». Но когда я вложил второе условие как другой оператор if внутри первого оператора if, команды «Сделать что-нибудь» были выполнены.

Почему это так и есть ли способ сделать это без <> 0 и без вложенности?

Оператор AND в If x AND y выполняет побитовое сравнение идентично расположенных битов в двух числовых выражениях. Примените If x * y, так как ложный имеет значение, равное 0, и наоборот.

JosefZ 13.09.2018 19:39

Спасибо, это странно, но я думаю, это имеет смысл. Если вы поставите это как ответ, я отмечу это как ответ

Ethan 13.09.2018 20:03
Instr не возвращает True или False. Он возвращает позицию первого вхождения строки поиска или 0, если он не найден. Может, это вас смущает?
aphoria 13.09.2018 20:46

aphoria - 0 оценивается как False, а любое ненулевое число оценивается как True. Если True AND True Then будет выполняться всегда, поэтому логично предположить, что If (любое ненулевое число) AND (любое ненулевое число) Then также будет выполняться, поскольку оба оператора оцениваются как True, но это выглядит так, как в VBScript И похоже на знак =, если сравнивает два числа вместо логических. По крайней мере, это то, что я понимаю из того, что говорит JosefZ

Ethan 13.09.2018 21:04

Верно, в этом моя точка зрения, Instr не возвращает логическое значение, он возвращает целое число.

aphoria 13.09.2018 21:34

Проблема в том, что VBScript использует одни и те же операторы для логических операций с битами а также, в зависимости от типа данных операндов. Поведение - задокументированный. Чтобы применить логическое сравнение, вам нужно использовать InStr(...) > 0 или CBool(InStr(...)) (оба из которых оцениваются как логический результат) вместо просто InStr(...) (который оценивает числовой результат).

Ansgar Wiechers 13.09.2018 21:37

В итоге я использовал CBool ​​(InStr ()) в обоих случаях. Я думаю, что таким образом легче понять цель заявления. Ансгар Вичерс, вы дали самое ясное объяснение, наиболее читаемое решение и поддержали его документацией. Если вы переформулируете свой комментарий в качестве ответа, я отмечу его как правильный ответ. В противном случае отвечу сам. Единственный ответ, который у нас есть до сих пор, более сложен, чем способ, который я предложил (и отверг) в вопросе.

Ethan 14.09.2018 14:32
1
7
941
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

If Time() >= TimeValue("12:00:00") AND Time() <= TimeValue("23:59:59") then 
   'Do Something
ElseIf  Time() >= TimeValue("00:00:00") AND Time() <= TimeValue("01:00:00") then 
   'Do the same 
Else
   'Do something different
End If

Это должно работать :)

Что с первым условием, OP запрашивал между 12:00 и 01:00, а не с 12:00 до 23:59:59?

user692942 14.09.2018 08:09

Я бы отметил это как ответ, если бы не две вещи: 1) хотя это и будет работать, это гораздо более сложный способ сделать это. Я бы предпочел использовать InStr (Time, "12") <> 0 AND InStr (Time, "AM"), чем это. Вы превратили 5 строк в 7; 2) как указывает Lankymart, аргументы, переданные функции TimeValue (), неверны. Я ценю вклад, хотя

Ethan 14.09.2018 14:26

@Lankymart Вместе с условием ElseIf это между 12 и 1 часами ночи. И именно поэтому для этого нужны два условия, мы ищем время в два разных дня.

flipdascript 15.09.2018 01:08
Ответ принят как подходящий

Обнаруженная вами проблема вызвана тем, что VBScript использует одни и те же операторы для логических и битовых операций, в зависимости от типа данных операндов. Функция InStr возвращает числовое значение, если одна из строк не является Null, поэтому операция становится побитовым сравнением вместо логического сравнения, как указано в JosefZ. Поведение задокументированный:

The And operator also performs a bitwise comparison of identically positioned bits in two numeric expressions and sets the corresponding bit in result [...]

Демонстрация:

>>> WScript.Echo "" & (True And True)
True
>>> WScript.Echo "" & (6 And 1)'0b0110 && 0b0001 ⇒ 0b0000
0
>>> WScript.Echo "" & (6 And 2)'0b0110 && 0b0010 ⇒ 0b0010
2

Чтобы применить логическое сравнение, вам нужно использовать InStr(...) > 0 или CBool(InStr(...)) (оба из которых оцениваются как логический результат) вместо просто InStr(...) (который оценивает числовой результат).

К вашему сведению, я использовал CBool ​​(InStr (…)) для обоих условий, и он отлично работает. Это был самый простой из предложенных способов, который лучше всего сохранял значение оператора If. Спасибо!

Ethan 18.09.2018 02:46

Я ценю объяснение того, как VBScript обрабатывает эти операции. Я только что обнаружил фатальную ошибку в подходе к реальной проблеме: это условие будет проверяться как истинное в любое время в течение AM, когда часы, минуты или секунды равны 12, а не только часам. Вместо этого я использую If Hour(Time) = 0 Then

Ethan 08.11.2018 16:53

Дата и время сохраняются как количество дней, где полночь - 0,0, а 1 час ночи - 1/24:

If Time <= 1/24 Then       ' or If Time <= #1am# Then

Когда вы используете функцию Time(), и если результат такой, 10:12:12 AM таким образом, Instr приведет к Ture, потому что Instr по умолчанию использует vbbinarycompare, ищущий любой двоичный формат 12 в 10:12:12 AM, и есть sec и min 12, поэтому он вернет True. просто попробуйте это:

  myHour=replace(Time,Right(Time,9),"")     'get only the hour from time
  myAMPM=replace(Time,Time,Right(Time,2))     'get only AM or PM from time
    If InStr(1,myHour,12,1) > 0 AND InStr(1,myAMPM,"AM",1) > 0 Then 
       wscript.echo "True"
    Else
      wscript.echo "False"
    End If

VBscript и vb.net имеют ту же проблему, что вы должны кормить их всем готовым к работе, но процесс внутри процесса в процессе, в это время происходит ошибка

hollopost 17.09.2018 15:45

Другие вопросы по теме