プロが教えるわが家の防犯対策術!

DFAを受理するプログラムを組んでいるのですが、コンパイルして動作させるとすぐに終わってしまいます。
どこがいけないのでしょうか…。助言を求めています。
手探りでやっているのですが、ファイル読み込みなど、基本的な所からわかっていない状態です。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>


enum { NFA_0_2_3_5, NFA_0_1_2_3_5_6_7_8_10_11_12, NFA_4_7_8_10, NFA_11_12, NFA_9_12, NFA_13_15_16, NFA_14 };

int regex(char *txt, int idx);
int DFA_match(char *txt, int startIndex);

int main (int argc, char *argv[])
{
int c, i, m, idx;
char text[1024], *pattern;
FILE *fp;


pattern = argv[optind++];

for (i = optind; i < argc; i++) {
fp = fopen(argv[i], "r");
if (fp == NULL) {
fprintf(stderr, "File %s: open failed.\n", argv[i]);
} else {
while (fgets(text, sizeof(text), fp) != NULL) {
m = 0;
for (idx = 0; (idx = regex(text, idx)) >= 0; idx++) {
m++;
}
if (m > 0) {
printf("%s: %s", argv[i], text);
}
}
}
}
return 0;
}
int DFA_match(char *txt, int startIndex)
{
int DFAstate = NFA_0_2_3_5;
int acceptLen = -1;
int i;

for (i = startIndex; txt[i] != '\0'; i++) {
switch (DFAstate) {

case NFA_0_2_3_5:
switch(txt[i]){
case 'x':
DFAstate = NFA_0_1_2_3_5_6_7_8_10_11_12;
break;
case 'z':
DFAstate = NFA_4_7_8_10;
break;
default:
return acceptLen;
}
break;

case NFA_0_1_2_3_5_6_7_8_10_11_12:
switch(txt[i]){
case 'x':
DFAstate = NFA_0_1_2_3_5_6_7_8_10_11_12;
break;
case 'z':
DFAstate = NFA_4_7_8_10;
break;
case 'y':
DFAstate = NFA_9_12;
break;
default:
return acceptLen;
}
break;

case NFA_4_7_8_10:
switch(txt[i]){
case 'x':
DFAstate = NFA_11_12;
break;
case 'y':
DFAstate = NFA_9_12;
break;
default:
return acceptLen;
}
break;

case NFA_11_12:
switch(txt[i]){
case 'y':
DFAstate = NFA_9_12;
break;
default:
return acceptLen;
}
break;

case NFA_9_12:
switch(txt[i]){
case 'y':
DFAstate = NFA_13_15_16;
acceptLen = i;
break;
default:
return acceptLen;
}
break;

case NFA_13_15_16:
switch(txt[i]){
case 'x':
DFAstate = NFA_14;
break;
default:
return acceptLen;
}
break;

case NFA_14:
switch(txt[i]){
case 'y':
DFAstate = NFA_13_15_16;
acceptLen = i;
break;
default:
return acceptLen;
}
break;
}
}
return acceptLen;
}

int regex(char *txt, int idx)
{
int i;
for (; idx < strlen(txt); idx++) {
if ( (i = DFA_match(txt, idx)) > 0) {
printf("matched!\n");
return idx;
}
}
return -1;
}

A 回答 (5件)

コマンドライン引数がわかってないのかもしれませんね


cygwinで
$ a bbb ccc.txt
とするとa.exeが実行され入力した文字列が引数として渡されます
プログラムで引数をうけとるのが argcとargv[ ] です
argcには引数の数(a, bbb, ccc.txtの3つがあるので3)
argv[ ] にはそれぞれの文字列
argv[0]は"a"
argv[1]は"bbb"
argv[2]は"ccc.txt"
が入ります。
(それとオプション引数を使っている様子はないので<getopt.h>とoptindは要らないのでは。)
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
おっしゃる通り、コマンドライン引数が分かっていない状態で他の文字探索のプログラムを流用して組んだのがmain関数だったので、不要な部分が多くありました。
上の回答を参考にいらない部分を削り、main関数の見直しをしてみたら動作するようになりました。また、今までコマンドライン引数を少し避けてしまっていたのですが、学習するよい機会になりました。
とてもわかりやすい説明をありがとうございました。

お礼日時:2009/03/08 01:03

>mainで入力すら行えず困っています。


マッチングそのものが正しく動くかどうかは別として、
このプログラムを sample という名前とすると
一行にひとつの対象となる文字列が置かれているようなファイルがあって

sample 適当な文字列 ファイル名1 ファイル名2

とすればプログラム中のDFAを使ってマッチングを試みています。
forも実行していないというのはそういうことではないのですか?

とりあえずは、デバッガーでステップ実行すれば状況が把握できるとお思いますけど。
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
おかげさまでなんとか動作するようになりました。
ファイルの読み込み周辺がまだしっかり理解できていない状態で、他のプログラムを流用してきたのが原因でした。お恥ずかしい限りです。
大変参考になるご意見をありがとうございました。

お礼日時:2009/03/08 00:57

「DFAを受理する」という言い回しが良くわからない(何かの入力を受理するDFAならわかりますが)のですが、


どこかからもらってきたものですか?

関数 main の先頭付近を見ると

pattern = argv[optind++];

for (i = optind; i < argc; i++) {
fp = fopen(argv[i], "r");

grep のように、プログラムの第一引数にパターン、二番目以降に検索対象のファイルということのようですが、
この pattern は代入されて以降一回も使われていません。
おそらく、本来はこれが正規表現にでもなっていて、そこから
DFAを組み立ててマッチングを行うもののような気がします。

DFA_match は追いかけたくありませんが、受け付けるアルファベットが
x, y, z である文法ということなんでしょうか。

この回答への補足

言葉が足りておらず申し訳ありません。
あらかじめ指定された正規表現(x,y,zで構成される)のパターンがあり、それを受理するDFAから作ったのが関数DFA_matchです。従って受け付けるアルファベットはx,y,zになります。
mainからregexに引数txt(検索対象の文字列)と引数idx(検索開始位置)を渡してマッチングを行いたいのですが、mainで入力すら行えず困っています。
mainは他の文字探索プログラムから適当に流用したものなので、現段階では全く見当違いの内容かもしれません。
ご指摘ありがとうございました。

補足日時:2009/03/07 10:08
    • good
    • 0

main で for ループに入っているかどうか, あるいは while でちゃんと読めているかは確認しましたか?


例えば for の直後 (fopen の前) に
printf("argv[%d] = %s\n", i, argv[i]); fflush(stdout);
while の直後 (m = 0 の前) に
printf("text = %s\n", text);
を入れて動かしてみてください.
    • good
    • 0
この回答へのお礼

forループに入ってもいないみたいですね…。
確認もしていませんでした。教えて下さりありがとうございます。
今からもう一度見なおしてテキストの入力方法を調べてみます。
ありがとうございました。

引き続き回答募集しています。
助言などしていただけたら嬉しいです。

お礼日時:2009/03/06 23:22

はっきりいって長いので読む気なし.


あなたがどのような動作を期待しているのかわからないので,
・どのような動作を期待しているのか
・どのように実行したのか
・どのようなデータを与えたのか
・どのような結果が得られたのか
をきちんと書いてください.

この回答への補足

ご指摘ありがとうございます。焦ったあまりに言葉が足りていませんでした。ごめんなさい。

このプログラムでは、テキストファイルを読み込み・またはテキストを入力して、それをあらかじめ指定されたパターンとマッチさせ、一致していた場合は"matched"と表示させたいと思っています。
関数DFA_matchはそのパターンから作ったDFAに応じてマッチングをする関数です。mainからregexには引数txt(検索対象の文字列)と引数idx(検索開始位置)を渡します。
cygwinでテキスト入力→ctrl+Dでパターンマッチを行うようにしたいのですが、コンパイルはうまく(?)いくのですが動作させると何も入力しないままに終わってしまいます。
以上で大丈夫でしょうか…?
自分ではmainのテキスト入力のあたりがおかしなことになっているのだと思います。しかしどこがまずいのか見直してもわかりません。
引き続きアドバイスを募集しています。

補足日時:2009/03/06 22:22
    • good
    • 0

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