John Rennemeyer
John Rennemeyer

Reputation: 465

How would I remove all commas not inside parenthesis from a string in C#?

I have a mathparser that can do functions like "IntPow(3,2)". If a user pastes "1,000,000" and then adds a plus symbol, making the full equation "1,000,000+IntPow(3,2)" the parser fails because it does not work with numbers that contain commas.

I need to remove the commas from the "1,000,000", but not from the "IntPow(3,2)" because IntPow has two parameters separated by a comma. The final equation will be "1000000+IntPow(3,2)". The equation is stored in one string. How would I remove only the commas that are outside of parenthesis? I'm assuming and saying that numbers that contain commas will not be placed inside the IntPow parameters list.

When I say "remove commas" I really mean remove "CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator" which could be a comma or a period depending on the local. This part will be easy because I assume RegEx will be used and I can just concatentate that value in the RegEx comma place.

I have this RegEx: (.*?) for finding the parenthesis and values inside of them but I'm not sure how to only remove the commas outside of the RegEx matches.

Upvotes: 0

Views: 1631

Answers (4)

Mouk
Mouk

Reputation: 1737

I don't think this is possible using regular expressions. Distinguishing between inside and outside parenthesis is not a regular language. It is a context non-sensitive language that can’t be decided using a regular state machine (expression). You need a stack machine (i.e. something link the decided by Chad)

Upvotes: 1

Sam Axe
Sam Axe

Reputation: 33738

Sub Main()

    '
    '   remove Commas from a string containing expression-like syntax
    '       (eg.  1,000,000 + IntPow(3,2) - 47 * Greep(9,3,2) $ 5,000.32 )
    '       should become:  1000000 + IntPow(3,2) - 47 * Greep(9,3,2) $ 5000.32
    '

    Dim tInput As String = "1,000,000 + IntPow(3,2) - 47 * Greep(9,3,2) $ 5,000.32"
    Dim tChar As Char = Nothing
    Dim tResult As StringBuilder = New StringBuilder(tInput.Length)
    Dim tLevel As Integer = 0

    For Each tChar In tInput
        Select Case tChar
            Case "("
                tLevel += 1
                tResult.Append(tChar)

            Case ")"
                tLevel -= 1
                tResult.Append(tChar)

            Case ","   '  Change this to your separator character.
                If 0 < tLevel Then
                    tResult.Append(tChar)
                End If

            Case Else
                tResult.Append(tChar)

        End Select
    Next

    Console.ForegroundColor = ConsoleColor.Cyan
    Console.WriteLine(tInput)
    Console.WriteLine(String.Empty)
    Console.ForegroundColor = ConsoleColor.Yellow
    Console.WriteLine(tResult.ToString)
    Console.WriteLine()
    Console.ResetColor()
    Console.WriteLine(" -- PRESS ANY KEY -- ")
    Console.ReadKey(True)

End Sub

Upvotes: 1

Chad Birch
Chad Birch

Reputation: 74548

The easiest way is to not try and make a regex do this. Just loop over the string one character at a time. If you read a '(', increment a counter. If you read a ')', decrement that counter. If you read a comma, delete it if the counter is 0, otherwise leave it alone.

Upvotes: 6

Andomar
Andomar

Reputation: 238076

But what if a user pastes:

1,000+IntPow(3,000,2,000)

Now the 3,000 is between comma's.

Upvotes: 2

Related Questions