• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:C言語のプログラムの流れについて)

C言語のプログラムの流れについて

このQ&Aのポイント
  • C言語のプログラムの流れを順番に教えてください。
  • 特にadd関数とinsert関数の中身の動きについてが分からないので教えていただきたいです。
  • リスト構造を用いて、read関数で読み込んだ単語をアルファベット順にソートしてリストのセルに入れ、同じ単語はまとめてその単語と個数を順に表示するプログラムです。

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

  • ベストアンサー
回答No.3

No.2です。 aやcが何をしているか分からないということで、ポインタやアドレスを理解されてないのでしょうか? プログラム内で moji *a; のように宣言されているのがポインタです。 ポインタにはアドレスが入ります。 例えば構造体1のアドレスが1番地にあった場合、 a=構造体1のアドレスと置くことで変数aに1番地と言う物が入ります。 そして、このaを使用して構造体1にアクセスできるようになります。 このプログラムではmallocで構造体のメモリを確保して、a,b,c,sentouは構造体のアドレスを割り振ってアクセスしています。 下の説明では変数と構造体の関係が分かるように、変数(構造体名)でsentou(構造体:1)のように書きます。 ※構造体名は適当です。この場で勝手につけています。 また、大きな流れとして 1、読み込み。 2、addで今まで読み込んだものと比較、挿入箇所があれば3へ。 3、instertで挿入。 4、EOFで無ければ1に戻る、EOFであれば5へ。 5、表示 のように動いています。 これらを念頭においてみてください。 [book text book computer] がtxtに入力されているときの動きと言うことで。 最初に構造体1のメモリを確保します。 そして、sentouでアクセス出来るようにしています。 中身は恐らく[data,cnt,next]=["",0,NULL]のような形になっているはずです。 ここからループに入ります。 ・1週目 read "book"が読み込まれます。 ↓ add "book"とsentou(構造体:先)のアドレスが渡されます。 c=sentou(構造体:先)としているのでcは(構造体:先)を参照しています。 for文の中で、"book"と(構造体:先)の中の""が比較されます。 "book"の方が大きいのでa=c;としてa(構造体:先)となります。 そして、c=c->next;としています。c(構造体:先)のnextはNULLですので、次のループは行われません。 ループを抜けたらinsert関数に行きます。 insertに送るもの (a,c,data)=(構造体:先,構造体:先,"text") ↓ insert まず(構造体:1)のメモリが確保され、b(構造体:1)の状態になります。 そうしたら、a(構造体:先)の中身を["",0,(構造体:1)のアドレス]にします。 そして、b(構造体:1)の中身を["book",1,NULL]にします。 現在の構造体の中身 (構造体:先) ["",0,(構造体:1)のアドレス] (構造体:1)  ["book",1,NULL] ・2週目 read "text"が読み込まれます。 ↓ add "text"とsentou(構造体:先)のアドレスが渡されます。 c=sentou(構造体:先)としているのでcは(構造体:先)を参照しています。 ここら辺は1週目と同様です。 for文の中で、"text"と(構造体:先)の中の""が比較されます。 "text"の方が大きいのでa=c;としてa(構造体:先)となります。 そして、c=c->next;としています。c(構造体:先)のnextは(構造体:1のアドレス)です。 よって、c(構造体:1)の状態になります。 そしたら、次は"text"と(構造体:1)の中の"book"が比較されます。 "text"の方が大きいのでa=c;としてa(構造体:1)となります。 そして、c=c->next;としています。c(構造体:1)のnextはNULLですので、次のループは行われません ループを抜けたらinsert関数に行きます。 (a,c,data)=(構造体:1,構造体:1,"text") ↓ insert まず(構造体:2)のメモリが確保され、b(構造体:2)の状態になります。 そうしたら、a(構造体:1)の中身を["book",1,(構造体:2)のアドレス]にします。 そして、b(構造体:2)の中身を["text",1,NULL]にします。 現在の構造体の中身 (構造体:先) ["",0,(構造体:1)のアドレス] (構造体:1)  ["book",1,(構造体:2)のアドレス] (構造体:2)  ["text",1,NULL] ・3週目 read "book"が読み込まれます。 ↓ add "book"とsentou(構造体:先)のアドレスが渡されます。 c=sentou(構造体:先)としているのでcは(構造体:先)を参照しています。 ここら辺は1,2週目と同様です。 for文の中で、"book"と(構造体:先)の中の""が比較されます。 "book"の方が大きいのでa=c;としてa(構造体:先)となります。 そして、c=c->next;としています。c(構造体:先)のnextは(構造体:1のアドレス)です。 よって、c(構造体:1)の状態になります。 そしたら、次は"book"と(構造体:1)の中の"book"が比較されます。 これは同じものですので、c(構造体:1)のカウントを1増やし中身を["book",2,(構造体:2のアドレス)]にしてから returnします。 insert関数は行われません。 現在の構造体の中身 (構造体:先) ["",0,(構造体:1)のアドレス] (構造体:1)  ["book",2,(構造体:2)のアドレス] (構造体:2)  ["text",1,NULL] ・4週目 read "computer"が読み込まれます。 ↓ add "computer"とsentou(構造体:先)のアドレスが渡されます。 c=sentou(構造体:先)としているのでcは(構造体:先)を参照しています。 ここら辺は1,2,3週目と同様です。 for文の中で、"computer"と(構造体:先)の中の""が比較されます。 "computer"の方が大きいのでa=c;としてa(構造体:先)となります。 そして、c=c->next;としています。c(構造体:先)のnextは(構造体:1のアドレス)です。 よって、c(構造体:1)の状態になります。 そしたら、次は"computer"と(構造体:1)の中の"book"が比較されます。 "computer"の方が大きいのでa=c;としてa(構造体:1)となります。 そして、c=c->next;としています。c(構造体:1)のnextは(構造体:2のアドレス)です。 よって、c(構造体:2)の状態になります。 次は"computer"と(構造体:2)の中の"text"が比較されます。 "text"の方が大きいので何もせずにbreakしてforを抜けます。 ループを抜けたらinsert関数に行きます。 (a,c,data)=(構造体:1,構造体:2,"computer") ↓ insert まず構造体3のメモリが確保され、b(構造体3)の状態になります。 そうしたら、a(構造体:1)の中身を["book",2,(構造体:3)のアドレス]にします。 そして、b(構造体:3)の中身を["computer",1,,(構造体:2)のアドレス]にします。 現在の構造体の中身 (構造体:先) ["",0,(構造体:1)のアドレス] (構造体:1)  ["book",1,(構造体:3)のアドレス] (構造体:3)  ["computer",1,(構造体:2)のアドレス] (構造体:2)  ["text",1,NULL] これでループ終了して、後は表示します。 なるべく分かりやすいようには書きましたが、テキスト形式ではこれが限界です。 また、アドレスを理解できないとこれを理解するのは難しいです。。 a,b,cは今どの構造体のアドレスを管理しているか、構造体の中身はどうなっているのか、ここら辺を重点的に見ていけば良いと思います。 長くなりましたがこんな所です。

qwewqwe
質問者

お礼

本当にありがとうございます。 確かにポインタなどアドレスについての理解が弱かったです。 非常に助かりました!

その他の回答 (2)

回答No.2

addは同じ文字列があった場合のカウントと、アルファベット順で先にくるかの摘出。 insertはaddで摘出された文字を挿入。 ですかね?多分。 実際に動きを見たわけではないので予定通りに動いていることを前提としたaddとinsertの動きは、 addでcの構造体の中の文字列と一つ一つ比較され、 同じであれば、カウントの増加してaddを終了。 挿入箇所が見つかれば比較を終了してinsertへ。 insertでは、addで摘出された文字列をそこに格納してそれ以降の文を後ろにずらしています。 分かりづらいですが、前の構造体で次の構造体のアドレスを管理というような鎖みたいな形で管理しています。 例えば、構造体1で構造体2のアドレスを管理、構造体2で構造体3のアドレスを管理というような感じです。 このとき、構造体2の次に構造体4を入れる場合は、 構造体2に構造体4のアドレスを管理させて、構造体4に構造体3のアドレスを管理させる。 そんな感じで挿入しているのではないかと思います。 一つ一つについて動作を確認した訳ではないので詳しい所は分かりませんが、おおよそそんなことをしたいのだと思います。 少々気になった所は、sentou周りの式がおかしいですね。 表示のときのp=sentou->next;とadd内のc=sentou;はどちらかにそろえた方がいいのではないでしょうか。 加えてこの状態ではsentouが解放されませんね。 また、表示のときに構造体のメモリを解放してから次の構造体のアドレスを参照しているようです。 この2点が気になりましたが、現状で上手く動いていますか? 蛇足ですがファイルオープンを2回しているように見えるのですが気のせいですかね? mallocもそうですが、条件式と同時に色々やりたがる部分が見られます。 実際にこういったことをしているのですから分けて考えた方がいい気がします。 他にもコメントアウトがないし、変数もどれが何をしているか分からないしで、少々いい加減のような気もします。 人が見ても分かりやすいプログラミングを心がければ多少改善するのではないでしょうか。

qwewqwe
質問者

補足

dataに[ book text book computer]と順番に格納された場合(mainのwhileループ4回分)のadd関数の動きを変数(a,b,c..)を使いながら順を追って説明していただくことはできないでしょうか。。 非常にめんどくさいとは思いますがお願いします。。

  • bid
  • ベストアンサー率0% (0/1)
回答No.1

一つ一つ追っていけば良いのではないでしょうか。 add なら、  リストのノードを指すためのポインタを用意して、  for でリストの先頭から最後までたどる間に、  data の文字列とノードに格納されている文字列を比較して等しいならカウントアップ、、 のように。 そうするとコードのおかしな部分にも気づくと思います。

qwewqwe
質問者

補足

全体的な流れも教えていただきたいのですが、特にaddのfor分の()の中と、main分の1つ目のwhileを抜けた後の流れが特によくわからないのです。。

関連するQ&A