Utility operations for converting to and from strings.
The StringCvt structure provides types and functions for handling the conversion between strings and values of various basic types.structure StringCvt : STRING_CVT
signature STRING_CVT = sig datatype radix = BIN | OCT | DEC | HEX datatype realfmt = SCI of int option | FIX of int option | GEN of int option | EXACT type ('a,'b) reader = 'b -> ('a * 'b) option val padLeft : char -> int -> string -> string val padRight : char -> int -> string -> string val splitl : (char -> bool) -> (char, 'a) reader -> 'a -> string * 'a val takel : (char -> bool) -> (char, 'a) reader -> 'a -> string val dropl : (char -> bool) -> (char, 'a) reader -> 'a -> 'a val skipWS : (char, 'a) reader -> 'a -> 'a type cs val scanString : ((char, cs) reader -> ('a, cs) reader) -> string -> 'a option end
[~]?[0-9].[0-9]+?E[0-9]+where there is always one digit before the decimal point, nonzero if the number is nonzero. The optional integer value specifies the number of decimal digits to appear after the decimal point, with 6 being the default. In particular, if 0 is specified, there should be no fractional part. The exponent is zero if the value is zero. A value (FIX opt) corresponds to a fixed-point representation:
[~]?[0-9]+.[0-9]+?where there is always at least one digit before the decimal point. The optional integer value specifies the number of decimal digits to appear after the decimal point, with 6 being the default. In particular, if 0 is specified, there should be no fractional part. A value (GEN opt) allows a formatting function to use either the scientific or fixed-point notation, whichever is shorter, breaking ties in favor of fixed-point. The optional integer value specifies the maximum number of significant digits used, with 12 the default. The string should display as many significant digits as possible, subject to this maximum. There should not be any trailing zeros after the decimal point. There should not be a decimal point unless a fractional part is included. The fourth constructor EXACT specifies that the string should represent the real using an exact decimal representation. The string contains enough information in order to reconstruct a semantically equivalent real value using REAL.fromDecimal o valOf o IEEEReal.fromString. Refer to the description of IEEEReal.toString for more precise information concerning this format. In all cases, positive and negative infinities are converted to "inf" and "~inf", respectively, and NaN values are converted to the string "nan".
takel f rdr s = #1(splitl f rdr s)
(char, 'a) reader -> (ty, 'a) readerCharacter readers are provided for the common sources of characters, either explicitly, such as the SUBSTRING.getc and STREAM_IO.input1 functions, or implicitly, such as the TEXT_IO.scanStream. As an example, suppose we expect to read a decimal integer followed by a date from TextIO.stdIn. This could be handled by the following code:
local structure TIO = TextIO structure SIO = TextIO.StreamIO val scanInt = Int.scan StringCvt.DEC SIO.input1 val scanDate = Date.scan SIO.input1 in fun scanID () = case scanInt (TIO.getInstream TIO.stdIn) of NONE => raise Fail "No integer" | SOME (intVal, ins') => case scanDate ins' of NONE => raise Fail "No date" | SOME (dateVal, _) => (intVal,dateVal)In this example, we used the underlying stream I/O component of TextIO.stdIn, which is cleaner and more efficient. If, at some later point, we wish to return to the imperative model and do input directly using TextIO.stdIn, we need to reset it with the current stream I/O value using TextIO.setInstream. Alternatively, we could rewrite the code using imperative I/O:
local structure TIO = TextIO val scanInt = TIO.scanStream (Int.scan StringCvt.DEC) val scanDate = TIO.scanStream Date.scan in fun scanID () = case scanInt TIO.stdIn of NONE => raise Fail "No integer" | SOME intVal => case scanDate TIO.stdIn of NONE => raise Fail "No date" | SOME dateVal => (intVal,dateVal)The scanString function was designed specifically to be combined with the scan function of some type T, producing a function val fromString : string -> T option for the type. For this reason, scanString only returns a scanned value, and not some indication of where scanning stopped in the string. For the user who wants to receive a scanned value and the unscanned portion of a string, the recommended technique is to convert the string into a substring and combine scanning functions with Substring.getc, e.g., Bool.scan Substring.getc. Or, the user can create an input stream with TextIO.openString using the string as the source. When the input source is a list of characters, scanning values can be accomplished by applying the appropriate scan function to the function List.getItem. Thus, Bool.scan List.getItem has the type
(bool, char list) readerwhich will scan a boolean value and return that value and the remainder of the list.