crscanf v0.2.0

scanf implementation for Crystal-lang

Scanf

This shard provides a compile-time scanf(fmt) macro backed by C sscanf.

scanf(fmt) returns a lambda that parses an input String and returns a typed Tuple.

GitHub release

Installation

Add scanf to your dependencies in your shard.yml file:

dependencies:
  scanf:
    github: tenebrousedge/crscanf
    branch: master

Then run shards install.

Usage

This shard exposes a global scanf macro:

  • fmt must be a compile-time string literal.
  • The returned lambda takes one String input.
  • The lambda returns a typed Tuple.

Example:

a = scanf("%3s %d").call("abc 123")
puts a #=> {"abc", 123}
puts typeof(a) #=> Tuple(String, Int32)

lam = scanf("%f -- %c")
b = lam.call("1234 -- q2")
puts b #=> {1234.0, "q"}
puts typeof(b) #=> Tuple(Float32, String)

Supported Surface

Feature Status
%d, %i, %u, %o, %x, %X Supported
hh, h, l, ll integer modifiers Supported
%f, %F, %e, %E, %g, %G, %a, %A Supported
l floating modifier Supported
%c, %s, %[...] Supported
Assignment suppression (*) Supported
%n Supported (without width or suppression)
%% Supported
%p Unsupported (compile-time rejection)
j, z, t Unsupported
L Unsupported
Wide-character conversions (%lc, %ls, %l[...]) Unsupported
Runtime format strings Unsupported
Embedded NUL input Rejected
Checked numeric overflow Not guaranteed

Semantics and Limits

  • Format must be a compile-time string literal.
  • Results are returned as a tuple.
  • Suppressed assignments are omitted from the returned tuple.
  • Literal-only formats return Tuple.new.
  • Incomplete matches raise Scanf::MatchError.
  • Trailing input after a completed format is permitted.
  • Floating-point parsing and some character classification follow the active C locale.
  • This library does not change process locale.
  • Numeric input outside destination C type range is unsupported: libc may hit undefined behavior before Crystal regains control.
  • %c width is a maximum; fewer bytes may be read at end-of-input.

More Examples

Integers:

scanf("%d %i %x").call("42 010 ff") # => {42, 8, 255}

Strings:

scanf("%3s %s").call("abcdef rest") # => {"abc", "def"}

Scansets:

scanf("%[^,]").call("hello,world") # => {"hello"}
scanf("%[]]").call("]]]X")          # => {"]]]"}

Suppression:

scanf("%*d %d").call("10 20") # => {20}

Failure handling:

begin
  scanf("%dX").call("1Y")
rescue Scanf::MatchError
  puts "format did not complete"
end

Compile-time format rejection:

# This fails to compile: format must be a literal.
format = "%d"
scanf(format)

This shard intentionally targets string scanning through sscanf. Direct scanning from IO streams is not provided.

Warning

scanf is a dangerous tool. It can easily result in undefined behavior. Test your format strings carefully. This implementation has at least as many bugs as the C version, and likely more.

Development

This shard requires no special libraries, aside from the Crystal compiler. Bugs should be reported via the GitHub issues list.

Optional developer checks:

# Runtime suite under C locale
LC_ALL=C crystal spec

# Compile-time format harness
bash spec/format_compile_spec.sh

# Non-default stress target
crystal spec spec/stress_runtime.cr

Some Crystal toolchains can run under sanitizers. If your local compiler and linker support it, you can try:

crystal spec --link-flags "-fsanitize=address"

This sanitizer command is optional and is not required by the normal test suite.

Contributing

  1. Fork it (https://github.com/your-github-user/scanf/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors

Repository

crscanf

Owner
Statistic
  • 0
  • 0
  • 0
  • 0
  • 0
  • about 4 hours ago
  • June 17, 2026
License

MIT License

Links
Synced at

Fri, 07 Aug 2026 00:11:34 GMT

Languages