Как лучше всего определить, является ли символ буквой в VB6?
-
01-07-2019 - |
Вопрос
Нужна функция, которая принимает символ в качестве параметра и возвращает true, если это буква.
Решение
Шонибой IsCharAlphaA
отвечать близко.Лучший способ — использовать версию W следующим образом:
Private Declare Function IsCharAlphaW Lib "user32" (ByVal cChar As Integer) As Long
Public Property Get IsLetter(character As String) As Boolean
IsLetter = IsCharAlphaW(AscW(character))
End Property
Конечно, все это редко имеет значение, поскольку все элементы управления VB6 поддерживают только ANSI.
Другие советы
Это была часть кода, опубликованного рпетрич в ответ на вопрос к Джоэл Спольски.Я чувствовал, что нужен пост, посвященный проблеме, которую он решает.Это действительно великолепно.
Private Function IsLetter(ByVal character As String) As Boolean
IsLetter = UCase$(character) <> LCase$(character)
End Function
Вы можете думать про себя: «Всегда ли это сработает?» Документация по функциям UCASE и LCASE подтверждает, что она будет:
Функция UCase В верхний регистр преобразуются только строчные буквы; все прописные буквы и небуквенные символы остаются неизменными.
Функция LCase В нижний регистр преобразуются только заглавные буквы; все строчные буквы и небуквенные символы остаются неизменными.
Private Function IsLetter(Char As String) As Boolean
IsLetter = UCase(Char) Like "[ABCDEFGHIJKLMNOPQRSTUVWXYZ]"
End Function
Что не так со следующим, которое не основано на непонятном языковом поведении?
Private Function IsLetter(ByVal ch As String) As Boolean
IsLetter = (ch >= "A" and ch <= "Z") or (ch >= "a" and ch <= "z")
End Function
Я считаю, что мы можем еще немного улучшить эту ситуацию. рпетричкод будет работать, но, возможно, только по счастливой случайности.Параметр вызова API должен быть TCHAR (на самом деле здесь WCHAR), а не Long.Это также означает, что не нужно возиться с преобразованием в Long или маскированием с помощью &HFFFF.Это, кстати, Integer и здесь также добавляется неявное преобразование в Long.Возможно, в данном случае он имел в виду &HFFFF&?
Кроме того, для совместимости с Win9X лучше всего явно вызвать оболочку UnicoWS для этого вызова API.Возможно, потребуется развернуть UnicoWS.dll, но, по крайней мере, мы получим такую возможность.Опять же, возможно, из VB6 это автоматически перенаправляется, у меня нет установленной Win9X для проверки.
Option Explicit
Private Declare Function IsCharAlphaW Lib "unicows" (ByVal WChar As Integer) As Long
Private Function IsLetter(Character As String) As Boolean
IsLetter = IsCharAlphaW(AscW(Character))
End Function
Private Sub Main()
MsgBox IsLetter("^")
MsgBox IsLetter("A")
MsgBox IsLetter(ChrW$(&H34F))
MsgBox IsLetter(ChrW$(&HFEF0))
MsgBox IsLetter(ChrW$(&HFEFC))
End Sub
Немного осмотревшись, обнаружил следующее...
Private Declare Function IsCharAlphaA Lib "user32" Alias "IsCharAlphaA" (ByVal cChar As Byte) As Long
Я считаю, что IsCharAlphaA проверяет наборы символов ANSI, а IsCharAlpha проверяет ASCII.Возможно, я ошибаюсь.
Private Function IsAlpha(ByVal vChar As String) As Boolean
Const letters$ = "abcdefghijklmnopqrstuvwxyz"
If InStr(1, letters, LCase$(vChar)) > 0 Then IsAlpha = True
End Function
Я использую это в VBA
Function IsLettersOnly(Value As String) As Boolean
IsLettersOnly = Len(Value) > 0 And Not UCase(Value) Like "*[!A-Z]*"
End Function
Это не совсем документирует себя.И это может быть медленно.Это хитрый хак, но это все, что есть.Я бы хотел быть более очевидным в своих проверках.Либо используйте регулярные выражения, либо напишите более очевидный тест.
public bool IsAlpha(String strToCheck)
{
Regex objAlphaPattern=new Regex("[^a-zA-Z]");
return !objAlphaPattern.IsMatch(strToCheck);
}
public bool IsCharAlpha(char chToCheck)
{
return ((chToCheck=>'a') and (chToCheck<='z')) or ((chToCheck=>'A') and (chToCheck<='Z'))
}