C#에서 Int.TryParse를 사용한 고급 구문 분석

18130 단어 dotnetcsharp
다음 서명과 함께 int.TryParse 메서드를 사용했을 것입니다.

public static bool TryParse (string? s, out int result);


이 C# 메서드는 s 문자열을 허용합니다. 이 문자열은 구문 분석할 수 있는 경우 int 값으로 변환되고 해당 정수 값은 result 매개 변수에 저장됩니다. 동시에 메서드는 true를 반환하여 구문 분석이 성공했음을 알립니다.

예를 들어 이 스니펫은 다음과 같습니다.

if (int.TryParse("100", out int result))
{
    Console.WriteLine(result + 2); // correctly parsed as an integer
}
else
{
    Console.WriteLine("Failed");
}


102를 인쇄합니다.

작동합니까? 예. 이것이 우리가 할 수 있는 최선입니까? 아니!

int.TryParse로 복잡한 문자열을 구문 분석하는 방법



100€를 파싱하려면 어떻게 해야 합니까? 작업을 수행하는 잘 알려지지 않은 과부하가 있습니다.

public static bool TryParse (
    string? s,
    System.Globalization.NumberStyles style, 
    IFormatProvider? provider, 
    out int result);


보시다시피 styleprovider 라는 두 개의 매개변수가 더 있습니다.
IFormatProvider? provider를 사용하면 문화권 정보를 지정할 수 있습니다. 예는 CultureInfo.InvariantCulturenew CultureInfo("es-es") 입니다.

하지만 이 오버로드의 진짜 왕은 style 매개변수입니다. 예상되는 문자열 형식을 지정할 수 있는 매개변수는 Flagged Enum입니다.
styleSystem.Globalization.NumberStyles 유형이며 여러 값이 있습니다.

[Flags]
public enum NumberStyles
{
    None = 0x0,
    AllowLeadingWhite = 0x1,
    AllowTrailingWhite = 0x2,
    AllowLeadingSign = 0x4,
    AllowTrailingSign = 0x8,
    AllowParentheses = 0x10,
    AllowDecimalPoint = 0x20,
    AllowThousands = 0x40,
    AllowExponent = 0x80,
    AllowCurrencySymbol = 0x100,
    AllowHexSpecifier = 0x200,
    Integer = 0x7,
    HexNumber = 0x203,
    Number = 0x6F,
    Float = 0xA7,
    Currency = 0x17F,
    Any = 0x1FF
}


이러한 값을 | 기호와 결합할 수 있습니다.

몇 가지 예를 살펴보겠습니다.

정수로 구문 분석



가장 간단한 예는 간단한 정수를 구문 분석하는 것입니다.

[Fact]
void CanParseInteger()
{
    NumberStyles style = NumberStyles.Integer;
    var canParse = int.TryParse("100", style, new CultureInfo("it-it"), out int result);

    Assert.True(canParse);
    Assert.Equal(100, result);
}


기준선으로 사용되는 NumberStyles style = NumberStyles.Integer; 에 주목하십시오.

괄호를 음수로 구문 분석



경우에 따라 숫자 주변의 괄호는 숫자가 음수임을 나타냅니다. 따라서 (100)은 -100을 쓰는 또 다른 방법입니다.

이 경우 NumberStyles.AllowParentheses 플래그를 사용할 수 있습니다.

[Fact]
void ParseParenthesisAsNegativeNumber()
{
    NumberStyles style = NumberStyles.Integer | NumberStyles.AllowParentheses;
    var canParse = int.TryParse("(100)", style, new CultureInfo("it-it"), out int result);

    Assert.True(canParse);
    Assert.Equal(-100, result);
}


통화로 구문 분석



문자열이 통화를 나타내는 경우? NumberStyles.AllowCurrencySymbol를 사용할 수 있습니다.

[Fact]
void ParseNumberAsCurrency()
{
    NumberStyles style = NumberStyles.Integer | NumberStyles.AllowCurrencySymbol;
    var canParse = int.TryParse(
"100€",
 style,
 new CultureInfo("it-it"), 
out int result);

    Assert.True(canParse);
    Assert.Equal(100, result);
}


그러나 유효한 기호는 메서드에 전달하는 CultureInfo 인스턴스와 관련된 기호뿐입니다.

둘 다

var canParse = int.TryParse(
    "100€", 
    style, 
    new CultureInfo("en-gb"), 
    out int result);


그리고

var canParse = int.TryParse(
    "100$", 
    style, 
    new CultureInfo("it-it"), 
    out int result);


유효하지 않습니다. 하나는 영국 문화를 사용하여 유로를 분석하기 때문이고, 다른 하나는 이탈리아 문화를 사용하여 달러를 분석하기 때문입니다.

힌트: CultureInfo에서 통화 기호를 얻는 방법은 무엇입니까? 다음과 같이 NumberFormat.CurrecySymbol 를 사용할 수 있습니다.

new CultureInfo("it-it").NumberFormat.CurrencySymbol; // €


천 단위 구분 기호로 구문 분석



문자열에 천 단위 구분 기호가 포함되어 있으면 어떻게 해야 할까요? 10.000은 이탈리아어 표기법으로 유효한 숫자입니다.

음, NumberStyles.AllowThousands 플래그를 지정할 수 있습니다.

[Fact]
void ParseThousands()
{
    NumberStyles style = NumberStyles.Integer | NumberStyles.AllowThousands;
    var canParse = int.TryParse("10.000", style, new CultureInfo("it-it"), out int result);

    Assert.True(canParse);
    Assert.Equal(10000, result);
}


16진수 값 구문 분석



드문 경우지만 발생할 수 있습니다. 16진수 표기법으로 문자열을 받지만 정수로 구문 분석해야 합니다.

이 경우 NumberStyles.AllowHexSpecifier가 올바른 플래그입니다.

[Fact]
void ParseHexValue()
{
    NumberStyles style = NumberStyles.AllowHexSpecifier;
    var canParse = int.TryParse("F", style, new CultureInfo("it-it"), out int result);

    Assert.True(canParse);
    Assert.Equal(15, result);
}


입력 문자열에는 16진수 접두사가 포함되어 있지 않습니다.

여러 플래그 사용



여러 Flagd Enum을 구성하여 지정된 값의 합집합을 나타내는 새 값을 만들 수 있습니다.

이 기능을 사용하여 예를 들어 천 단위 구분 기호가 포함된 통화를 구문 분석할 수 있습니다.

[Fact]
void ParseThousandsCurrency()
{
    NumberStyles style = 
NumberStyles.Integer 
| NumberStyles.AllowThousands 
| NumberStyles.AllowCurrencySymbol;

    var canParse = int.TryParse("10.000€", style, new CultureInfo("it-it"), out int result);

    Assert.True(canParse);
    Assert.Equal(10000, result);
}

NumberStyles.AllowThousands | NumberStyles.AllowCurrencySymbol가 트릭을 수행합니다.

결론



우리 모두는 간단한int.TryParse 방법을 사용하지만 입력 문자열을 구문 분석하는 데 더 복잡한 계산이 필요한 경우 이러한 오버로드에 의존할 수 있습니다. 물론 여전히 충분하지 않은 경우 사용자 지정 파서를 만들어야 합니다(또는 더 간단한 접근 방식으로 정규식을 사용할 수 있음).

아무도 사용하지 않는 오버로드가 있는 메서드가 있습니까? 의견에 공유하십시오!

즐거운 코딩하세요!

🐧

좋은 웹페이지 즐겨찾기