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

ForNext

Only Do What Only You Can Do

2.1. TAB の復元

VBScript

JScript

Perl

更新日 : 2008.12.26
use strict;
#******************************************************************************
#   TAB の 復元
#******************************************************************************
my  $c              =   "";
my  $EOF            =   "\0";
my  $NEWLINE        =   "\n";
my  $TAB            =   "\t";
my  $BLANK          =   " ";
my  $col_read       =   0;
my  $col_write      =   0;
my  @tabs           =   [];
my  $MAXCOL         =   80;

settab();

while (($c = get_char()) ne $EOF)
{
    # 空白なら
    if ($c eq $BLANK) 
    {
        # 出力せずに、読み込み現在位置を1つ進める
        $col_read++; 
    }
    # TABなら
    elsif ($c eq $TAB)
    {
        # 出力せずに、読み込み現在位置をTAB位置まで進める
        ++$col_read while (!tabpos($col_read));
    }
    # 改行コードなら
    elsif ($c eq $NEWLINE)
    {
        # 改行コードを出力
        put_char($c);
        # 読み込み現在位置をクリア
        $col_read   =   0;
        # 書き込み現在位置をクリア
        $col_write  =   0;
    }
    # 空白でもTABでも改行コードでもなかったら
    else
    {
        # 読み込み現在位置と書き込み現在位置が一致していない
        if ($col_read ne $col_write)
        {
            # 書き込み現在位置から、読み込み現在位置まで
            my $col;
            for $col ($col_write+1 .. $col_read)
            {
                # TAB位置なら
                if (tabpos($col))
                {
                    # TABを出力
                    put_char($TAB);
                    # 書き込み現在位置をTAB位置まで進める
                    $col_write  =   $col;
                }
            }
            # 書き込み現在位置から、読み込み現在位置まで
            for (; $col_write < $col_read; $col_write++)
            {
                # 空白で埋める
                put_char($BLANK);
            }
        }
        # 読んだ文字をそのまま出力
        put_char($c);
        # 読み込み現在位置を文字幅だけ進める
        $col_read   += length($c);
        # 書き込み現在位置を文字幅だけ進める
        $col_write  =   $col_read;
    }
}

#==============================================================================
#   TAB 位置 の 初期設定
#==============================================================================
sub settab
{
    for (1.. $MAXCOL)
    {
        $tabs[$_ - 1] = ($_ % 4 ==  0);
    }
}

#==============================================================================
#   TAB 位置か?
#==============================================================================
sub tabpos
{
    my ($col)   =   @_;

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

    $MAXCOL =   $col;

    return  $tabs[$col - 1];
}

#==============================================================================
#   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_read       =   0;
$col_write      =   0;
$tabs           =   array();
$MAXCOL         =   80;

settab();

while (($c = get_char()) != $EOF)
{
    # 空白なら
    if ($c == $BLANK) 
    {
        # 出力せずに、読み込み現在位置を1つ進める
        $col_read++; 
    }
    # TABなら
    else if ($c == $TAB)
    {
        # 出力せずに、読み込み現在位置をTAB位置まで進める
        while (!tabpos(++$col_read));
    }
    # 改行コードなら
    else if ($c == $NEWLINE)
    {
        # 改行コードを出力
        put_char($c);
        # 読み込み現在位置をクリア
        $col_read   =   0;
        # 書き込み現在位置をクリア
        $col_write  =   0;
    }
    # 空白でもTABでも改行コードでもなかったら
    else
    {
        # 読み込み現在位置と書き込み現在位置が一致していない
        if ($col_read != $col_write)
        {
            # 書き込み現在位置から、読み込み現在位置まで
            for ($col = $col_write+1; $col <= $col_read; $col++)
            {
                # TAB位置なら
                if (tabpos($col))
                {
                    # TABを出力
                    put_char($TAB);
                    # 書き込み現在位置をTAB位置まで進める
                    $col_write  =   $col;
                }
            }
            # 書き込み現在位置から、読み込み現在位置まで
            for (; $col_write < $col_read; $col_write++)
            {
                # 空白で埋める
                put_char($BLANK);
            }
        }
        # 読んだ文字をそのまま出力
        put_char($c);
        # 読み込み現在位置を文字幅だけ進める
        $col_read   += strlen($c);
        # 書き込み現在位置を文字幅だけ進める
        $col_write  =   $col_read;
    }
}
#==============================================================================
#   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_read        =   0
col_write       =   0

settab

while (c = get_char) != $EOF
    # 空白なら
    if (c == BLANK) 
        # 出力せずに、読み込み現在位置を1つ進める
        col_read    +=  1
    # TABなら
    elsif (c == TAB)
        # 出力せずに、読み込み現在位置をTAB位置まで進める
        col_read += 1   while (!tabpos(col_read))
    # 改行コードなら
    elsif (c == $NEWLINE)
        # 改行コードを出力
        put_char c
        # 読み込み現在位置をクリア
        col_read    =   0
        # 書き込み現在位置をクリア
        col_write   =   0
    # 空白でもTABでも改行コードでもなかったら
    else
        # 読み込み現在位置と書き込み現在位置が一致していない
        if (col_read != col_write)
            # 書き込み現在位置から、読み込み現在位置まで
            for col in col_write+1 .. col_read
                # TAB位置なら
                if (tabpos(col))
                    # TABを出力
                    put_char TAB
                    # 書き込み現在位置をTAB位置まで進める
                    col_write   =   col
                end
            end
            # 書き込み現在位置から、読み込み現在位置まで
            for col_write in col_write .. col_read-1
                # 空白で埋める
                put_char BLANK
            end
        end
        # 読んだ文字をそのまま出力
        put_char c
        # 読み込み現在位置を文字幅だけ進める
        col_read    += c.length
        # 書き込み現在位置を文字幅だけ進める
        col_write   =   col_read
    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