[表示 : 全て 最新50 1-99 101- 201- 301- 401- 501- 601- 701- 801- 2chのread.cgiへ]
Update time : 06/11 11:18 / Filesize : 195 KB / Number-of Response : 805
[このスレッドの書き込みを削除する]
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧] [類似スレッド一覧]


↑キャッシュ検索、類似スレ動作を修正しました、ご迷惑をお掛けしました

C言語なら俺に聞け(入門篇) Part 21



1 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 06:24:18 ]
C言語の入門者向け解説スレです。
・C++言語はスレ違いです。
・分からない事をなるべく詳しく書いて下さい。
・ソースコードを晒すと答えやすくなるかもしれません。
・質問者は最初にその質問をした時のレス番号を名前欄に書いて下さい。

前スレ
C言語なら俺に聞け(入門篇) Part 20
pc11.2ch.net/test/read.cgi/tech/1192455273/

教えて欲しいのではなく丸投げしたいならこちらへ
C/C++の宿題を片付けます 99代目
pc11.2ch.net/test/read.cgi/tech/1194262698/

2 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 06:25:04 ]
Part 1 ttp://pc8.2ch.net/test/read.cgi/tech/1146700389/
Part 2 ttp://pc8.2ch.net/test/read.cgi/tech/1153818463/
Part 3 ttp://pc8.2ch.net/test/read.cgi/tech/1160682950/
Part 4 ttp://pc8.2ch.net/test/read.cgi/tech/1162999861/
Part 5 ttp://pc8.2ch.net/test/read.cgi/tech/1165022193/
Part 6 ttp://pc10.2ch.net/test/read.cgi/tech/1167325490/
Part 7 ttp://pc10.2ch.net/test/read.cgi/tech/1170064980/
Part 8 ttp://pc11.2ch.net/test/read.cgi/tech/1171946674/
Part 9 ttp://pc11.2ch.net/test/read.cgi/tech/1173284217/
Part 10 ttp://pc11.2ch.net/test/read.cgi/tech/1174290325/
Part 11 ttp://pc11.2ch.net/test/read.cgi/tech/1176800483/
Part 12 ttp://pc11.2ch.net/test/read.cgi/tech/1178620766/
Part 13 ttp://pc11.2ch.net/test/read.cgi/tech/1179301993/
Part 14 ttp://pc11.2ch.net/test/read.cgi/tech/1181735298/
Part 15 ttp://pc11.2ch.net/test/read.cgi/tech/1182719692/
Part 16 ttp://pc11.2ch.net/test/read.cgi/tech/1184003625/
Part 17 ttp://pc11.2ch.net/test/read.cgi/tech/1185286631/
Part 18 ttp://pc11.2ch.net/test/read.cgi/tech/1187213990/
Part 19 ttp://pc11.2ch.net/test/read.cgi/tech/1190342593/

3 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 06:25:50 ]
うお、あぶね俺もたてるとこだった。
ともあれ>>1

4 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 07:46:40 ]
XP VisualC++2005 ExEdiで作業をしています。

現在WAVEの単純音データに離散フーリエ変換を行ってそのデータをExcelでグラフ化しているのですが
フーリエが終わってデータを格納した後、それをグラフにおこして別窓で表示させたいのですがどのようなプログラムをかけばいいのでしょうか?
またそのような事が詳しくかかれているHPなど参考になるところがありましたら是非紹介をお願いします。

わかりにくくてすみません。

5 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 13:09:44 ]
窓を開いてグラフを描くようなプログラムを書けばいいです

窓の開き方がわからないとか、図形の表示の仕方がわからない?
その場合は Win32 API を勉強

6 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 13:23:41 ]
やっぱりWin32APIでの表示なんですね ありがとうございます。

7 名前:デフォルトの名無しさん [2007/11/07(水) 14:51:32 ]
強化学習のQ-learningを用いたサンプルプログラムはないですか?

上記とは別にルーレット選択とボルツマン選択のサンプルプログラムもよろしくお願いします。

プログラムはC言語でお願いします。 どうもこれらがイメージつかないんでお願いします。


8 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 15:30:37 ]
>>7
スレ違い。
つーか、マルチすんなや。
pc11.2ch.net/test/read.cgi/tech/1193150915/961
pc11.2ch.net/test/read.cgi/tech/1193556424/227
ちゃんと↑の228にレスついているだろ。

9 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 15:43:42 ]
末尾再帰の最適化が起きる条件ってやっぱり実装によって違う?

10 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 15:54:26 ]
>>9
違う。つーか、入門者はそんなこと気にしなくて構いません。



11 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 15:57:52 ]
と入門者が申しております。

12 名前:sage [2007/11/07(水) 16:01:08 ]
>>10
ちょっと気にしてるんだよ。
やっぱgccか・・・?
デバッガ使うスキルがないんで確認ができないんだよね。

13 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 16:03:15 ]
>>12
アセンブリ出力を読むスキルもない?
例えば、callってニモニックがどこに散らばっているか位読めれば末尾再帰が展開されたかどうか判るんだけど。
つーか、スレ違い脱中年。

14 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 16:03:35 ]
ない。

15 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 16:05:19 ]
まずは逆アセンブルからか・・・


16 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 18:33:55 ]
>>15
-S でいいだろ

17 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 18:37:49 ]
BCCならそうだね。
VCだったら /FA かな

18 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 20:04:57 ]
質問です。

コマンドラインからパスワード等の入力をするときは、標準入力にパスワードを入力してるのに
画面には入力した文字を表示しないようになってるよね。これってどうやって実装してるんですか?
fgets()などのC言語のライブラリ関数では、どうやればいいかわからない。。

19 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 20:30:32 ]
www.linux.or.jp/JM/html/LDP_man-pages/man3/getpass.3.html
を読めば分かると思うが、通常は打った文字はechoされて画面に出る。
が、しかし、echoフラグを一時的に切れるような、getpassあたりの関数を使えば隠す事が可能になる。
詳しい実装方法は、getpass関数のソースを読めばわかると思うよ。

20 名前:18 mailto:sage [2007/11/07(水) 20:44:02 ]
>>19
ありがとうございます



21 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 22:44:27 ]
くだらない質問なのですが

struct e{
int value[];
};


int temp[256]
e num[256].value[256];
と宣言して

temp[i]にnumのvalueを一時的にまとめてコピーしたいのですが

temp[i]=num[i].value[];

といったことはできるのでしょうか?

22 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 22:51:47 ]
やってみればいいと思うよ^^

23 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 22:58:20 ]
やってみました。できませんでした><

そのためにmemcpyがあるのですね。
できました。ありがとうございましt

24 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 23:26:07 ]
あともう一つ質問なのですが

temp[]に
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15

の縦の行、つまり 0 4 8 12 を一度に入れたいのですが
そういうやり方はfor使うしかないですかね

25 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 23:34:42 ]
>>17
gccだったら?

26 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 23:36:22 ]
>>24
一度にって表現がよくわからない。

27 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 23:39:26 ]
for文を使わないでmemcpyみたいな感じで、ということです

28 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 23:44:57 ]
memcpyみたいなものの内部でforを使ってたらどうすんだよ

29 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 23:46:24 ]
ふつーのコンパイラなら-Sでアセンブリ出力。

30 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 23:51:22 ]
>>29
サンクス。



31 名前:デフォルトの名無しさん mailto:sage [2007/11/07(水) 23:53:25 ]
>>24
二次元配列がメモリ上でどうなってるか考えてみればすぐわかるだろうに。

32 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 00:13:35 ]
二次元なのか。
まだまだトーシローな俺は
二次元配列のような格納できる関数でもあるのかとおもっちまったぜ・・・

33 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 00:19:20 ]
>>31
そうですね。諦めました
人間諦めが肝心

34 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 10:44:09 ]
>>21

struct e{
int value[256];
};

e tmp;
e num[256];

tmp = num[i];

35 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 12:58:14 ]
ふと思ったんだけど、
構造体同士の代入はできて配列同士の代入はできないて理不尽じゃね?

36 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 14:14:01 ]
>>35
いや別に。Cでは配列をそのまま扱うことはできないと諦めているからどうでもいいよ。
どうせ、関数にそのまま渡すことさえできないんだから。

37 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 14:23:10 ]
>>21
マルチ乙

38 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 14:34:56 ]
>>35
理不尽っつぅかそういう考え方なんだな。配列は一つの纏まったオブジェクトではない、と。
一つの纏まったオブジェクトにしたいなら、上のように構造体で包めばいい。

39 名前:デフォルトの名無しさん [2007/11/08(木) 16:46:00 ]
double型のデータを表示するときに桁数をそろえたいんですが、どうすればいいですか?
マイナスの符号とかがあると変わってしまって表が汚くなります

40 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 16:51:29 ]
符号だけなら "%+f" とか "% f" にすればいいよ



41 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 16:58:33 ]
つ[%25.15g]

42 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 17:01:40 ]
>>40
どうも!

43 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 17:44:24 ]
>>38
構造体も配列同様、コピーできなかったのも今は昔。

44 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 17:49:20 ]
double型で割り算する場合、その数字がどのぐらい小さいと危険ですか?

45 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 17:52:54 ]
このぐらい(・∀・)c

46 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 18:01:16 ]
>>44
IEEE754であれば、表わすことができる最大値が1e308程度なので、商がその値を超えなければ(精度は兎も角)解は得られる。
つまり、1/1e-308は1e308だが、10/1e-308は1e309なので無限大になってしまう。
尤も、無限大になっても特に危険はないので安心して0で割ればいいと思う。

47 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 18:05:38 ]
そこが実数演算の面白いところだよな。
1 / -1e-320はちゃんと-Infになるからね。

48 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 18:46:18 ]
>>46
0で割るととまってしまうんですが・・・

49 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 18:49:53 ]
今日構造体習った
スゲー便利

50 名前:デフォルトの名無しさん [2007/11/08(木) 20:06:22 ]
>>48
0の除算をしたらプログラム割り込みが発生し、強制終了となる。



51 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 20:34:16 ]
それ整数型だろ。

52 名前:デフォルトの名無しさん mailto:sage [2007/11/08(木) 23:29:45 ]
実数演算だと0で割っても止まらないんだよな
0で割ってるのに気がつかなくてはまったことがある

53 名前:デフォルトの名無しさん mailto:sage [2007/11/09(金) 00:32:25 ]
2
1
0
-1
-2
というテキストファイルinput.txtをscanfを使ってリダイレクトで、
scanf.exe<input.txt >output.txt
というようにして読み込みたいのですが、
for(i=0;i<100;i++){
scanf("%d",&c[i]);
tmp=i;
if(c[i]==EOF){
break
}
として、ファイルの終端まで読もうとすると、-1の行までしか読み込みません。
-2まで読み込んでファイルの終端で読み込みを完了させるにはどうしたらよいのでしょうか?
scanfとリダイレクトは絶対使わなければならないので、そこ以外を変更することで対処したいのです。

54 名前:デフォルトの名無しさん mailto:sage [2007/11/09(金) 00:41:59 ]
それはたまたまEOFの値が-1だったというだけだろう。
scanfの戻り値を見ろ。あるいはscanf後にfeof(stdin)を見るという手も使えると思う。

55 名前:デフォルトの名無しさん mailto:sage [2007/11/09(金) 05:47:16 ]
>>53
EOFとの比較は、「ほにゃららの場合はEOFになる」と明記されたものと行います。
例えばfgetc()のリターン値とか。

56 名前:デフォルトの名無しさん mailto:sage [2007/11/09(金) 13:55:01 ]
double *dp;
dp=(double*)malloc(sizeof double);
コンパイル通らないよ
どうすればいい

57 名前:デフォルトの名無しさん mailto:sage [2007/11/09(金) 13:59:32 ]
sizeof (double)

sizeof *dp


58 名前:デフォルトの名無しさん mailto:sage [2007/11/09(金) 14:00:36 ]
ども

59 名前:デフォルトの名無しさん mailto:sage [2007/11/09(金) 14:01:33 ]
(double)

60 名前:デフォルトの名無しさん [2007/11/09(金) 14:39:24 ]
巡回セールス問題を解くプログラムを順列を用いて書きたいのですけど
for(i = 0; i < n; i++) used[i]=NO;
perm(0);

return(0);
}

void perm(int d)
{
int i,j;
int b[MAXN];
int s = adj[a[0]][a[n-1]];

if(d == n){
for(i = 0; i < n-1; i++){
s+=adj[a[i]][a[i+1]];
}
}

else {
for (i = 0; i < n; i++) {
if (used[i] == NO) {
a[d] = i;
used[i] = YES;
perm(d + 1);
used[i] = NO;
}
}
}
}
これだけだとただの列挙になってしまいます
最小値だけをだすにはどうしたらいいでしょうか?



61 名前:デフォルトの名無しさん mailto:sage [2007/11/09(金) 19:05:00 ]
>>54>>55
ありがとうございます。
ちょっと詳しくしらべてみます。

62 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 00:00:54 ]
struct Point {
int *x;
int y;
};
にして
p = (struct Point *)malloc( sizeof(struct Point) *10 );
p->x=(int *)malloc(sizeof(int)*10);
とメモリを確保したら
p[0〜9].x[0〜9] のメモリが確保されているということですよね。

p[1].x = 10;
とやったらxに10が入ると思ったのですが入らないのはなんでですか?

63 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 00:03:00 ]
逆ピラミッドを描きたいのですが、どうしてもできません

#include <stdio.h>

int main(void)
{
int a,i,j;

printf("何段ですか? ");
scanf("%d",&a);

for(i=1;i<=a;i++){
for(j=1;j<=i-1;j++)

putchar(' ');

for(j=1;ここの部分がわかりません;j++)

putchar('*');

putchar('\n');

}
return(0);
}

助言をお願いします


64 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 00:03:44 ]
62はわかりました
p[1].x[1] = 10;
こう入れないとだめなんですね

んで、 p[0].x[0] = 10;
だと表示ができるのですが
p[1].x[1] = 10;
だとエラーが出てしまいます。なんででしょうか

65 名前:デフォルトの名無しさん [2007/11/10(土) 00:21:11 ]
>>62,64
p = (struct Point *)malloc( sizeof(struct Point) *10 );
ここでp10個分、p[10]が確保されてるので
for(i = 0;i < 10;i++) p[i]->x = (int *)malloc(sizeof(int)*10);
で各xには別のx[10]分を確保

66 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 00:22:29 ]
>>64
もし>>62の通りのプログラムなら、p[0]のxしか確保されてない
p->x=(int *)malloc(sizeof(int)*10); //p->xはp[0].xと同義

全てのpについてxを確保するなら以下のように繰り返しを使う
for(i=0; i<10; ++i){
p[i].x=(int *)malloc(sizeof(int)*10);
}

67 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 00:23:47 ]
プログラムのことではないのですが、お尋ねしたいことがあります。
このたび仕事でC言語のソース解析を行うことになったのですが、コードリーディングのために便利なツールなどは無いでしょうか?
コード中の関数や構造体をダブルクリックすると、定義してあるソースまでジャンプしてくれたりしたら助かるのですが


よろしくお願いいたします

68 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 00:24:10 ]
つまり
p[0].x[0〜9]が確保されていて
p[1].xは確保されていなかったわけですね。

ありがとうございます。頭がスッキリニッコリ
ということは解放するときは
for(int i=0;i<10;i++)
free(p[i].x);
free( p );
こういう風にせんといかんわけですね。

69 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 00:26:36 ]
>>67
VisualStudioは、右クリックから定義へ移動って機能があるけど、Cでちゃんと動くかはわからない。

70 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 00:29:10 ]
>>69
それなりに動く。
たまにどのシンボルか選べってなることもあるけど。



71 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 00:30:21 ]
>>68
doxygenというのがあるよ
ttp://www.fides.dti.ne.jp/~oka-t/doxygen.html#sample
こんな感じでクラスや関数間の関係を可視化してくれる。

導入方法はここから
ttp://skazami.web.infoseek.co.jp/tools/Graphviz_Doxygen.htm


72 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 00:30:59 ]
>>71のは>>67へ向けたもの

73 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 00:59:10 ]
構造体に不定の配列を定義して、後で配列の最大値を設定するにはどうしたらよいでしょうか?
例えば…

struct{
foo[]
};

で、配列の使用時に

foo[bar]; (barは最大値)

という風にしたいのですが…

それとも構造体の定義時にあらかじめ余裕をもって配列を定義してしまう方がいいですか?

74 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 01:15:34 ]
malloc。
良く分からないなら、あらかじめ定義した方が良いだろうね。

75 名前:デフォルトの名無しさん [2007/11/10(土) 01:23:53 ]
>>67
秀丸エディタにそういう機能あるよ。

76 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 01:48:32 ]
>>74
ありがとうございます。

正直よくわからないので、助言どおり余裕を持って最初に定義してしまうことにします…すんません。

77 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 05:16:10 ]
>>63
for(i = a;i >= 1;i--){
for(j = a - i;j > 0;j--) putchar(' ');
for(j = i * 2 - 1;j > 0;j--) putchar('*');
putchar('\n');
}
最初のをfor(i=1;i <= a;i++)で上下反転。


78 名前:デフォルトの名無しさん [2007/11/10(土) 10:33:24 ]
こんな図形をFor文で作れといわれたんですが・・
まったくワカリマセン(´・ω・`)・・どなたか助けてください
↓こんなの
***
**
*

79 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 10:39:04 ]
>>78
宿題スレ池

#include <stdio.h>
#define N 3
int main()
{
char i, j;
for (i = 0; i < N; i++) {
for(j = N; j > i; j--) {
printf("*");
}
printf("\n");
}
return 0;
}

80 名前:78 [2007/11/10(土) 10:43:36 ]
>79さん
ありがとうございます

そうさせていただきます・・w



81 名前:デフォルトの名無しさん [2007/11/10(土) 11:47:01 ]
質問です。
今C言語の勉強をしていて、Cpadというエディターで書いたあとにコンパイルして
実行ボタンを押して実行しています。
コマンドプロンプトが表示されて、処理が実行されますが一回で終わってしまいます。
例えば「ある数をscanfして、それに2を加えた数をprintfする」というプログラムのとき
結果が出力されたあとに、またscanfに戻るって何度もプログラムを続けることってできないですか?
説明下手ですが、宜しくお願いします。

82 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 11:49:57 ]
>>81
for(;;) {
  scanf(・・・);
  printf(・・・);
}


83 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 12:02:25 ]
>>82
ありがとうございます。それで指定した数までは終了しないようになりました。


#include <stdio.h>
int main(void)
{
int i, j,a;
printf("数を入力して\n");
for (i = 0; i < 10; i++) {

scanf("%d",&j);
a=5+j;
printf("%d\n",&j);
}
return 0;
}


何入力しても結果が3928になるのはなぜなんだろう…

84 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 12:04:31 ]
>>83
a の値を表示させてないからじゃないかな

85 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 12:04:37 ]
> printf("%d\n",&j);

86 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 12:08:30 ]
>>84->>85
迅速なレスありがとうございます。
間違っていました…。
でも今度は結果が3926が出力されるようになりました。
今日手探りで色々入れたので、もしかしたら環境の問題なのかもしれません。
ちょっと色々試してみます。ありがとうございました。


87 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 12:10:42 ]
>>86
printf("%d\n", a); // & はいらない

88 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 12:32:05 ]
struct RGB{
int r,g,b;
}

という構造体を

struct RGB *color;
color = (struct RGB *)malloc( sizeof(struct RGB) *10 );
と10個作って、各要素を足して4で割るということを続けていきたいのですが

(color[0]+color[1])/4
という感じに、構造体同士を足したりできるのでしょうか?


89 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 12:36:29 ]
>>88
ムリ。

90 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 12:41:57 ]
それだと
(color[0].r+color[1].r)/4
(color[0].g+color[1].g)/4
(color[0].b+color[1].b)/4
としないといかんわけですか。




91 名前:63 mailto:sage [2007/11/10(土) 13:09:39 ]
>>77
お答え頂ありがとうございました。
ずっと悩んでいたので、やっとスッキリすることができました。

92 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 13:32:08 ]
再帰を習ったのですが理解できなくて、自分なりに、ネットとかで調べて、
再帰の概念は何となく分かったのですが、いざプログラムとなると…。
例えば、構造体を
struct node{
int a;
struct node *r;
struct node *l;
};
と定義し、
引数を二分探索木の根のアドレスとし、二分探索木の最小の値を持つ節点の
アドレスを返す関数minを作成。
1 struct node *min(struct node *t){
2 struct node *m = (struct node *)NULL;
3 if(t != (struct node *)NULL){
4 if(t->l == (struct node *)NULL)
5 m = t;
6 else
7 m = min(t->l);
8 }
9 return m;
10 }
と書いてあるのですが、どういう手順で実行されるのかと、7行目で、
なぜ変数に関数を代入してるのかも意味が解りません。

93 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 13:47:26 ]
関数を代入してるんじゃない
関数を実行した戻り値を代入しているんだ

94 名前:92 mailto:sage [2007/11/10(土) 14:28:06 ]
>>93
レスありがとうございます。
関数を代入しているわけではなく、関数の戻り値を代入しているのですね。
なぜ、戻り値を代入しているのですか?

3行目は、二分探索木の有無の判定で、無い場合は、そのままNULLを
返して終了。
4〜5行目は、左部分木が無ければ、根が最小値なので、最小値の節点の
アドレスを入れる変数であるmに根のアドレスであるtを代入して、
それを返して終了。
なので、7行目以外は解るのですが、7行目はどういう処理をしてる
のですかね?

95 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 14:35:53 ]
>>94
tがNULL→NULLを返す
t->lがNULL→tが最小なのでtを返す
それ以外→t->lから始まる二分木で最小の物を返す

ok?

96 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 14:42:11 ]
      ○
    ○┘└○
   ○┘○┘└○
  ○┘  ・・・┘└・・・
 ○┘

97 名前:92 mailto:sage [2007/11/10(土) 15:24:02 ]
>>95
はい、そこまでは解っています。どういう処理と言うか、tがNULLでなく、
t->lもNULLでない場合にどういう手順で動いてるかが解らなくて。

tがNULLでなく、t->lもNULLでない場合を考えたとして、
>>96さんの図で言えば、一番左下に位置している○が最小ですよね。
そして、一番左下の○まで来て、さらに再帰呼び出しをすると、
3行目のif(t != (struct node *)NULL)で条件に一致せずに、
9行目のreturn m;に進んで、ここで、どうなるんですか?
2行目でstruct node *m = (struct node *)NULL;としているので、
戻り値は、このアドレスになって、7行目のm = min(t->l);で、mに
代入しても、最小値のアドレスになりませんよね…

98 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 15:44:58 ]
>>97
if(t->l == (struct node *)NULL)
に引っかかって
m = min(t->l);
が実行されずに
m=t
が実行されるので
if(t != (struct node *)NULL){
が偽になるのは再帰ではなく外から呼び出した場合だけ

99 名前:92 mailto:sage [2007/11/10(土) 16:00:46 ]
>>98
確かに一番左下を再帰呼び出しした時に、
if(t->l == (struct node *)NULL)にひっかかるので、
一番左下の○まで来て、さらに再帰呼び出しされる事は、ないですね。
となると、
if(t->l == (struct node *)NULL)
に引っかかって
m=t
が実行されて、
次は
return m;
ですよね?
このreturn m;で、メイン関数に返されて終了ってことですかね?
それだと、
m = min(t->l);
じゃなくて、
min(t->l);
で十分じゃないですか?
何のために、m = min(t->l);としているのですか?

100 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 16:19:20 ]
自分で考えてみたんですがちょっと分からないので
教えてください。

学校でユークリッドの互除法によって最大公約数を出すプログラムを
作ったんですが、これは2つの数の最大公約数を求めるものですよね。
もし3つとか6つとかの数の最大公約数を求めるんだったらどうプログラムするのが
一番なのでしょうか?ユークリッドを工夫すれば出来るでしょうか。



101 名前:デフォルトの名無しさん mailto:sage [2007/11/10(土) 16:22:55 ]
>>99
メイン関数に返るのではなく呼び出した関数の呼び出した位置に返るのだよ
つまりmin(t->l)が実行されたあとにその戻り値がmに代入されてreturn mで戻り値となりそれが更に・・・
てな具合で呼び出した順を逆にたどるために各階で戻り値を返す必要があるわけだ






[ 続きを読む ] / [ 携帯版 ]

前100 次100 最新50 [ このスレをブックマーク! 携帯に送る ] 2chのread.cgiへ
[+板 最近立ったスレ&熱いスレ一覧 : +板 最近立ったスレ/記者別一覧]( ´∀`)<195KB

read.cgi ver5.27 [feat.BBS2 +1.6] / e.0.2 (02/09/03) / eucaly.net products.
担当:undef