2017-02-18 11 views
0

Scanfモジュールは幾分 それは下のチャネルの状態を尊重しない反し点で動作するように見える:チャネルが再作成されない限りScanf.Scanningのバッファを制御するには?

(* prepare test data *) 
let() = 
    let oc = open_out "test.txt" in 
    output_string oc "abcdefghij\n"; 
    close_out oc 
;; 

let ic = open_in "test.txt" 

(* ic at offset 0: “ab…” *) 
let() = 
    let sc = Scanf.Scanning.from_channel ic in 
    let s = Scanf.bscanf sc "%2s" (fun s -> s) in 
    Printf.eprintf "read [%s]\n" s (* -> [ab] *) 
;; (* sc out of scope at this point *) 

(* hint: close ic here and reopen for expected result *) 
seek_in ic 4 

(* ic at offset 4: “ef…” *) 
let() = 
    let sc = Scanf.Scanning.from_channel ic in 
    let s = Scanf.bscanf sc "%2s" (fun s -> s) in 
    Printf.eprintf "read [%s]\n" s (* -> [cd] ‽ *) 
;; 

close_in ic 

は明らかScanning.tの内部バッファは 生き残ります。 再同期を強制するもう1つの方法はありますか? 「読書は、ICの現在の読み取り位置から始まる。」というdocs 主張

は、私は、まさにこの動作が が文書化されている場所へのポインタをいただければと思います。

答えて

0

ちょうど一般的な設計原則では、Scanf.Scanning.from_channelへの呼び出しは、チャネルの責任をScanfモジュールに移すと言います。 Scanfモジュールの背後にあり、チャネルを直接操作する場合は、(ここではseek_inと同じように)動作することは保証されていません。

私が使った事実上すべてのレイヤードI/Oライブラリと同様に動作します。たとえば、fdopen()をUnix stdioから使用することはできず、FILE抽象化を介してデータを読み込むと同時に、基礎となるファイル記述子を任意の方法で操作することを期待しています。

ドキュメントにこれらの問題が記載されていれば(どちらの場合も)良いかもしれません。

+0

ほとんどの場合、定期的なテキストが散在していますので、ほとんどの場合、 '' Scanf''は必要ありません。 –

+0

テキストをバッファに読み込み、 'sscanf'を使うことができます。私の経験では、 'sscanf'はチャネルからのスキャンよりも使いやすく、より信頼できます。私は何十年もの間、生産コードでscanfを使っていません。あなたのテキストがシンプルなら 'int_of_string'などを使うこともできます。 FWIW。 –

関連する問題