challenge 条件を満たす行を取り除く

ファイルから1行ずつ読み込み、"#"で始まる行だけを取り除いてファイルに出力するコードを書いてください。

サンプル入力

hello!
# remove this
 # don't remove this
bye!
サンプル出力
hello!
 # don't remove this
bye!

Posted feedbacks - OCaml

まんまF#でやってみました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
open System;;
open System.Text;;
open System.IO;;
open Array;;

let fileIO (ifname:string) (ofname:string) =
    let streamW = new StreamWriter( ofname, false, Encoding.Default ) in
    let streamR = new StreamReader( ifname, Encoding.Default ) in
    let rmCommentLn (wstream:StreamWriter) =
        let rec readf (rstream:StreamReader) =
            let line = rstream.ReadLine() in
            if line = null then ()
            else
                begin
                    if not (line.StartsWith "#")
                    then wstream.WriteLine line
                    else ();
                    readf rstream
                end
        in using streamR readf
    in using streamW rmCommentLn;;

if (length Sys.argv) = 3
then fileIO Sys.argv.(1) Sys.argv.(2)
else ();;

ループを使わずにストリームでやってみました。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
(* 関数合成 *)
let ($) f g x = f (g x)

let _ =
  (* ファイルのオープン *)
  let input =
    open_in "input_file"
  in
  let output =
    open_out "output_file"
  in
  (* 一行ずつ読み込むストリーム作成 *)
  let lines =
    Stream.from (fun _ ->
      try
    Some (input_line input)
      with
    _ -> None)
  in
  (* 正規表現で判定する *)
  let exp = 
    Str.regexp "^#"
  in
  (* 条件にマッチしたら空文字列を返す *)
  let filter str =
    if Str.string_match exp str 0  then
      ""
    else
      str ^ "\n"
  in
  (* ループでやらずにストリームで処理するところが関数型言語の肝 *)
  Stream.iter (output_string output $ filter) lines;
  (* 後始末 *)
  close_in input;
  close_out output

再帰関数で書いてみました。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
let rec work (file,str) =
  let line =
    try 
      Some (input_line file)
    with
      _ -> None
  in  match line with
        None -> str
      | Some line -> work (file,str^(if ((String.get line 0) = '#') then "" else line^"\n"));;

let in_file = open_in "./hellow.txt";;
let out_file = open_out "./newhellow.txt";;
output_string out_file (work (in_file,""));;
close_in in_file;;
close_out out_file;;

改行入りのinput_lineも欲しいなぁ。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let rm_line ?(c='#') fname =
  let rec loop r w =
    try
      let l = input_line r ^ "\n" in
      if (l.[0] <> c) then (output_string w l);
      loop r w
    with err -> 
      close_in r; close_out w;
      if err = End_of_file
      then Sys.rename (fname^".tmp") fname;
  in loop (open_in fname) (open_out (fname^".tmp"));;

Index

Feed

Other

Link

Pathtraq

loading...