Access Count : 710
Copyright © 2020 TAKEHANA TADASHI
著作日時: 2020.09.26.土. 20:53:00 著作者、竹花 忠
配布、配信、公然での口述、販売、改変、をしないでください。
情報支援プログラム、TjShiensection.hsの設計構想の骨子:
<ソースコード>
これは、Haskell言語によるプログラムです。
まず、本プログラムの全ソースコードは下記の通りです。
{-概要・予備知識
プログラム起動時、プログラム名の次の引数に、検索対象とするファイルの名前を指定します。
"検索文字列:"のプロンプトに対して、検索対象とするファイル中の1セクションに含まれいる文字列1個をタイプ入力して改行します。
すると、→行以下に、その文字列が含まれているセクションがすべて表示されます。
なお、セクションとは、空行で隔てられた各範囲です。
"検索文字列:"のプロンプトに対して、改行だけを入力すると本プログラムは終了します。
-}
import Data.List
import System.IO
import System.Directory
import System.Environment
import Control.Exception
import Control.Monad
main = do
args <- getArgs
let
[targetFile] = args
argcnt = length args
if argcnt /= 1
then
putStrLn "使い方 : \nTjShiensection 検索対象ファイル名"
else do
contents <- readFile targetFile
let
lineContents = lines contents
sectionContents = packSections lineContents
pickupSectionLoop sectionContents
{-
ただし、上記の
let
lineContents = lines contents
sectionContents = packSections lineContents
pickupSectionLoop sectionContents
このコードは、
pickupSectionLoop . packSections . lines $ contents
と記述することもできる。
-}
--packSections lineContents
packSections :: [String] -> [String]
packSections [] = []
packSections lineContents@("":xs) =
let
(h,t) = break (/= "") lineContents
in
packSections t
packSections lineContents =
let
(h,t) = break (== "") lineContents
in
(unlines h) : packSections t
--pickupSectionLoop sectionContents
pickupSectionLoop :: [String] -> IO ()
pickupSectionLoop sectionContents = do
putStrLn "検索文字列 : "
searchString <- getLine
if null searchString
then
putStrLn "情報支援プログラム:TjShiensectionは、終了しました!!"
else do
let
selectSections = filter (isInfixOf searchString) sectionContents
putStrLn "→"
mapM_ putStrLn selectSections
putStrLn ""
pickupSectionLoop sectionContents
{-
ただし、上記の
let
selectSections = filter (isInfixOf searchString) sectionContents
putStrLn "→"
mapM_ putStrLn selectSections
putStrLn ""
pickupSectionLoop sectionContents
このコードは、
putStrLn "→"
mapM_ putStrLn . filter (isInfixOf searchString) $ sectionContents
putStrLn ""
pickupSectionLoop sectionContents
もしくは、
putStrLn "→"
mapM_ ((\(b, s) -> if b then putStrLn s else return ()) . (\s -> (isInfixOf searchString s, s))) sectionContents
putStrLn ""
pickupSectionLoop sectionContents
と記述することもできる。
-}
<設計構想の骨子>
情報支援プログラム、TjShiensection.hsでは、セクション内に検索文字列があるかないかによる、セクションの採否の決定を行う。
各セクションをそれぞれ文字列1個にする。そして、それらの文字列によるリストを用意する。
そうすれば、関数filterを使用して、その述語に関数isInfixOfを使って、そしてまた先に用意したリストを処理対象リストとして使って、検索文字列を含んでいるセクションのリストアップができる。
関数filterで検索文字列を含むセクションをリストアップできたら、あとは、そのリストを表示すれば完成である。
さて、ふりだしに戻って、このプログラム゛ては、まず初めに、検索対象ファイルから全内容を、文字列1個として取得する。
つまり、contents <- readFile targerFileである。
これによって、contentsにファイルの全内容が文字列個として取得される。
この後、先に述べた通り、関数filterで利用するのに適したセクションごとに1個の文字列の、文字列のリストに、ファイルから読み込みだ1個の文字列を、変換・編集、する。
ところで、セクションとは何かというと、それは、空行の連なりで隔てられた、空行ではない行の連なった範囲である。
さて、セクションが取り出せるためには、空行とそれ以外の行との区別がつけられることが必要である。
関数linesを使用すれば、空行は、""になり、それ以外の行は、""以外の文字列となる。
つまり、""かそれ以外の文字列かで、空行かそれ以外の行であるかが区別できる。
そこで、lineContents = lines contentsを行う。
これによって、空行が""でそれ以外の行が""以外の文字列となる。そのような文字列によるリストが、lineContentsである。
次は、そのlineContentstから、セクション文字列を要素としたリストを取得する。
セクション文字列、つまり、""以外の文字列の連なりの範囲による文字列、を取り出すのに役立つ関数は、関数breakである。
関数breakを使用すれば、""の連なりの範囲を取り出したり、""以外の文字列の連なりの範囲を取り出したりできる。
break (/= "")、""以外が出現した所でリストを分割。break (== "")、""が出現した所でリストを分割。
これらを交互に使用することで、""以外の文字列の範囲を次々に取り出してゆける。
それによって、""以外の文字列の範囲を1個の文字列とした、セクション文字列、を要素としたリストを取得しているのが、
sectionContents = packSections lineContents
である。
セクション文字列を要素としたリストを取得する際の、具体的な、関数breakほかの使い回しの仕方は、関数packSectionsに書かれている通りである。
最後に、各セクションを1個の文字列とした、それらの文字列からなるリストであるsectionContentsをわたして、関数pickupSectionLoopを実行する。
ここではまず、検索文字列を取得する。
そして、検索文字列とセクション文字列を照合して、検索文字列が含まれたいたセクション文字列をリストアップする。
リストアップしたセクション文字列はすべて表示する。
ここでの以上の動作を繰り返し実行する。
そうすることで、様々な検索文字列に対してのリストアップ結果を表示させてゆける。
それを実行しているのが、
pickupSectionLoop sectionContents
である。
そのようなことで、この情報支援プログラム、TjShiensection.hsは完成している。
プログラムコードの詳しい解説については、情報支援プログラムTjShiensection.hsの解説用文書を参照してください。