Scanf

このページは最後に更新されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

last mod. 2009-09-10 (木) 17:07:46

Chapter 20 標準ライブラリ

module Scanf: sig .. end

フォーマット入力関数

Introduction

Functional input with format strings

Scanfモジュールは、フォーマット入力関数、すなわちスキャナを提供します。

フォーマット入力関数は、文字列やファイル、その他文字を返すどんなものからでも読み出すことができます。より一般的な入力元は、scanning bufferと呼ばれ、Scanf.Scanning.scanbug?型を持ちます。より一般的なフォーマット入力関数はどんなscanning bufferからも読み込むことができ、bscanfと呼ばれます。

一般的には、フォーマット入力関数は3つの引数を取ります。

  • 第1引数: 入力元
  • 第2引数: 読み込む値を決定するフォーマット文字列
  • 第3引数: 読み込んだ値が適用される受け取り関数(receiver funciton)

なので、フォーマット入力関数のScanf.bscanfは、bscanf ib fmt fで呼ばれ、

  • ibは入力元(Scanf.Scanning.scanbuf型のscanning bufferが多い)
  • fmtはフォーマット文字列(Printf?Format?モジュールで使われるものと同じ)
  • fは読み込む値と同じ数の引数を持つ関数

A simple example

上で述べたように、bscanf ib "%d" fは入力元ibから10進整数nを読み込み、f nを返す。

例えば、

  • 入力元としてstdibを使い(Scanf.Scanning.stdibは標準入力から読み込む入力バッファ)
  • fをlet f x = x + 1と定義すれば bscanf stdib "%d" fは整数nを標準入力から受け取りf n (すなわちn + 1)を返す。すなわち、bscanf stdib "%d" fを評価し,41をキーボードで入力すれば、42を最終的な結果として受け取る。

Formatted input as a functional feature

Camlのscan機能は、Cの同様の機能に似ている。しかし、大きく異なる点もあり、よりシンプルで、より強力である。フォーマット入力関数は高階関数でりパラーメタは通常の関数と同様に渡され、一般的な手続き言語のように変数に直接代入はしない。Camlのフォーマット文字列は簡単に複雑なトークンを定義できる。また、関数型言語で期待されるように、フォーマット入力関数はポリモルフィズムをサポートし、ユーザ定義のポリモルフィックスキャナとやり取りできる。さらに、Camlのフォーマット文字列はコンパイル時に型チェックが行なわれる。

module Scanning: sig .. end

Scanning buffers

Type of formatted input functions

type ('a, 'b, 'c, 'd) scanner = ('a, Scanning.scanbuf, 'b, 'c, 'a -> 'd, 'd) format6 -> 'c

フォーマット入力関数の型。('a, 'b, 'c, 'd) scannerはどこかのscanning bufferからフォーマット文字列に従って入力を読み込むフォーマット入力関数の型です。より正確には、scanがフォーマット入力関数とすると、scan ib fmt fはフォーマット文字列fmtに従って読み込んだ引数をfに適用します。そのとき入力はscanning bufferであるibから読み込みます。例えば、scanf関数は('a, 'b, 'c, 'd) scanner型を持つので、stdibから読み込む:scanf ffmtはフォーマット文字列によって指定された引数をfに適用する、そのとき引数はstdinから読み込まれる。

フォーマッ文字列fmtに%rが指定された場合、対応する入力関数を受け取り関数の前に渡す必要がある。例えば、read_elemがt型の値を読み込む場合、bscanf ib "%r;" read_elem fは型tの値vと文字";"を読み込む。そして、f vを返す。

exception Scan_failure of string

入力が与えられたフォーマットに一致しないときに、発生する例外。

The general formatted input function

val bscanf : Scanning.scanbuf -> ('a, 'b, 'c, 'd) scanner

bscanf ib fmt r1 ... rN fはscanning buffer ibから、フォーマット文字列fmtに従って、関数fに適用します。fの返り値は、bscanf全体の返り値になります。例えば、fがfun s i -> i+1ならば、Scanf.sscanf "x= 1" "%s = %i" fは2を返します。

r1 to rNは対応する%rに対する入力関数です。

Format string description

フォーマット文字列は、以下の3種類の要素を含んでいます。

  • 通常の文字。入力された文字と単純にマッチします。
  • 変換指定子。入力を読み込み、変換をし、fに対する引数になります
  • トークンの境目を示すscanning indication

The space character in format strings

上記のように、フォーマット文字内の通常の文字は入力内の文字と単純にマッチする。しかし、ある文字はこのシンプルなルールの例外となっている。空白文字(ASCIIコード32)は単一の空白文字にマッチするのではなく、すべてのホワイトスペースとマッチします。より正確にはフォーマット文字列内のスペースは任意の数のタブ、スペース、ラインフィード、キャリッジリターンとマッチします。

Matching any amount of whitespace, a space in the format string also matches no amount of whitespace at all; hence, the call bscanf ib "Price = %d $" (fun p -> p) succeds and returns 1 when reading an input with various whitespace in it, such as Price = 1 $, Price = 1 $, or even Price=1$.

Conversion specificationstrings

Conversion specifications consist in the % charar, followed by an optional flag, an optional field width, an. x or X: reads an unsigned hexadecimal integer. o: reads an s: reads a string argument that spreads as much as possible, until the following bounding condition holds: a whitespace has n found, a scanning indication has been encountered, or the en reached. Hence, this conversion always succeeds: it returns an, if the bounding condition holds when the scan begins. S: read string argument (delimiters and special escaped characters folaml). c: reads a single character. To test the current input cheld width, i.e. use specification %0c. Raise Invalid_argument, a single delimited character (delimiters and special escaped ch, e, E, g, G: reads an optionally signed floating-point number decimal notation, in the style dddd.ddd e/E+-dd. F: reads a floumber according to the lexical conventions of Caml (hence the dtory if the exponent part is not mentioned). B: reads a booleantrue or false). b: reads a boolean argument (for backward companot use in new programs). ld, li, lu, lx, lX, lo: reads an int3ied by the second letter (decimal, hexadecimal, etc). nd, ni, n argument to the format specified by the second letter. Ld, Li,nt to the format specified by the second letter. [ range ]: reaoned in the range of characters range (or not mentioned in it, not match the range. The set of characters from c1 to c2 (incluurns a string representing a decimal number or an empty string nge, it must occur as the first character of the range (or just function and applies it to the scanning buffer ib to read the i must therefore have type Scanning.scanbuf -> 'a and the argum: reads a format string argument. The format string read must hcation fmt. For instance, "%\( %i% \)" reads any format string that can read a value of type int; hence Scanf.sscanf "\\\"%4d\ read so far. n: returns the number of characters read so far. ns read so far. !: matches the end of input condition. %: matchFollowing the % character that introduces a conversion, there mrsion that follows occurs as usual, but the resulting value is ters; and %8[\\000-\\255] returns the next 8 characters (or allavailable, if fewer than 8 characters are available in the inpu convertion always succeeds, even if there is nothing to read ior heavy duty lexical analysis and parsing. If it appears not expressive enough for your needs, several alternative exists: reted lexers, ocamlyacc-generated parsers.

Scanning indicationsar just after the string conversions %s and %[ range ] to delimintroduced by a @ character, followed by some constant characteoken should end just before the next matching c (which is skippred, the string token spreads as much as possible. For instancenext tab character or to the end of input. If a scanning indica conversion, it is treated as a plain c character. Note:

the s hence, when producing formatted text to be scanned by !Scanf.bthe Format module (or, if you need to use functions from Printfle check the format strings that contain '@' characters).

Excy raise the following exceptions when the input cannot be read can_failure if the input does not match the format. Raise Failu not possible. Raise End_of_file if the end of input is encountded to read the current conversion specification. Raise Invaliding is invalid. Note: as a consequence, scanning a %s conversioile: if the end of input is reached the conversion succeeds ands the characters read so far, or "" if none were read.

Specian_channel -> ('a, 'b, 'c, 'd) scanner Same as Scanf.bscanf, butacters, seeking the reading position, and so on).

As a consequdirect low level reading and high level scanning from the same ing -> ('a, 'b, 'c, 'd) scanner Same as Scanf.bscanf, but readsgiven string. val scanf : ('a, 'b, 'c, 'd) scanner Same as Scanf.bscanf, but reads from the predefined scanning buffer Scanf.Scanning.stdib that is connected to stdin. val kscanf : Scanningcanning process or some conversion fails, the scanning function scanning process.

Reading format strings from input

val bscaanning.scanbuf ->

      ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
 ording to the given format string fmt, and applies f to the resailure if the format string value read does not have the same t->
      ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
      (('a, 'b, t, but reads from the given string.

val format_from_string : stgument to a format string, according to the given format string as a format string, does not have the same type as fmt.

新規 編集 添付