Skip to content
Strings and Printf
step 1/7

Reading — step 1 of 7

Learn

~3 min readLists, Recursion, IO

OCaml strings are immutable (since 4.06). The String module and Printf are the daily-use tools.

Basic operations

let s = "hello"
String.length s                    (* 5 *)
String.get s 0                     (* 'h' — 0-indexed *)
s.[0]                              (* 'h' — sugar for String.get *)
String.sub s 1 3                   (* "ell" — start, length *)
String.uppercase_ascii s            (* "HELLO" *)
String.lowercase_ascii s            (* "hello" *)
String.concat ", " ["a"; "b"]      (* "a, b" *)
String.split_on_char ',' "a,b,c"   (* ["a"; "b"; "c"] *)
String.contains s 'e'              (* true *)
String.equal "a" "a"               (* true; or use = *)
String.compare a b                  (* -1, 0, 1 *)
String.trim "  hi  "               (* "hi" *)

String concatenation — ^

"Hello, " ^ "World"                (* "Hello, World" *)
let name = "Ada" in
"Hi, " ^ name ^ "!"

The ^ operator concatenates strings. It's O(n) — not great for many appends. Use Buffer (below) or String.concat for that.

Buffer — efficient building

let buf = Buffer.create 16 in
Buffer.add_string buf "Hello";
Buffer.add_string buf ", ";
Buffer.add_string buf "World";
Buffer.contents buf                (* "Hello, World" *)

For repeated concatenation in a loop, much faster than ^.

Printf — formatted output

Printf.printf "%s is %d\n" "Ada" 36
Printf.printf "%.2f\n" 3.14159     (* 3.14 *)
Printf.printf "%x\n" 255            (* ff *)
Printf.printf "%-10s|\n" "hi"        (* "hi        |" — left-pad *)

Format specifiers: %s (string), %d (int), %f (float), %c (char), %b (bool), %x (hex), %a (custom — pass a printer fn).

TYPE-CHECKED format strings

The format string is checked at COMPILE TIME against the arguments:

Printf.printf "%d\n" "hello"
(* Error: This expression has type string but an expression was expected of type int *)

Every %s requires a string arg, every %d an int — typos fail to compile. Far safer than printf in C.

sprintf — to a string

let s = Printf.sprintf "%s: %d" "x" 42  (* "x: 42" *)

Same as printf but returns a string instead of printing.

Reading input

let line = read_line ()             (* reads to newline, strips \n *)
let n = int_of_string line

(* All of stdin: *)
let rec read_all acc =
  try read_all (read_line () :: acc)
  with End_of_file -> List.rev acc

read_line () returns one line. EOF raises End_of_file. int_of_string parses; float_of_string for floats.

Strings vs bytes

OCaml has TWO related types:

  • string — immutable
  • bytes — mutable

Most code uses string. For mutating buffers, use bytes or Buffer.

Common mistakes

  • == vs === is physical equality (rarely what you want); = is structural. "a" == "a" may be false; "a" = "a" is true.
  • Using ^ in tight loops — O(n²). Use Buffer.
  • Forgetting \n in printf — output is buffered; you may not see it until flush. Add explicit newline.
  • Mixing string and char'a' is a char; "a" is a string. Different types.
  • String mutation attempts — strings are immutable since 4.06. Use bytes for mutable.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…