2017年6月2日金曜日

strtok_r によるネスト化されたトークンの切り出し

strtok_r によるネスト化されたトークンの切り出しの例題です。 テキストファイルを読み込み、単語ごとにハッシュ表を作成し、出現する頻度を表示する例題も兼ねています。

strtok 関数はスレッドセーフ化されておらず、再入可能(リエントラント)な利用には向いていません。
strtok 自体が最初の引数で与えられた文字列を変更してしまうためや、内部で確保された文字列の中身を変更してトークンとして切り出しているためです。
while 内に while 文で strtok を呼び出したり、別のスレッドで strtok を呼び出した場合、最後に呼び出された strtok により内部の文字列が変更され、思い通りの結果が得られないと言う状況が発生します。
また、ある関数で strtok を使っていて、その結果から別の関数を呼び出した場合、ソース上からは見えない状況で正しい結果が得られないと言うことにもなり得ます。
strtok_r はこのような状況においても現在扱っている文字列の処理に影響が及ぶことはありません。

以下のソースでは、テキストファイルの内容を全てメモリ内に格納した後、strtok_r にて改行(\n)とスペース( )により単語を抜き出し、ハッシュテーブルへの登録や頻度のカウントを行っています。
loadHashBAD 関数は strtok により処理を行うもので、思い通りの結果が得られていないことが分かります(一行目の単語しか抽出できない)。
loadHash 関数にて strtok_r を利用することにより全ての行の単語が抽出されます。 実行結果(strtok を使用した場合:loadHashBAD) 実行結果(strtok_r を使用した場合:loadHash) file.txt の内容

0 件のコメント:

コメントを投稿