Poszukuję szybkiego sposobu (w języku C#), aby ustalić, czy ciąg znaków jest poprawną nazwą zmiennej. Moją pierwszą intuicją jest pobudzić jakiś regex, żeby to zrobić, ale zastanawiam się, czy jest lepszy sposób na zrobienie tego. Może jakaś tajna metoda ukryta głęboko pod nazwą IsThisAValidVariableName (nazwa napisu) lub inna łatwa do zrobienia metoda, która nie jest podatna na błędy, które mogą powstać z powodu braku sprawności wyrażenia regularnego.Jak ustalić, czy ciąg znaków jest poprawną nazwą zmiennej?
Odpowiedz
Spróbuj tego:
// using System.CodeDom.Compiler;
CodeDomProvider provider = CodeDomProvider.CreateProvider("C#");
if (provider.IsValidIdentifier (YOUR_VARIABLE_NAME)) {
// Valid
} else {
// Not valid
}
dłuższej drogi, plus jest znacznie wolniejsze, jest użycie refleksji iteracyjne nad członków klasy/nazw i porównać przez sprawdzenie czy odbitego członka ** toString (.) ** jest takie samo jak wejście łańcuchowe, wymaga to wcześniejszego wczytania zespołu.
Innym sposobem wykonania tej czynności (o wiele dłuższą drogą, która pokonuje użycie wyrażenia regularnego, przy użyciu już dostępnego skanera/parsera Antlr), jest graniczenie z parsowaniem/kopiowaniem kodu C#, a następnie skanowanie pod kątem nazw elementów (tj. Zmiennych) i porównując do ciągu znaków użytego jako dane wejściowe, na przykład wprowadź ciąg o nazwie "fooBar", a następnie podaj źródło (na przykład kod zespołu lub kod C#) i zeskanuj go, analizując szukając konkretnie deklaracji członków, takich jak na przykład
private int fooBar;
Tak, jest to skomplikowane, ale pojawi się potężne zrozumienie, gdy zdasz sobie sprawę z tego, co robią autorzy kompilatorów, i zwiększysz swoją znajomość języka C# do poziomu, w którym będziesz bardzo intymny z składnia i jej cechy szczególne.
Źle zrozumiałem pytanie. –
Istnieje kilka szczególnych przypadkach wokół postaci @
, które są łatwe do zapomnij sprawdzić - mianowicie '@'
sama w sobie nie jest poprawnym identyfikatorem, a nie jest "@1foo"
. Aby je złapać, możesz najpierw sprawdzić, czy ciąg znaków jest słowem kluczowym, a następnie usunąć @
od początku łańcucha, a następnie sprawdzić, czy to, co pozostało, jest prawidłowym identyfikatorem (nie dopuszczając znaków @
).
Połączyłem to z metodą analizowania sekwencji unikodowych Unicode w identyfikatorach i miejmy nadzieję, że zakończono sprawdzanie znaków w kodzie Unicode w C# (5.0). Aby z niego skorzystać, najpierw zadzwoń pod numer TryParseRawIdentifier()
, aby obsłużyć słowa kluczowe, sekwencje specjalne, znaki formatujące (które zostały usunięte) oraz dokładne identyfikatory. Następnie przekaż wynik do IsValidParsedIdentifier()
, aby sprawdzić, czy pierwszy i kolejne znaki są poprawne. Zwróć uwagę, że ciągi znaków zwrócone od TryParseRawIdentifier()
są równe wtedy i tylko wtedy, gdy identyfikatory są uważane za identyczne przez C#.
public static class CSharpIdentifiers
{
private static HashSet<string> _keywords = new HashSet<string> {
"abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked",
"class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else",
"enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for",
"foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock",
"long", "namespace", "new", "null", "object", "operator", "out", "override", "params",
"private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed",
"short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw",
"true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using",
"virtual", "void", "volatile", "while"
};
public static IReadOnlyCollection<string> Keywords { get { return _keywords; } }
public static bool TryParseRawIdentifier(string str, out string parsed)
{
if (string.IsNullOrEmpty(str) || _keywords.Contains(str)) { parsed = null; return false; }
StringBuilder sb = new StringBuilder(str.Length);
int verbatimCharWidth = str[0] == '@' ? 1 : 0;
for (int i = verbatimCharWidth; i < str.Length;) //Manual increment
{
char c = str[i];
if (c == '\\')
{
char next = str[i + 1];
int charCodeLength;
if (next == 'u') charCodeLength = 4;
else if (next == 'U') charCodeLength = 8;
else { parsed = null; return false; }
//No need to check for escaped backslashes or special sequences like \n,
//as they not valid identifier characters
int charCode;
if (!TryParseHex(str.Substring(i + 2, charCodeLength), out charCode)) { parsed = null; return false; }
sb.Append(char.ConvertFromUtf32(charCodeLength)); //Handle characters above 2^16 by converting them to a surrogate pair
i += 2 + charCodeLength;
}
else if (char.GetUnicodeCategory(str, i) == UnicodeCategory.Format)
{
//Use (string, index) in order to handle surrogate pairs
//Skip this character
if (char.IsSurrogatePair(str, i)) i += 2;
else i += 1;
}
else
{
sb.Append(c);
i++;
}
}
parsed = sb.ToString();
return true;
}
private static bool TryParseHex(string str, out int result)
{
return int.TryParse(str, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out result);
//NumberStyles.AllowHexSpecifier forces all characters to be hex digits
}
public static bool IsValidParsedIdentifier(string str)
{
if (string.IsNullOrEmpty(str)) return false;
if (!IsValidParsedIdentifierStart(str, 0)) return false;
int firstCharWidth = char.IsSurrogatePair(str, 0) ? 2 : 1;
for (int i = firstCharWidth; i < str.Length;) //Manual increment
{
if (!IsValidParsedIdentifierPart(str, i)) return false;
if (char.IsSurrogatePair(str, i)) i += 2;
else i += 1;
}
return true;
}
//(String, index) pairs are used instead of chars in order to support surrogate pairs
//(Unicode code-points above 2^16 represented using two 16-bit characters)
public static bool IsValidParsedIdentifierStart(string s, int index)
{
return s[index] == '_' || char.IsLetter(s, index) || char.GetUnicodeCategory(s, index) == UnicodeCategory.LetterNumber;
}
public static bool IsValidParsedIdentifierPart(string s, int index)
{
if (s[index] == '_' || (s[index] >= '0' && s[index] <= '9') || char.IsLetter(s, index)) return true;
switch (char.GetUnicodeCategory(s, index))
{
case UnicodeCategory.LetterNumber: //Eg. Special Roman numeral characters (not covered by IsLetter())
case UnicodeCategory.DecimalDigitNumber: //Includes decimal digits in other cultures
case UnicodeCategory.ConnectorPunctuation:
case UnicodeCategory.NonSpacingMark:
case UnicodeCategory.SpacingCombiningMark:
//UnicodeCategory.Format handled in TryParseRawIdentifier()
return true;
default:
return false;
}
}
}
public static bool IsIdentifier(string text)
{
if (string.IsNullOrEmpty(text))
return false;
if (!char.IsLetter(text[0]) && text[0] != '_')
return false;
for (int ix = 1; ix < text.Length; ++ix)
if (!char.IsLetterOrDigit(text[ix]) && text[ix] != '_')
return false;
return true;
}
- 1. Upewnij się, że ciąg jest poprawną nazwą CSS o nazwie
- 2. Jak ustalić, czy ciąg znaków jest identyfikatorem SID użytkownika?
- 3. Jak przekonwertować ciąg znaków na prawidłową nazwę zmiennej w python?
- 4. Jak ustalić, czy ciąg zawiera któryś ze znaków specjalnych?
- 5. Jak ustalić, czy ciąg zawiera konkretny podłańcuch
- 6. Jak ustalić, czy ciąg ma niealfanumeryczne znaki?
- 7. Jak ustalić ciąg jest angielski lub perski?
- 8. Funkcja sprawdzania, czy ciąg znaków jest datą
- 9. Jak sprawdzić, czy ciąg znaków jest xml?
- 10. Jak sprawdzić, czy ciąg znaków może być używany jako nazwa zmiennej w PHP?
- 11. Jak ustalić, czy dany ciąg reprezentuje datę?
- 12. Dlaczego spacja jest poprawną nazwą kolumny w SqlServer?
- 13. Jak sprawdzić, czy ciąg znaków jest prawidłową zmienną języka Java?
- 14. Jak ustalić, czy ciąg nie jest wyrażeniem regularnym?
- 15. java - Jak sprawdzić, czy ciąg znaków jest prawidłową nazwą elementu XML?
- 16. Czy mogę określić, czy ciąg znaków jest identyfikatorem obiektu MongoDB?
- 17. Sprawdź, czy ciąg znaków jest adresem URL
- 18. Sprawdź, czy ciąg znaków jest obrazem
- 19. Jak ustalić, czy ciąg "kończy się" innym ciągiem w R?
- 20. Ruby, sprawdź, czy ciąg znaków jest prawidłowy?
- 21. Sprawdź, czy ciąg znaków interpunkcyjnych jest
- 22. Sprawdzanie, czy ciąg znaków jest pusty
- 23. Ustal, czy ciąg znaków jest "pusty".
- 24. Szyny: możliwe sprawdzenie, czy ciąg znaków jest binarny?
- 25. Czy xmlns = "" jest poprawną przestrzenią nazw xml?
- 26. Jak sprawdzić, czy ciąg jest numeryczny?
- 27. Jak ustalić, czy drzewo binarne jest kompletne?
- 28. Jak ustalić, czy obiekt jQuery jest odroczony?
- 29. Jak ustalić, czy powiązanie szyn jest przyspieszone?
- 30. Jak ustalić, czy jednostka doktrynalna jest trwała?
masz na myśli C# nazwę zmiennej? I myślę, że regex to twój najlepszy zakład, chyba że rzucisz swoją małą parserem (co jest przesadą dla tak małej rzeczy do sprawdzenia). – Earlz
Jedna rzecz, na którą należy zwrócić uwagę, jeśli używasz wyrażenia regularnego, jest to, że istnieje kilka klas znaków uinicode być może trzeba będzie wziąć pod uwagę: http://msdn.microsoft.com/en-us/library/aa664670%28VS.71%29.aspx –
+1 brak zaufania do premii regex – bobince