home > 写経編 > Brian W.Kernighan, P.J.Plauger『ソフトウェア作法』 > 2.種々のフィルタ >

ForNext

Only Do What Only You Can Do

2.4. 文書情報の圧縮

VBScript

JScript

Perl

更新日 : 2008.12.26
use strict;
#******************************************************************************
#   文書情報の圧縮
#******************************************************************************
my  $c              =   "";
my  $EOF            =   "\0\0";
my  $NEWLINE        =   "\n";

my  @buf            =   [];
my  $lastc          =   "";

my  $nrep           =   1;
my  $nsave          =   0;

my  $RCODE          =   "\0";
my  $MAXCHUNK       =   255;
my  $THRESH         =   4;

for ($lastc = get_char(); $lastc ne $EOF; $lastc = $c)
{
    # 違う文字が出てくるまで 読む
    for ($nrep = 1; ($c = get_char()) eq $lastc; $nrep++)
    {
        last if ($nrep >= $MAXCHUNK);
    }

    if ($nrep < $THRESH)
    {
        # 繰り返し回数が 閾値未満なら、バッファに ためる
        for ( ; $nrep > 0; $nrep--)
        {
            $nsave++;
            $buf[$nsave] = $lastc;

            # $MAXCHUNK 以上には、ためない
            put_buf() if ($nrep >= $MAXCHUNK);
        }
    }
    else
    {
        # 繰り返し回数が 閾値を超えたら、バッファ内容を出力
        put_buf();

        # 反復の目印
        put_char($RCODE);

        # 繰り返される文字
        put_char($lastc);

        # 繰り返す回数
        put_char($nrep);
        put_char($RCODE);
    }
}
# 残りの バッファ内容を出力
put_buf();

#==============================================================================
#   バッファ内容を出力
#==============================================================================
sub put_buf
{
    if ($nsave > 0)
    {
        # 文字数
        put_char($nsave);
        put_char($RCODE);

        # バッファ内容
        my $i;
        for $i (1..$nsave)
        {
            put_char($buf[$i]);
        }
    }
    $nsave  =   0;
}

#==============================================================================
#   1文字 取得
#==============================================================================
my  $current_line   =   "";
my  $pos            =   -1;

sub get_char
{
    my  $char;

    # まだ読んでなかったら
    if ($current_line eq "")
    {
        # 1行読む
        $current_line = <STDIN>;

        # ファイルの終わりなら 終了
        return  $EOF    if  (!$current_line);

        # 改行コードを取り除く
        chomp($current_line);

        # 現在位置 クリア
        $pos    =   0;
    }

    # 行の終わりに達したら
    if ($pos >= length($current_line))
    {
        # 現在行 クリア
        $current_line = "";

        # 行の終わりを 知らせる
        return $NEWLINE;
    }

    # 半角 / 全角
    if  (substr($current_line, $pos, 1) =~ /^[\x80-\xff]/)
    {
        # 2バイト取得
        $char   =   substr($current_line, $pos, 2);
        $pos    +=  2;
    }
    else
    {
        # 1バイト取得
        $char   =   substr($current_line, $pos, 1);
        $pos++;
    }

    return $char;
}

#==============================================================================
#   1文字 出力
#==============================================================================
my  $buffer         =   "";

sub put_char
{
    ($_)    =   @_;

    if  ($_ eq  $NEWLINE)
    {
        # 行の終わりなら 出力
        print   $buffer, "\n";
        $buffer =   "";
    }
    else
    {
        # 行の終わりでなければ、バッファにためる
        $buffer .=  $_;
    }
}

PHP

更新日 : 2008.12.26
<?php
#******************************************************************************
#   TAB の 除去
#******************************************************************************
$c              =   "";
$EOF            =   "\0";
$current_line   =   "";
$pos            =   -1;
$NEWLINE        =   "\n";
$buffer         =   "";
$TAB            =   "\t";
$BLANK          =   " ";
$col            =   0;
$tabs           =   array();
$MAXCOL         =   80;

settab();

while (($c = get_char()) != $EOF)
{
    if ($c == $NEWLINE)
    {
        put_char($c);
        $col    =   0;
    }
    else if ($c == $TAB)
    {
        do
        {
            put_char($BLANK);
            $col++;
        }
        while (!tabpos($col));
    }
    else
    {
        put_char($c);
        $col    +=   strlen($c);
    }
}
#==============================================================================
#   TAB 位置 の 初期設定
#==============================================================================
function settab()
{
    global $MAXCOL;
    global $tabs;

    for ($i = 1; $i <= $MAXCOL; $i++)
    {
        $tabs[$i - 1] = ($i % 4 ==  0);
    }
}

#==============================================================================
#   TAB 位置か?
#==============================================================================
function tabpos($col)
{
    global $MAXCOL;
    global $tabs;

    if ($col > $MAXCOL)
    {
        for ($i = $MAXCOL + 1; $i <= $col; $i++)
        {
            $tabs[$i - 1] = ($i % 4 ==  0);
        }
    }

    $MAXCOL =   $col;

    return  $tabs[$col - 1];
}

#==============================================================================
#   1文字 取得
#==============================================================================
function get_char()
{
    global $fp;
    global $EOF;

    global $current_line;
    global $pos;
    global $NEWLINE;

    $char   =   "";

    # まだ読んでなかったら
    if ($current_line == "")
    {
        # まだ OPEN してなかったら
        if ($pos == -1)
        {
            $fp = fopen("php://stdin", "r");
        }

        # 1行読む
        $current_line   =   fgets($fp);

        # ファイルの終わりなら 終了
        if (feof($fp))
        {
            fclose($fp);
            return  $EOF;
        } 

        # 改行コードを取り除く
        $current_line   =   rtrim($current_line, "\n\r");

        # 現在位置 クリア
        $pos    =   0;
    }

    # 行の終わりに達したら
    if ($pos >= strlen($current_line))
    {
        # 現在行 クリア
        $current_line = "";

        # 行の終わりを 知らせる
        return $NEWLINE;
    }

    # 半角 / 全角
    if  (mb_ereg('^[\x80-\xff]', substr($current_line, $pos, 1)))
    {
        # 2バイト取得
        $char   =   substr($current_line, $pos, 2);
        $pos    +=  2;
    }
    else
    {
        # 1バイト取得
        $char   =   substr($current_line, $pos, 1);
        $pos++;
    }

    return $char;
}

#==============================================================================
#   1文字 出力
#==============================================================================
function put_char($char)
{
    global $NEWLINE;
    global $buffer;

    if  ($char  ==  $NEWLINE)
    {
        # 行の終わりなら 出力
        echo    $buffer, "\n";
        $buffer =   "";
    }
    else
    {
        # 行の終わりでなければ、バッファにためる
        $buffer .=  $char;
    }
}
?>

Python

Ruby

更新日 : 2008.12.26
#******************************************************************************
#   TAB の 除去
#******************************************************************************

#==============================================================================
#   1文字 取得
#==============================================================================
$current_line   =   []
$pos            =   -1
$NEWLINE        =   "\n"
$EOF            =   "\0";

def get_char
    # まだ読んでなかったら
    if $current_line.size   ==  0
        # 1行読む
        line    =   $stdin.gets

        # ファイルの終わりなら 終了
        return  $EOF    unless  line

        # 改行コードを取り除く
        line.chomp!;

        # 文字の配列に分解
        $current_line   =   line.split(//s)

        # 現在位置 クリア
        $pos        =   0;
    end

    # 行の終わりに達したら
    if $pos >= $current_line.size
        # 現在行 クリア
        $current_line   =   []

        # 行の終わりを 知らせる
        return $NEWLINE;
    end

    char    =   $current_line[$pos]
    $pos    +=  1

    return char
end

#==============================================================================
#   1文字 出力
#==============================================================================
$buffer =   ""

def put_char(char)
    if  char    ==  $NEWLINE
        # 行の終わりなら 出力
        puts    $buffer
        $buffer =   ""
    else
        # 行の終わりでなければ、バッファにためる
        $buffer <<  char
    end
end

#==============================================================================
#   TAB 位置 の 初期設定
#==============================================================================
$tabs           =   [];
$MAXCOL         =   80;

def settab()
    for i in (1.. $MAXCOL)
        $tabs[i - 1] = (i % 4   ==  0)
    end
end

#==============================================================================
#   TAB 位置か?
#==============================================================================
def tabpos(col)
    if (col > $MAXCOL)
        for i in (($MAXCOL + 1)..col)
            $tabs[i - 1] = (i % 4   ==  0)
        end
    end

    $MAXCOL =   col

    return  $tabs[col - 1];
end

#==============================================================================
#   TAB の 除去
#==============================================================================
c               =   ""
TAB             =   "\t"
BLANK           =   " "
col             =   0

settab

while (c = get_char) != $EOF
    if (c == $NEWLINE)
        put_char c
        col =   0
    elsif (c == TAB)
        begin
            put_char BLANK
            col +=  1
        end until tabpos(col)
    else
        put_char c
        col +=   c.length
    end
end

PowerShell

Scala

F#

C

C++

C++Builder

VC++

C#

Java

Objective-C

D

VB

VB.NET

Delphi

Ada

PL/SQL

T-SQL

関数型

inserted by FC2 system