Kyle Sargent
Kyle Sargent

Reputation: 21

How to use OCaml Scanf module to parse a string containing integers separated by spaces WITHOUT Str

The title basically says it all. I am aware that through the use of regexp via OCaml's Str module, this task is quite simple - however, suppose you are only allowed to use the standard library and Scanf module. I am interested in taking a string looks like this:

    "12 34 555 6 23 34 5663 234 ..."

And returning an array that looks like this

  [|12; 34; 555; 6; 23; 34; 5663; 234; |]

Can someone help me out? I found the Scanf documentation (available http://caml.inria.fr/pub/docs/manual-ocaml/libref/Scanf.html) to be pretty unhelpful in understanding how to use the module

Upvotes: 1

Views: 2689

Answers (3)

coredump
coredump

Reputation: 38809

Not sure how idiomatic it is, but it works:

let parse_integers s =
  let stream = (Scanning.from_string s) in
  let rec do_parse acc =
    try
      do_parse (Scanf.bscanf stream " %d " (fun x -> x :: acc))
    with
      Scan_failure _ -> acc
    | End_of_file -> acc
  in Array.of_list (List.rev (do_parse []));;

A little test:

# parse_integers " 20 3 22";;
- : int array = [|20; 3; 22|]

(Update)

As explained in comments, the above code is not tail-recursive, whereas the following one is:

...
let rec do_parse acc = 
  match (Scanf.bscanf stream " %d " (fun x -> x :: acc)) 
with 
  | xs -> do_parse xs 
  | exception Scan_failure _ -> acc 
  | exception End_of_file -> acc
in ...

Upvotes: 2

V. Michel
V. Michel

Reputation: 1619

let rec f acc s =
  if s="" then
    Array.of_list (List.rev acc)
  else
    Scanf.sscanf s "%d %[^\n]" (fun n s-> f (n::acc) s)
;;



f [] "12 34 555 6 23 34 5663 234";;
# - : int array = [|12; 34; 555; 6; 23; 34; 5663; 234|]

Upvotes: 0

Jeffrey Scofield
Jeffrey Scofield

Reputation: 66803

The format string for all the Scanf functions specifies a fixed number of values; thus, you can't expect to use a function from Scanf to read a variable number of values from a string.

If you break your string into pieces, you can use Scanf.sscanf s "%d" (fun x -> x) to translate each piece into an int. However, the function int_of_string is much simpler for that purpose.

I'd say you should start by breaking the string into pieces.

Upvotes: -1

Related Questions