5ちゃんねる ★スマホ版★ ■掲示板に戻る■ 全部 1- 最新50  

■ このスレッドは過去ログ倉庫に格納されています

C言語なら、俺に聞け! <20>

1 :ともっち:02/05/15 19:36
C言語質問すれです

・comp.lang.c FAQ
http://www.eskimo.com/~scs/C-faq/top.html
・C FAQ 日本語訳
http://www.catnet.ne.jp/kouno/c_faq/c_faq.html

・前スレ
<19> http://pc.2ch.net/test/read.cgi/tech/1020756993/

リンクは>>2-4あたり

623 :デフォルトの名無しさん:02/05/20 22:31
じゃあ入門卒業試験の課題としてこれはどうだ。

int match(const char *pattern, const char *string);

patternがstringとマッチするなら0で無い値、マッチしないなら0を返す。

pattern中の文字'?'は任意の1文字とマッチする。
'*'は0文字以上の任意の文字列とマッチする。
それ以外の文字は、その文字自身とマッチする。


624 :デフォルトの名無しさん:02/05/20 22:32
トークンきりだし、構文解析、構文チェックまではCで書けるとして、
そのあとにネイティブコードを作るときはやっぱりアセンブラだよね。
Cでもできるのかな。

625 :デフォルトの名無しさん:02/05/20 22:34
>>624
ネイティブコードを生成すること自体はCでも書けるだろ。
知識は必要だろうけど。

626 :デフォルトの名無しさん:02/05/20 22:36
>>623
patternの中に*や?がひとつも含まれていなかったら、strcmp(string,pattern)と等価?それともstrstr(string,pattern)と等価?

627 :デフォルトの名無しさん:02/05/20 22:37
>>624
アセンブリ言語コードを出力すればいいんじゃないの?
そういうコンパイラも多い。

628 :デフォルトの名無しさん:02/05/20 22:37
>>627
gccとか?

629 :デフォルトの名無しさん:02/05/20 22:37
>>626
strcmpと等価ということで。

630 :デフォルトの名無しさん:02/05/20 22:38
>>628
そう。UnixのたいがいのCコンパイラと
8bitのころのPCのたいがいのCコンパイラ。
DOSだとLSI-C86もそうじゃなかったっけ。

631 :デフォルトの名無しさん:02/05/20 22:39
>>629
ちょっとやってみよう。
再帰使うとうまくゆくかな・・・

632 :631:02/05/20 22:41
いや再帰じゃないな・・・

633 :デフォルトの名無しさん:02/05/20 22:44
>>632
出題者は再帰を使う回答を用意しますた。

634 :デフォルトの名無しさん:02/05/20 22:46
>>623
じゃあ補足すると、これぐらいは全部通ればとりあえず合格?
あんまり書くと長くなりすぎるから省略。

assert( match("abc", "abc") != 0 );
assert( match("abc", "abcd") == 0 );

assert( match("?bc", "abc") != 0 );
assert( match("a?c", "abc") != 0 );
assert( match("ab?", "abc") != 0 );
assert( match("ab?", "ab") == 0 );

assert( match("ab*", "abc") != 0 );
assert( match("ab*", "ab") != 0 );
assert( match("a*c", "abbbbbc") != 0 );
assert( match("a*c", "abc") != 0 );
assert( match("a*c", "ac") != 0 );

// 最長一致なら以下のチェック.
assert( match("a*c", "acc") != 0 );
assert( match("a*d*g", "adgabcdefg") != 0 );

635 :デフォルトの名無しさん:02/05/20 22:53
テストドライバその1

#include <stdio.h>

int main(int argc, char **argv)
{
 if (argc != 3) {
  fprintf(stderr, "usage: %s pattern string\n", argv[0]);
  return 1;
 }
 printf("%smatched\n", match(argv[1], argv[2]) ? "" : "un");
 return 0;
}

テストドライバその2
#include <stdio.h>
#include <string.h>

char line[1024];

int main(int argc, char **argv)
{
 if (argc != 2) {
  fprintf(stderr, "usage: %s pattern\n", argv[0]);
  return 1;
 }
 while (fgets(line, sizeof(line), stdin) != NULL) {
  char *eol = strchr(line, '\n');
  if (eol != NULL) {
   *eol = '\0';
  }
  if (match(argv[1], line)) {
   puts(line);
  }
 }
 return 0;
}


636 :デフォルトの名無しさん:02/05/20 22:56
assert並べるほうがいいな。
同じテストを何度でも繰り返せ、実行一発で結果がわかる。

637 :623:02/05/20 22:57
>>634
あ、そうですね。そのテストのほうが良いかも。

ちなみに>>634で用意したテストプログラムは、

その1: patternとstringをコマンドライン引数で与えて
matchedまたはunmatchedをプリントする。

その2: patternをコマンドライン引数で与えて
標準入力から1行ずつ読み込み、マッチする行だけ出力する。

いずれもpatternはちゃんとクオートしないと切ねぇことになる。


638 :617=623:02/05/20 22:59
テストドライバその2の方は、
むか〜しワタスィが書いた超簡易grepモドキそのものです。

639 :600:02/05/20 23:02
サパーリ出来ません。
逝ってきます…

640 :631:02/05/20 23:03
末尾に*がくると失敗するなぁ・・・・
やりなおそう。

641 :631:02/05/20 23:03
あ、ちなみに私はあの入門書を読み終えたばかりの人じゃないです。

642 :634:02/05/20 23:04
>>634
いかん、このassertだと * があったら無条件で1返せば通ってしまう(笑)
ので追加。
assert( match("a*c", "ab") == 0 );

あと複合系(もっと要る気が)
assert( match("a**?*", "ab") != 0 );
assert( match("a**?*", "a") == 0 );

643 :631:02/05/20 23:05
と思ったけどできた。

644 :デフォルトの名無しさん:02/05/20 23:15
あるモジュールAが別のモジュールBをよんで、さらにモジュールB
が別のモジュールCを呼んで...という具合にモジュールAを頂点とし
て呼ばれているモジュールすべてを洗い出すにはどうやって調べて
いけばよいのでしょうか?モジュールA、B、Cなどすべてのモジュ
ールのソースはあります。どなたか効率よく調べる方法がありましたら、
教えてくださいませんか。

645 :631:02/05/20 23:18
末尾が?で終わるときに失敗するんですが、いいですか?
だめですよね?(^_^;)

646 :仕様書無しさん:02/05/20 23:19
M-.

647 :デフォルトの名無しさん:02/05/20 23:19
>>644
このへんはどう? http://ctool.sourceforge.net/
他にもいろいろあるはず。

648 :デフォルトの名無しさん:02/05/20 23:19
>>644
クロスリファレンスや呼び出しツリーを作ってくれるツールを使えば?

649 :デフォルトの名無しさん:02/05/20 23:21
644
もれはソースブラウザ(M$)でしらみつぶしかな。

650 :623:02/05/20 23:25
あんまり引っ張っても何なので…
出題者が用意した回答です。
あんまり叩かないで(w

int match(const char *pattern, const char *string)
{
 while (*pattern) {
  switch (*pattern) {
  case '?':
   if (! *string) {
    return 0;
   }
   pattern++;
   string++;
   break;
  case '*':
   pattern++;
   do {
    if (match(pattern, string)) {
     return 1;
    }
   } while (*string++);
   return 0;
  default:
   if (*pattern++ != *string++) {
    return 0;
   }
  }
 }
 return ! *string;
}


651 :631:02/05/20 23:29
ギブアップ 末尾に?があると失敗します。

int match(const char *pattern,const char *str)
{
for(;*str||*pattern;str++,pattern++){
if(*pattern=='?'){
str++,pattern++;
continue;
}
if(*pattern=='*'){
while(*pattern=='?'||*pattern=='*')
pattern++;
if(*pattern=='\0'){
return 1;
}
while(*str!=*pattern){
str++;
}
}
if(*str!=*pattern)
return 0;
}

return 1;
}


652 :651:02/05/20 23:39
Visual C++の方に持っていって、デバッガにかけてみよう。
でないとどこが間違っているのかわからない(T_T)

653 : :02/05/20 23:42
ついでに正規表現版まで作ってくれ!!

654 :デフォルトの名無しさん:02/05/20 23:54
>>653
どの正規表現?
.と*だけで良いなら何とか…

(正規表現の文法自体は正規文法でないという罠)

655 :644:02/05/20 23:55
>>647,648,649
ありがとうございます。ckrefを使用してみます。

656 :651:02/05/20 23:55
for(;*str||*pattern;str++,pattern++){
の部分を
for(;;str++,pattern++){
if(*str||*pattern){
break;
}
に変えたら成功した・・・・
もしかしたらforについて勘違いしている部分があるかも(汗

657 : :02/05/20 23:56
とりあえずperlでつかえるくらい。。ナンチッテ

グループとかは無理ですか?

658 :651:02/05/20 23:57
あ!!
もしかしたらcontinueした時はforの条件式が評価されないんですか?

659 :デフォルトの名無しさん:02/05/21 00:00
>>657
Perlの正規表現だと、それこそちょっとしたコンパイラ書くくらいの
手間がかかると思われ。

グループって[a-z]みたいなやつ?
暇潰しの課題にはちょっと面倒すぎるなあ。

660 :651:02/05/21 00:06
やっと出来ました・・・・
forについての間違った認識を正すことが出来てよかったです。
ありがとうございました。

int match(const char *pattern,const char *str)
{
for(;*str||*pattern;str++,pattern++){
if(*pattern=='?')
goto loopend;
if(*pattern=='*'){
while(*pattern=='?'||*pattern=='*')
pattern++;
if(*pattern=='\0')
return 1;
while(*str!=*pattern)
str++;
}
if(*str!=*pattern)
return 0;
loopend: ;
}

return 1;
}


661 : :02/05/21 00:06
orとかは?

U(MA|FO)

みたいに

662 :デフォルトの名無しさん:02/05/21 00:07
>>656
for(;*str||*pattern;str++,pattern++){
は条件式が真ならループは続いて、
for(;;str++,pattern++){
if(*str||*pattern){
break;
}
はifの条件式が真ならループを抜ける。
前者と後者じゃまったく逆の処理じゃないの?

663 :デフォルトの名無しさん:02/05/21 00:08
>>662
すみません。
if!(*str||*pattern)) break;の間違いです。

664 :663:02/05/21 00:09
じゃなくて、
if(!(*str||*pattern)) break;

665 :デフォルトの名無しさん:02/05/21 00:35
あのなぁ。
if (*str) って書くなら、素直に if (*str != '\0') って書け。
省略すればいいって訳じゃないぜ。
if (isalpha(XXX)) とか、if (found) はこう書くべきだがな。

666 :デフォルトの名無しさん:02/05/21 00:36
>>665
同意

667 :デフォルトの名無しさん:02/05/21 00:37
strtokを書いたことがある方に聞きます
staticな局所変数を使いました?

668 :デフォルトの名無しさん:02/05/21 00:38
>>660
>goto loopend;
continue;じゃいかんの?

Cの文法に躍らされてる気がする。
そんなにまちがえるなら素直に状態遷移書けばいいのに

212 KB
★スマホ版★ 掲示板に戻る 全部 前100 次100 最新50

read.cgi ver 05.04.02 2018/11/22 Walang Kapalit ★
FOX ★ DSO(Dynamic Shared Object)