プログラミング言語 Standard ML 入門 (問題の解答例)
15 入出力処理

15.2 テキスト入出力

問 15.1

入力ファイル名のリストと出力ファイル名を受け取り,与えられたすべての入力ファ イルの内容を連結した内容を出力ファイルに書き出す関数
cat : string list -> string -> unit.  
を定義せよ.

解答例  以下に定義例を示す。

   local
     open TextIO
   in
     fun copyStream ins outs =
         if endOfStream ins then ()
         else case input1 ins of
                SOME c => (output1(outs,c);
                           copyStream ins outs)
              | NONE => copyStream ins outs
     fun cat L out =
         let
           val sources = map openIn L
           val sink = openOut out
         in
           (foldl (fn (x,_) => copyStream x sink) () sources;
            map closeIn sources;
            closeOut sink)
         end
   end
問 15.2

指定されたファイルの文字数と行数をプリントする関数
wc : string -> unit  
を定義せよ.

解答例  以下に定義例を示す。

   local
     open TextIO
   in
     fun wc file =
        let
          val ins = openIn file
          fun count (l,c) =
             if endOfStream ins then (l,c)
             else case input1 ins of
                SOME #"\n" => count (l+1, c+1)
              | SOME _ => count (l, c+1)
              | NONE => (l,c)
          val (l,c) = count (0,0)
          val _ = print (Int.toString l ^ " ")
          val _ = print (Int.toString c ^ "\n")
          val _ = closeIn ins
        in
          ()
        end
   end

以下はSML#でのテスト実行例である

   # wc "count.sml";
   20 503
   val it = () : unit
問 15.3

filterFile 関数を用いて,ファイルの中の文字をすべて小文字に変換した ファイルを作成する関数
lowerFile : string -> string -> unit  
を定義せよ.

解答例  以下に定義例を示す。

   fun lowerFile inf outf = filterFile Char.toLower inf outf
問 15.4

stdInstdOut を使用し,プロンプト文字 ? を 印字し,ユーザからの入力を受け取り,入力した文字をそのまま印字するプロ グラム
echo : unit -> unit  
を書け. たとえば,以下のような動作をする.
- echo(); abc abc 1234; 1234; ? val it = () : unit  
この例では,最後のプロンプトの後,ファイル終了文字を入力している.

解答例 

   fun echo () =
     let
       fun loop () =
           (print "? ";
            if TextIO.endOfStream TextIO.stdIn then ()
            else
              case TextIO.inputLine TextIO.stdIn of
                SOME string => (print string; loop ())
              | NONE => loop()
            )
     in
       loop()
     end