Mantis Bug Tracker

View Issue Details Jump to Notes ] Issue History ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0004594OCamlCaml lightpublic2008-08-05 16:322012-02-02 15:19
Reportersmitley 
Assigned Toweis 
PrioritynormalSeverityminorReproducibilityalways
StatusclosedResolutionfixed 
PlatformOSOS Version
Product Version3.11+dev 
Target VersionFixed in Version3.10.0 
Summary0004594: scanf %s processing
DescriptionThe following program:

let fd = open_in "tst"
let printit s =
  Printf.printf "read %d %s\n" (String.length s) s;;
Scanf.fscanf fd "%s" printit;;
Scanf.fscanf fd "%s" printit;;

when run on the tst file with contents:
xxx yyy

produces the following output:
read 3 xxx
read 0

Ocaml versions prior to 3.10 produced the output:
read 3 xxx
read 3 yyy

TagsNo tags attached.
Attached Files

- Relationships

-  Notes
(0004600)
weis (developer)
2008-09-08 14:14

The behaviour you observed is conformant to the specification:

%s: reads a string argument that spreads as much as possible, until the
    following bounding condition holds: a whitespace has been found, a
    scanning indication has been encountered, or the end-of-input has been
    reached.
    Hence, this conversion always succeeds: it returns an empty
    string if the bounding condition holds when the scan begins.
 
The first scan returns "xxx" and ends on the space character. The second scan then starts on this space character; according to the specification, it stops immediately and returns an empty string.

If you want to skip the space, you simply have to mention it in the format: if the first format is "%s " then the second scan starts after the space (alternatively, the second scan may be " %s" to skip the space before scanning the second string).

Furthermore, as mentioned in the documentation, the usage of fscanf is kind of picky:

    To avoid confusion, consider using [bscanf] with an explicitly created
    scanning buffer. Use for instance [Scanning.from_file fname], to allocate
    the scanning buffer reading from file [fname] once and for all.

Therefore, I would suggest you avoid using fscanf as much as possible and use bscanf instead (let ib = Scanf.Scanning.from_file "tst" ...).

As you mentioned, Ocaml versions prior to 3.10 produced a different output; in fact, the scanner always skipped blanks after a %s specification; this was confusing in case of reading a file one line at a time, since reading the last field of a line would silently skip any amount of empty lines, thus preventing the detection and proper treatment of empty lines by the programmer.
(0004936)
weis (developer)
2009-04-29 20:39

This is not a bug, but a better behaviour to properly handle end of file conditions and empty lines.

- Issue History
Date Modified Username Field Change
2008-08-05 16:32 smitley New Issue
2008-08-05 16:41 xleroy Status new => assigned
2008-08-05 16:41 xleroy Assigned To => weis
2008-09-08 14:14 weis Note Added: 0004600
2008-09-08 14:37 weis Status assigned => resolved
2008-09-08 14:37 weis Resolution open => fixed
2009-04-29 20:39 weis Note Added: 0004936
2009-04-29 20:39 weis Status resolved => closed
2009-04-29 20:39 weis Fixed in Version => 3.10.0
2012-02-02 15:19 protz Category Caml-light => Caml light


Copyright © 2000 - 2011 MantisBT Group
Powered by Mantis Bugtracker