Search code examples
algorithmsml

Remove the first char to extract an integer (unhandled exception: Subscript)


I'm trying to write a function which extracts only the integer in a string.

All my strings have the format Ci where C is a single character and i is an integer. I would like to be able to remove the C from my string.

I tried something like this :

fun transformKripke x = 
    if size x > 1
    then String.substring (x, 1, size x)
    else x

But unfortunately, I get an error like unhandled exception: Subscript. I assume it's because sometimes my string will be empty and size of empty string is not working. But I don't know how to make it work... :/

Thanks in advance for your help

Best Regards.


Solution

  • The problem is calling String.substring (x, 1, size x) when x is not long enough.

    The following should fix your immediate problem:

    fun transformKripke s =
        if size s = 0
        then s
        else String.substring (s, 1, size s)
    

    or slightly prettier:

    fun transformKripke s =
        if size s = 0
        then s
        else String.extract (s, 1, NONE)  (* means "until the end" *)
    

    But you may want to consider naming your function something more general so that it can be useful in more senses than performing a Kripke transform (whatever that is). For example, you may want to be able to extract an actual int the first time one occurs anywhere in a string, regardless of how many non-integer characters that precede it:

    fun extractInt s =
        let val len = String.size s
            fun helper pos result =
                if pos = len
                then result
                else let val c = String.sub (s, pos)
                         val d = ord c - ord #"0"
                     in case (Char.isDigit c, result) of
                           (true, NONE)     => helper (pos+1) (SOME d)
                         | (true, SOME ds)  => helper (pos+1) (SOME (ds * 10 + d))
                         | (false, NONE)    => helper (pos+1) NONE
                         | (false, SOME ds) => SOME ds
                     end
        in helper 0 NONE
        end