プロが教える店舗&オフィスのセキュリティ対策術

C言語のisgraph関数

<C++>
UINT uint = 66;
if(isgraph(uint)){}

をPerlに書き換えようとしたんですが、

<Perl>
$uint = 66;
if(??? =~ /[:graph:]/){}

ここまでしか分かりませんでした。
Perlへの正しい変換を教えてください。

A 回答 (6件)

細かいことですが、isgraphに対応するのは、


[:graph:]ではなくて、[:print:]じゃありませんか?
([:graph:]は0x20含んでますから)


sub isgraph {
  my $key = shift @_;
  $key =~ /^[\x21-\x7E]+$/ ? return 1 : return 0;
}

このような感じで書いておけば、
C同様、 if(isgraph($value)){ … } でいけます。
(エラーチェックなどは省略してますが)

コードを渡したいのであれば文字に変換を一行追加する必要がありますけれど。
    • good
    • 0
この回答へのお礼

$uint = 0x20;
if(pack("C",$uint) =~ /[[:graph:]]/){
print 'TRUE';
} else {
print 'FALSE';
}

は、natsuki_tkさんと異なる結果で、Cと同じくFALSEを得ることができました。
ロケールの違いでしょうか。
上の訂正がこのことでしょうか?

でも、natsuki_tkさんの/[\x21-\x7E]/の方が速いでしょうし、
packも必要ないからそれを使うことにして、[:graph:] は使わないことにしました。
将来、isgraphの範囲の定義が変更されることを考えれば
[:graph:]を使用した方がいいんでしょうけど。

ありがとうございました。

お礼日時:2003/09/06 23:00

>$c = ' '; # $c = ('c', 0x20);


>printf("'%s' is NOT a graphic character.\n", $c) if ($c !~ /[[:graph:]]/);
>はちゃんと真になりましたよ?

申し訳ありません。
印刷可能と表示可能を勘違いしておりました。

graph [:alnum:] [:punct:]
print [:alnum:] [:punct:] 空白

ですので、この場合[:graph:]で全く問題無いのですね(^^;
ろくに確認もせずすみませんでした。
    • good
    • 0

お礼をどうもありがとうございます。

まず、補足くださった疑問点から
片付けていきましょう。

>[]の2重についてのことが分からないんですが、正規表現の
>[abc] #aかbかcのorという意味
>というorの意味が、/[[:graph:]]/の内か外の[]にあてはまりますか?

文字クラスの意味は、No.2 の方のご説明通りです。「[:alpha:]」を例にとって考えれば、
「[[:alpha:]]」は「[ABC..Za..z]」のように要素を列挙するのではなく、
「[A-Za-z]」のように範囲指定しているものだと思います。だから、

>[:graph:]でひとつの文字クラスです。文字クラスは[]で囲んで表現しますから、
>[[:graph:]]でワンセットです。

便宜的に「[:alpha:]」は「A-Za-z」に置き換わると考えてください。
つまり、「/[[:alpha:]]/」として初めて「/[A-Za-z]/」の意味になります。
これを角括弧を外して、「/A-Za-z/」と書いては意味を成しませんね。
ですから、以下のコードは間違いということになります。

>if ($c =~ /[:graph:]/) {...}

次はPOSIX モジュールを使う場合の補足です。
回答 No.3 のように書くと POSIX 準拠の関数すべてがインポート(輸入)
されてしまいますので、無駄を省くために

use POSIX qw(isgraph); # isgraph のみインポート

または

use POSIX qw(:ctype_h);
# 標準ヘッダ ctype.h で定義されているシンボルをすべてインポート

としてください。
それから、if や unless は文修飾子として用いたほうが一層効率的です。

printf("'%s' is a graphic character.\n", $c) if ($c =~ /[[:graph:]]/);

最後に No.4 の方のご指摘について。

>細かいことですが、isgraphに対応するのは、
>[:graph:]ではなくて、[:print:]じゃありませんか?
>([:graph:]は0x20含んでますから)

そうなのですか?Cでの定義とは異なりますね。
(Cの is 系関数は文字1個しか引数に取れないところも違いますが)
でも、手元の Perl v.5.6.1(Turbolinux Workstation 8.0 上の)では、

$c = ' '; # $c = ('c', 0x20);

printf("'%s' is NOT a graphic character.\n", $c) if ($c !~ /[[:graph:]]/);

はちゃんと真になりましたよ?
ホワイトスペースは定義通り弾かれているようですが。
    • good
    • 0
この回答へのお礼

[]が2重になる理由が理解できました。
POSIXは使ったことがなくて分かりませんでしたが、Perlへの移植が成功したのでまんぞくしました。
ありがとうございました。

お礼日時:2003/09/06 23:03

こんにちは。

文字コードから文字への変換には pack 関数を使います。

$c = pack('c', $uint);

そしてこの文字を使います。

if ($c =~ /[[:graph:]]/) {...}

こういう書き方もできるようです。

if ($c =~ /\p{IsGraph}/) {...}

ただし、文字としてありえない値を与えたときの挙動は両者で異なります。
前者は黙って無視しますが、後者は "Malformed UTF-8 character"
何とかかんとかというエラーが出ます。"$uint = 1000;" などで試してみてください。

おなじみの is 系関数を使いたいならば、POSIX モジュールを使うのが簡単でしょう。

use POSIX;

$c = pack('c', $uint);
if (isgraph($c)) {...}

参考URL:http://sk.redbit.ne.jp/~letzh/perl/sc/14.html

この回答への補足

こんにちは。
[]の2重についてのことが分からないんですが、正規表現の
[abc] #aかbかcのorという意味
というorの意味が、/[[:graph:]]/の内か外の[]にあてはまりますか?
あてはまるとすると、
if ($c =~ /[:graph:]/) {...}
のようなソースもありえることになると思いますが、
if ($c =~ /[:graph:]/) {...}
のようなソースはありえるんでしょうか?

is...のようなものは、必ず/[[...]]/のように、最低でも[]が2つ必要なんでしょうか?

補足日時:2003/09/06 15:31
    • good
    • 0

ご質問が「isgraph()を使うようなシチュエーションで、Perlのやり方でうまくやりたい」のか、「Perlを使ってisgraph()とまったく仕様が同じ関数を実装したい」のかどちらなのか分からないので、前者と仮定してお答えします。



C言語ではcharが数値を保持する型であるため、文字の判定関数は引数をintで受けるものが多いようですが、Perlでは文字を扱う演算子や関数に数値を与えることはできません。そのため66ではなく文字リテラルで'B'と書く必要があります。

それから、[:graph:]でひとつの文字クラスです。文字クラスは[]で囲んで表現しますから、[[:graph:]]でワンセットです。

以下のコードを実行すると"True"と表示されます。

$uint = 'B';
if ($uint =~ /[[:graph:]]/) {print "True\n"}

この回答への補足

ありがとうございました。
[]の理解が間違っていたみたいで

$uint = 66;
if(pack("C",$uint) =~ /[[:graph:]]/){
 print 'TRUE';
} else {
 print 'FALSE';
}

のように[]を2重にするとできました。

Perlの:graph:の動作とは無関係で、C言語のisgraph()関数
の移植なんですが、ロケールは考えないとしてこれでいいですか?

補足日時:2003/09/06 15:18
    • good
    • 0

int isgraph(int c);


 次の文字に一致したらゼロ以外の値を、一致しなければゼロ返します
 スペース ( ' ' ) を除く印字可能文字( ASCIIコードの0x21-0x7E )

この意味を考えて、Perl版を作成してください。
http://www1.cts.ne.jp/~clab/hsample/Func/Func05. …

参考URL:http://www1.cts.ne.jp/~clab/hsample/Func/Func05. …
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!