• ベストアンサー

正規表現の応用

C言語のソースコードを扱っています。 デバッグのため(関数がどういう順番で呼び出されているかを知るため)、関数の先頭にprint文をつけようと思っています。 例えば、 int hoge(引数の並び) { 関数の中身 } なら int hoge(引数の並び) { printf("hoge"); 関数の中身 } といった具合です。 関数が膨大なので、手作業で一つずつprintfを書くのは現実的ではありません。 関数の最初の1行のパターンマッチは、/int\s\w*(.*)/ でうまくいくのですが、次の行の{まで含んだ正規表現に対応させるやり方がわかりません。 また、printf文を読み込んだソースコードに挿入するにはどうしたらよいのでしょうか。 どなたか分かる方がいらしたらご教授よろしくお願いいたします。

noname#182748
noname#182748
  • Perl
  • 回答数4
  • ありがとう数4

質問者が選んだベストアンサー

  • ベストアンサー
  • kumoz
  • ベストアンサー率64% (120/185)
回答No.4

2行単位で処理するようなループを書けば、正規表現マッチが簡単になると思います。 my $twoline = <FH>; while (<FH>) { $twoline .= $_; $twoline .= "printf(\"hoge\");\n" if $twoline =~ /int\s\w*\(.*\)\s*\n\s*\{\s*\n/; my ($line1, $line2) = $twoline =~ /^(.*\n)(.*\n)$/s; print $line1; $twoline = $line2; } print $twoline;

noname#182748
質問者

お礼

解答ありがとうございます。2行単位でやってみます。

その他の回答 (3)

  • axsies
  • ベストアンサー率64% (38/59)
回答No.3

複数行マッチングはmオプションを付ければ可能です。 具体的には、 /int\s\w+(.*)/m のようにすればOKです。 注意点としては、複数行マッチングの時、任意の一文字を表す「.」はそのままでは改行にはマッチしません。 sオプションを付ければマッチするようになります。 perlの正規表現は結構複雑な仕様なので、リファレンスを一読されることをお勧めします。

noname#182748
質問者

お礼

解答ありがとうございます。 正規表現はたしかに複雑ですね。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

「全体を読み込む」は「全体を読み込む」以外の表現が難しいんだけどなぁ.... 強いて言い換えれば「ファイル全体を 1つの文字列として読み込む」... ぜんぜん変わらん. で「よろしく」ってのは「やりたいように」ってこと. 例えば「改行の直後の {」は /\n\{/ でマッチできる.

noname#182748
質問者

お礼

ありがとうございます。ファイル全体を読み込むこともできるのですね。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.1

えぇと.... /int\s\w*(.*)/ という正規表現だと, int 型の変数の宣言にもマッチするはずなのですが.... あと, int 以外 (void を含む) を返す関数で破綻するね. どこまでまじめに処理するかにもよるんだけど, 手を抜くなら $/ = undef; $file = <>; で全体を一気に読み込んでからよろしくする.

noname#182748
質問者

お礼

解答ありがとうございます。 >あと, int 以外 (void を含む) を返す関数で破綻するね. ここは、適宜置き換えるので問題ありません。 >どこまでまじめに処理するかにもよるんだけど, 手を抜くなら $/ = undef; $file = <>; で全体を一気に読み込んでからよろしくする. すいませんが、もう少し詳しく説明してくれませんか。「全体を読み込む」とか「よろしくする」ではわかりませんでした。 よろしくお願いいたします。

関連するQ&A

  • 正規表現に関する質問

    以前もここで質問したものです。皆様の解答をヒントに一歩進みました。 C言語のソースコードを扱っています。 デバッグのため(関数がどういう順番で呼び出されているかを知るため)、関数の先頭にprint文をつけようと思っています。 例えば、 int hoge(引数の並び) { 関数の中身 } なら int hoge(引数の並び) { printf("hoge"); 関数の中身 } といった具合です。 関数が膨大なので、手作業で一つずつprintfを書くのは現実的ではありません。 ここで、 open(IN,"$ARGV[0]"); @array = <IN>; for($i=0;$i<@array;$i++){ if($array[$i] =~ / _*.+\(.*\)/){ $tmp = $&; if($array[$i+1] =~ "^{\n"){ print $array[$i]; print $array[$i+1]; print "printf(\"FileName:$ARGV[0] FunctionName:"; print $tmp; print "\");"; print "\n"; $i++;} else{ print $array[$i]; } }else{ print $array[$i]; } } というコードを書きました。しかしこれでもうまくいかないケースが多々ありました。 int main(void) { intro(); new_game(); /* @@@ exit(0); */ /* causes a warning in C++ */ return(0); } のように返り値が横ではなく上についていたり、 void __ast_string_field_index_build(struct ast_string_field_mgr *mgr, ast_string_field *fields, int num_fields, int index, const char *format, ...) { のように引数が複数行にわたる場合です。 どのようにしたらよいのでしょうか。 どなたか教えてもらえませんか?

    • ベストアンサー
    • Perl
  • 関数先にて配列の長さを取得する方法

    関数にて、引数にて渡された配列(ポインタ)から配列数を調べる方法はないでしょうか? #include <stdio.h> void test(unsigned int *p){ printf ("%d\n", sizeof(*p)/sizeof(p[0])); //結果 1 } int main(){ unsigned int hoge[] = {0x30, 0x31,0x32}; test(hoge); printf("%d", sizeof(hoge)/sizeof(hoge[0])); //結果3 return 1; } 上記コードの関数testの*pから配列の数3が抜き取りたいと思っております。 よろしくお願いします。

  • 正規表現

    gccです。次のコードを実行すると"cd"にマッチするのは3箇所あるはずなのにreg()のprintfが1回しか実行されません。どこが変なんでしょうか? #include <stdio.h> #include <sys/types.h> #include <regex.h> #include <string> int re(std::string text, std::string pattern) { size_t nbmatch = 128; regex_t preg; regmatch_t pmatch[nbmatch]; if (regcomp(&preg, (char*)pattern.c_str(), REG_EXTENDED||REG_NEWLINE)) return 1; if (regexec(&preg, (char*)text.c_str(), nbmatch, pmatch, 0)) return 2; for (int i=0; i<(int)nbmatch && (int)pmatch[i].rm_so>-1 && (int)pmatch[i].rm_eo>-1; i++) printf("%d to %d (%d chars)\n", (int)pmatch[i].rm_so, (int)pmatch[i].rm_eo, (int)pmatch[i].rm_eo-(int)pmatch[i].rm_so); return 0; } int main() { re("abcdefg abcdefg abcdefghijk abcicawd","cd"); return 0; }

  • C言語の基本的な質問ですが、関数へのポインタの宣言

    関数へのポインタの質問です。 下のように、関数へのポインタを使ったプログラムを書きました。 (関数へのポインタを理解するためのものなので、実用的な意味はありません。(*^_^*) また、このプログラムはコンパイルもリンクも実行も問題なく出来ます。) #include <stdio.h> int add_func(int,int); (*func_p0) (int,int); int main(void) { int (*func_p1) (int,int); int (*func_p2) ( ); int hoge0,hoge1,hoge2; func_p0=add_func; hoge0=func_p0(3,5); printf("0 : 3+5は%d\n",hoge0); func_p1=add_func; hoge1=func_p1(3,5); printf("1 : 3+5は%d\n",hoge1); func_p2=add_func; hoge2=func_p2(3,5); printf("2 : 3+5は%d\n",hoge2); return(0); } int add_func(int x, int y) { return(x+y); } func_p0のように戻り値の型を書かない場合と、func_p1やfunc_p2のように戻り値の型を書くのとでは何が違うのでしょうか。 func_p0は外部変数ですが、自動変数にする(main関数の中で同様に宣言。)とコンパイルエラーになります。 それはなぜですか。 func_p1のように引数の型が書いてあるのと、func_p2のように引数の型が書いていないのでは何が違うのでしょうか。 int (*func_p2) ( );というのは、int (*func_p2) (void);とは違うんですよね?

  • -(ハイフン)_(アンダーバー)の先頭や末尾での使用不可にする正規表現の書き方

    JavaScriptの(正確にはJavaScriptのみというわけでは無く、どの言語にもいえることなのですが、)正規表現を使って、以下のような書き方を不許可にしたいのですが、なかなかうまくいきません。 絶対条件は、英数字のみです。 禁止にしたい:-hoge、hoge-、_hoge、hoge_ しかし、これはOK:ho-ge、ho_geなどなど........ ようするに、先頭末尾に-(ハイフン)_(アンダーバー)の使用を禁止にしたいのです。 但し以下の場合に使わなければなりません。 function check( str ) { if( str.match(/ここに制御文/) ) return false; else return true; } ↑ みたいな関数があって、下記のような処理をほどこしています。 if( !check( str ) ){ alert( strMsg ); return false; } わかりづらい内容かもしてませんが、 どなたご教授いただけば幸いです。 宜しくお願いいたします。

  • 自動でステップオーバーされる関数にしたい

    Visual StudioでF11をおしてステップインしたときに エラーの起こりようがないような関数の中には入らないようにできないでしょうか。 class HOGE{ int hoge; public: int getHoge(){ return hoge; } //このような関数にステップインしたくない }; リリースビルドではインライン関数にするとステップインできないようになりますが、 デバッグビルドでも問答無用でステップインしないようにする方法はありませんか? または、デバッグビルドでも関数単位でインライン展開を指定できるような方法はありませんか? __forceinlineをつけても、やはりデバッグビルドでは無視されてしまいました。

  • visual c++ 2008のバグ?

    visual c++ 2008 Express Editionを使ってC++言語でプログラミングしているのですが、どうしても理解できない動作に困っています。 int putPiece(int x, int y, int typ, int dir, int blo, int col){ ・・・ if(canPlacePiece(x, y, typ, dir, blo, col) == true){ ・・・ } } int canPlacePiece(int x, int y, int typ, int dir, int blo, int col){ ・・・ //変数宣言 printf("%d,",x); //デバックのため ・・・  } かなり省略してますが、上のような感じで、パズルのピースを置くための関数putPiece内で引数をそのまま関数canPlacePiece(ピースを置けるか調べる関数)に渡します。関数canPlacePieceはピースが置けるならtrueを返し、置けないならfalseを返すようにしてあり、関数putPiece内のif文内にはピースを置くための処理が書かれています。 問題はこの関数putPieceを呼び出した際に、ループ文があるわけでもないのにcanPlacePiece関数が何回も呼び出された感じの動作をするということです。たとえばputPiece関数の引数xに1を入れて呼び出したとき、canPlacePiece関数内printf文でxの中身1が1回だけ表示されるだけのはずが、「1,2,2,2,2,2,・・・」と表示されます。このようにcanPlacePiece関数が引数を変えて何回も呼び出されているような動作をしていますが、この関数を抜けるとピースを置く処理をしてreturn trueするか、置けずにreturn falseしてputPiece関数を抜けるだけなので、こんな動作はありえないはずなんです。 これはvisual c++ 2008のバグ? それともC++の仕様? それともまだ見落としているところがある?

  • std::listの代入について

    最近std::listを勉強し始めたのですが質問があります。 あるクラスに以下を用意しました。 メンバ変数 std::list< int > list_int; メンバ関数 void SetListInt( const std::list< int > *temp_list ){ list_int = *temp_list; } 以下質問内容です。 ・この SetListInt 関数の場合 temp_list の先頭のみが代入されますか? ・また, temp_list の元の場所が削除または変更されても list_int の中身(この場合は先頭のみ?)は変わらないですよね? ・引数で貰って中身を全部代入したいならイテレータでfor文を回すしかないのでしょうか? 質問が多く拙文でお恥ずかしいのですが、よろしければご回答お願い致します。

  • 構造体を引数で関数へ渡す

    こんばんは。現在C言語を学んでいます。 課題という形で構造体で定義されたデータを関数の引数に当てはめ、データを渡すという処理を行わねばならぬのですが、関数を利用しての構造体の受け渡しが分からず苦戦しております。ご助言頂ければ幸いです。 分かりづらいかとは思いますが下記が私が簡単にですが作ったものとなります。 私の考えている動作プロットとしては 1. 構造体の形式を定義する。 2. 冒頭にて存在する関数を定義 3. main関数内にて構造体に名前を付けて定義し、値を入力より受付 4. do_it_hoge関数に構造体を引数として与え(ここが分からず)関数を呼び出す。 5. 関数内にて引数で受け取った &hoge.a,b,c等を表示するなどしたい。(受け取る方法が分からず) 関数を呼ぶ際にカッコ内に入れるのは構造体の名前のみで良いのでしょうか? (例: do_it_hoge(hoge); のように) また呼び出される関数側の括弧は何を記述するのでしょうか? いつもならint hogehoge, や char hoge, などと宣言しているかと思うのですが。 読みづらく、分かりにくいものかとは思いますが どうぞ宜しくご教授頂ければと思っております。 構造体を触るのが久しぶりだったのでそちらでミスがあるかもしれません。もし何か補足等必要でしたらメッセージ頂ければ返事させていただきたいと思います。 //----------------------------------------------------------------// //構造体HOGEHOGE定義 //----------------------------------------------------------------// typedef struct tagHOGEHOGE { int a,b; int c; }HOGEHOGE; void do_it_hoge();//関数定義。ここでのカッコ内の定義も不明 //----------------------------------------------------------------// // main //----------------------------------------------------------------// void main(){ HOGEHOGE hoge;//hogeをHOGEHOGE利用で定義 scanf("%d,%d",&hoge.a,&hoge.b);//カンマ区切りで代入 scanf("%d",&hoge.c);//数値をhoge.cへ do_it_hoge();//←ここが分からず } //----------------------------------------------------------------// // do_it_hoge 関数。構造体を引数で受け取りたい関数。 //----------------------------------------------------------------// void do_it_hoge(){ // ←括弧内の受け方が分からず // ここでmainで入力された &hoge.aなどを参照して表示したい // 例: printf("hogeA:%d",&hoge.a); } //----------------------------------------------------------------//

  • 正規表現について

    正規表現につての質問です。 今テキストファイルに下記のような漢字と数字が並んでいます。 そこから、漢字一文字だけの行を抜き出してきたいのですが、うまくいきません。PerlとCygwinを使用しています。よろしくお願いします。 人584504122 情報542701982 商品510342870 日414551872 方347990908 者347069359 中339925319 表示330177395 的324961911 私323727263 検索291502623 見ル285226619 場合275698771 一256241900 利用253752129 年240881734 時239273060 前228762989 店225241510 登録224560617   ・   ・    ・ プログラム中身 #! /usr/bin/perl -w #テキストから指定した単語などとマッチすると、 #その単語を含んだ文を抜き出してくる。 while(<>){ s/ +//g; s/\s+//g; if(/^([亜-煕]|[一-龠]){1}[0-9]*/){ print; print "\n"; } }