• ベストアンサー

ばばぬきプログラムについて

 下記のようなプログラムで4人のコンピュータにババヌキをさせるプログラムを組んでる最中なんです。  decklistまでは表示できてもshufflelistではコンパイルは通っても実行するとデバックが起きてしまって困っています。while文をなくすとちゃんと返り値を持って表示はできるんですがwhile分で繰り返したとたんデバックが起きるんですがその理由がわかりません。どうして無理でしょうか?ご教授願います。 decklistは整列されリストに保存した山札の関数。 shufflelistはランダムで保存していく関数。 personの関数はdecklistのほうで試したところコンパイルは通るんですがこちらもデバックが起きてしまいます。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> #define N 53 //デッキのカードの構造体 struct card{ int t; struct card *next; }*deck; //カードを配った後のそれぞれのプレイヤーの情報(仮 struct player{ int card; struct player *nextcard; struct player *nextturn; }; //関数定義 struct card *talloc(void); struct player *lalloc(void); struct card *decklist(void); struct card *shufflelist(void); struct player *person(struct player *P); void displist(void); int main(void){ struct player *A,*B,*C,*D; struct player *p; p=person(A); while(p!=NULL){ printf("%d ",p->card); p=p->nextcard; } return 0; } //card構造体のセルの確保 struct card *talloc(void){ return (struct card *)malloc(sizeof(struct card)); } //player構造体のセルの確保 struct player *lalloc(void){ return (struct player *)malloc(sizeof(struct player)); } //カードを切る前の整列された山札の関数 struct card *decklist(void){ int i,add=1,count=0; struct card *p; deck=NULL; for(i=0;i<53;i++){ if(count==4){ add+=1; count=0; } p=talloc(); p->t=add; p->next=p; count++; p->next=deck; deck=p; } return deck; } //山札をシャッフルした後の山札の関数 struct card *shufflelist(void){ int i,a,count=0,r; struct card *d,*p,*q,*shuffle; p=decklist(); shuffle=NULL; while(p!=NULL){ srand(time(NULL)); r=(int)rand()%(N-count); for(i=0;i<r;i++){ p=p->next; } q=talloc(); q->t=p->t; d=p->next; p->next=d->next; q->next=shuffle; shuffle=q; count++; p->next=p; } return shuffle; } //プレイヤーへカードを配るための関数 struct player *person(struct player *PERSON){ struct player *a; struct card *library; int i; PERSON=NULL; library=decklist(); a=lalloc(); while(a!=NULL){ a->card=library->t; for(i=0;i<4;i++){ library=library->next; } a->nextcard=a; a=PERSON; } a->nextcard=NULL; while(a!=NULL){ printf("%d ",a->card); } return PERSON; }

  • UA7l
  • お礼率16% (1/6)

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

  • ベストアンサー
  • 7o8
  • ベストアンサー率55% (5/9)
回答No.6

とりあえず、カードを抜く処理について、抜いたカードの前後に対する 処理の一例として理解いただければ、いいかと思います。 が、実はシャッフルであれば、もっとお手軽にできます。 そう、カードの交換です。 ------------------------------------------------------------ //山札をシャッフルした後の山札の関数 struct card *shufflelist3(void){ int i,j,cnt,r1,r2,t; struct card *p,*p1,*p2; srand(time(NULL)); cnt=rand()%53+30; p=decklist(); for(j=0;j<cnt;j++){ p1=p2=p; r1=(int)rand()%53; r2=(int)rand()%53; if(r1==r2) continue; for(i=0;i<r1;i++) p1=p1->next; for(i=0;i<r2;i++) p2=p2->next; // r1番目とr2番目の入れ替え t=p1->t; p1->t=p2->t; p2->t=t; } return p; } ------------------------------------------------------------ で、気付いたかもしれませんが、ババ抜きにおいて山札は枚数が決まっていて、 カードが配布されたら0になるべきものであるので、配列でOKだったりします。 ポインタ構造は不定枚数の時に効果を発揮しますが、なにぶん、10枚目!といった際に 10枚目を探すことになりますので、例えば p[9]と一発で指定できる配列には かないません。 私はプログラムは一回作ったら必ず見直すようにしています。 配列版にすると全体的な影響が大きすぎるので、プログラムは提示しませんが 上記よりものすごくシンプルになったりします。 #時間がない、といっている中、同じところばかり見ていてすみません。 #ただ、バグが発生しやすいCはプログラムの見直し、及び、確実な仕様の理解は必須です。 > 自分の頭がコンピュータ側としての理解の仕方に合わせれてないことを痛感しました。 > もうちょっと練り考えて見たいと思います。 そんなにコンピュータ側にあわせる必要もないです。 前に提示した私のサンプルはポインタのリスト構造が後ろに伸びていく、ただ それをイメージしただけで、コンピュータ側にあわせたわけではないです。 カードを抜く処理が言葉だけでは伝わらなかったので、サンプルを作ろうと思ったのですが ちょっと思うようにいかず、若干ですが、リスト構造作成の方に手を入れさせて頂きました。 私としてはカードを抜く処理が伝われば、それでいいです。 で、他処理ですが、 ・プレーヤーにカードを配る処理  →A,B,C,Dはグローバル変数にしてしまってもいいのではないでしょうか?   その上で、これからもらうカードとしてa,b,c,d、及び、その手前をaa,bb,cc,ddとして   山札から1枚引く関数を実行、カードが無くなったらループから脱出、って感じに   すればいいでしょう。   山札から1枚引く関数は前に提示した関数を参考にすればいいかと思います。 ・ゲーム実行  4人の内3人はコンピュータでしょうか?  ババ抜きは本来は相手の表情等を伺っての戦略が必要ですが、流石にそういった処理は  難しいので、何も戦略がないとすれば、単に乱数を使用しカードを抜いていく、といった  処理をすればいいだけとなります。  これも山札から1枚抜く処理が主立ったものになるかと思います。  言葉で書くより面倒な処理は多いかとは思いますが、慣れればすぐにできるようになります。  がんばってみてください。

UA7l
質問者

お礼

助言ありがとうございます。  確かに枚数が決まってる処理には不定なリストよりも配列のほうが直接ほしい値に接続できるのが利点でここでは走するべきでした。自分がリストを使おうと思ったのは最初の整列された山札からシャッフルの山札を作るときに配列だとランダムで配列を指定してそこのあたいをマタ別の配列に入れるときランダムで指定する配列の値がかぶってしまうのがきになりリストで実現するほうがイイと思ったのでリストにしたのがおっしゃるとおりむしろ難易度を上げてる気がしてなりませんね。。。。  関数での使い方が凡庸性が高すぎて逆に混乱してしまうことが多々あり山札で一枚引かせる関数などその動作でどこまで細かく分けるのかまだよくわからないことが多いので確認していきたいと思います。  ゲーム実行ではこのばばぬきプログラムはパソコンにババヌキの処理をやらせたいので作ろうとしました。設定はよくありがちな4人くらいが一般的かと思いそうしました。  戦略というよりは個人的につけてみたい機能として「ジョーカーがあるとある動作をする」っという人間らしい考え方を組み込みたいと思ってますが時間がないのでそこまで手が出せるかわからないのが現状です。なので今は短的にプログラムの完成を目指して生きたいと思ってます。  リストでの実現はこれで勉強になるのですが、ただ起源もあり、配列の場合のプログラムが探したところあったのでとりあえずこちらを優先的にプログラムを完成させ、リストでのプログラムも後々完成させたいと思っています。そちらの法に力を入れたいのでこの質問版はとりあえず〆させていただきます。  勝手ながらプログラムそのものを変えてしまって7o8さんにはご迷惑かけました。すみません。 ただ今後に生かせるようにがんばっていきます!!ありがとうございました。お世話になりました。

その他の回答 (5)

  • 7o8
  • ベストアンサー率55% (5/9)
回答No.5

まずはわかりやすいように作るべき何ですが、ここがプログラムの 難しいところであって、各個人に随分と考え方が異なってきてしまいます。 で、申し訳ないんですが、現在のカードのリスト構造における作成方法が 私とあっていないので、どうあるべきか?というのが少々難しく感じてしまっています。 私のイメージするカードのリスト構造は上から順々に生成していく、というもので、 頭の中の整理がつけばどうでもいいことなんですが、イマイチ後ろのカードから 作成していく感覚になじめていないのです。 とりあえず、私の方で作成した、簡単に動作確認をした decklist2及び shufflelist2を以下に記します。 ご参考になれば幸いです。 #変数の命名関連は参考にしないでください。(^_^;;;;; #decklistは正常動作しているのを確認しましたが、こういう作成例があるということで。 struct card *decklist2(void){ int i,add=1,count=0; struct card *p,*pp,*deck; pp=p=talloc(); for(i=0;i<53;i++){ if(count==4){ add+=1; count=0; } deck=p; p->t=add; p->next=talloc(); p=p->next; count++; } free(deck->next); deck->next=NULL; return pp; } //山札をシャッフルした後の山札の関数 struct card *shufflelist2(void){ int i,j,count=0,r; struct card *pd,*pp,*p,*q,*qd,*shuffle; srand(time(NULL)); pp=p=decklist(); qd=q=shuffle=talloc(); for(j=0;j<53;j++){ r=(int)rand()%(53-count); for(i=0;i<r;i++) { pd=p; p=p->next; } //シャッフル後のカードに対する処理 q->t=p->t; qd=q; q->next=talloc(); q=q->next; // pのリストからカードを抜く if(r==0) pp=p->next; //先頭のカードを抜く場合はppを次のカードに移す。 else pd->next=p->next;//そうでなければ前後のカードからの関係を外す。 free(p); //抜かれたカードの領域解放 count++; pd=p=pp; } // 最後の1枚に対する処理 free(qd->next); qd->next=NULL; return shuffle; }

UA7l
質問者

補足

プログラムまでマコトにありがとうございます。なかなか理解するには自分のスペックがちょっと足らない気がします。。。@期限がまもないので理解していきたい気持ち半分プログラムを完成させなければという気持ち半分です。 自分がおもっていたよりも多くの変数が用意なされてたことにちょっと驚きました。また自分の頭がコンピュータ側としての理解の仕方に合わせれてないことを痛感しました。 もうちょっと練り考えて見たいと思います。

  • 7o8
  • ベストアンサー率55% (5/9)
回答No.4

事故レス(^_^ > ただ単純に元々のpの先頭にリセットしたかったのであれば、単純に > 「pp=p=decklist();」に変更、while文最後の「p->next=p;」を > 「p=pp;」にすればいいだけですよ。 分かって頂けるとは思いますが、上記変更ではwhile文は終了しません。 単純にfor文に置き換えるのが手でしょうね

  • 7o8
  • ベストアンサー率55% (5/9)
回答No.3

もう一回プログラムを見直してみました。 ご確認頂けますか? ・shufflelist関数 > for文で繰り返した後での位置からまたカウントすると思ったので一度リセット > する意味で返したつもりなんですけどどういう理由からNGなのでしょうか?  ただ単純に元々のpの先頭にリセットしたかったのであれば、単純に  「pp=p=decklist();」に変更、while文最後の「p->next=p;」を  「p=pp;」にすればいいだけですよ。  ただ、pからカードを抜く処理がうまくいっていないように見えるのが  気になります。  カードを抜くには一つ前のpに対するp->nextに対し、抜かれたpのp->nextを  設定する必要があります。  while文内のforでpツリーを追う際に一つ前のpを保持している必要がありますよね?  あと、シャッフルするのに乱数を使うのは当然ですが、乱数初期化関数を  ループ内で何度も実行するものではありません。  また、乱数初期化関数に定数を設定するものでもないです。  #乱数のハズなのに同じ数しか出てこないことになりますよ。 ・person関数  恐らくですが、libraryへの値設定そのものまではうまくいっています。  で、while文の中でa=PERSON;を実行しているのは何故でしょうか?  結局これが原因で1回でroopを抜け、その後のa->nextcard=NULL;で  aがNULLなのに実行してしまい、エラーになっています。  で、エラーとは全然関係ないのですが、person関数はmainからユーザAに  対して実行するようになっています。  ユーザAのためにカードを初期化する、って変じゃないですか?  (これはデバッグ用?shufflelist関数内にあるのはOKだとは思います)  そもそも関数仕様からすると、main()関数内でAに対し領域を割り当てる  べきかと思います。 ・main関数  まずはA、B、C、Dに領域を割り当てましょう。  で、最初に呼ぶのはshufflelist関数ですよね?  person関数でユーザにカードを割り当てるのであれば、1枚1枚割り当てるような  関数に変更した方がいいかと思います。  (カードは53枚ありますからね) ・その他  カードを抜く関数を作成した方がいいですかね。  そーすればshufflelist関数でも使用できますし、ユーザからのカードを  抜く処理にも使えます。  カードリストから先頭の削除を行う処理がキモですが、ポインタのポインタを  使えばいいかとおもいます。

UA7l
質問者

補足

助言ありがとうございます。 >ただ単純に元々のpの先頭にリセットしたかったのであれば、単純に >pp=p=decklist();」に変更、while文最後の「p->next=p;」を >p=pp;」にすればいいだけですよ。  この部分ですがp->nextを最初に戻すのはリストの先頭であるshuffleをさすべきだと思ったのでp->next=shuffle;だと思いました。  person関数では処理がおかしいですね。ありがとうございます。 乱数のところですがそういう仕様だとは知らずwhile分の中に入れてました。  mainからその他については個人的にperson関数では配るだけをさせメインの中で配られたそれぞれのリストをさすためのA,B,C,Dを用意させそこに代入させようかと思います。カードを抜く関数は同時に捨てさせる機能を搭載してプレイヤー間で使いたいとおもっています。 チョット自分でも7o8さんのおっしゃっている >ただ、pからカードを抜く処理がうまくいっていないように見えるのが>気になります。カードを抜くには一つ前のpに対するp->nextに対し、 >抜かれたpのp->nextを 設定する必要があります。while文内のforでp >ツリーを追う際に一つ前のpを保持している必要がありますよね? の部分は新しく*dをつくりd=p->next;p->next=d->next;free(d);と続けそのpのさしている部分を開放しなくせばいいと思い組んでみましたが、1回目は返せても2回目以降の試行でもでてきます。 今のところの改良し手を加えたプログラムは下記です。 #include<stdio.h> #include<stdlib.h> #include<string.h> #include<time.h> #define N 53 //デッキのカードの構造体 struct card{ int t; struct card *next; }; //カードを配った後のそれぞれのプレイヤーの情報(仮 struct player{ int card; struct player *nextcard; struct player *nextturn; }; //関数定義 struct card *talloc(void); struct player *lalloc(void); struct card *decklist(void); struct card *shufflelist(void); struct player *person(void); void displist(void); //void displist(struct player *hito); int main(void){ struct player *A,*B,*C,*D; /* A=person(); displist(A); B=person(); displist(B); C=person(); displist(C); D=person(); displist(D); */ displist(); return 0; } //card構造体のセルの確保 struct card *talloc(void){ return (struct card *)malloc(sizeof(struct card)); } //player構造体のセルの確保 struct player *lalloc(void){ return (struct player *)malloc(sizeof(struct player)); } //カードを切る前の整列された山札の関数 struct card *decklist(void){ int i,add=1,count=0; struct card *p,*deck; deck=NULL; for(i=0;i<53;i++){ if(count==4){ add+=1; count=0; } p=talloc(); p->t=add; p->next=p; count++; p->next=deck; deck=p; } return deck; } //山札をシャッフルした後の山札の関数 struct card *shufflelist(void){ int i,j,a,count=0,r; struct card *d,*p,*q,*shuffle; p=decklist(); shuffle=NULL; srand(time(NULL)); // for(j=0;j<20;j++){ r=(int)rand()%(51-count); for(i=0;i<r;i++){ p=p->next; } q=talloc(); q->t=p->t; d=p->next; p->next=d->next; free(d); q->next=shuffle; shuffle=q; count++; p->next=shuffle; // } return shuffle; } //プレイヤーへカードを配るための関数 struct player *person(void){ struct player *a,*hito; struct card *library,*old; int i; hito=NULL; library=decklist(); old=decklist(); while(library->next!=NULL){ a=lalloc(); a->card=library->t; old->next=library->next; for(i=0;i<4;i++){ library=library->next; } a->nextcard=hito; hito=a; } return hito; } //表示用関数 void displist(void){ struct card *p; p=shufflelist(); while(p!=NULL){ printf("%d ",p->t); p=p->next; } }

  • 7o8
  • ベストアンサー率55% (5/9)
回答No.2

shufflelist()内のwhile文継続条件は pがNULLでないこと、となっています。 で、これはどこかでpがNULLになることを期待しているとは思うのですが、 そのwhile文最後で、「p->next=p;」を実行しています。 pがNULLになることがあるのであれば、この実行は NGですし、おそらく それが原因で異常終了しているかと思います。 person()も同様で while文継続条件は aがNULLでないこと、となっています。 つまり、while文を抜けた時点で aはNULLであり、その直後に 「a->nextcard=a;」を実行しています。 確認してみては如何でしょうか?

UA7l
質問者

補足

助言ありがとうございます。 最後にあるp->next=p;は自分でも確信はないんですが上のfor文でポインタを移動し値を示しているのでwhile文で次の処理をするときp->nextがshuffleからでなくfor文で繰り返した後での位置からまたカウントすると思ったので一度リセットする意味で返したつもりなんですけどどういう理由からNGなのでしょうか?今書いて思ったのでリセットという意味では一度p->nextにshuffleをいれるとリセットされると思ったんですがこれも何かでます。。。 person()の方は条件文を間違えました。このときはlibraryからそれぞれプレイヤーに配るので判定はaではなくlibraryの方でやってみましたがこれでもだめでした。 まだCプログラムを書く上で知識が足りない部分もあり完成させるのに時間がかかるかもしれませんがこれを完成させたいと思っています。 期限も間近に近づいていることもあり焦っています。。。 さまざまな意見よろしくお願いします。

回答No.1

まず、「デバッグが起きる」という言い方はしません。 添付の画像のようなメッセージボックスが出ていると思いますが、これを見ると「例外が発生する」という記述があります。 これであれば通じます。 いまひとつ何がやりたいのか分かりませんが、まず「例外が発生する」原因について person関数で変数[PERSON]にNULLを設定しています。 その後、[PERSON]はperson関数内で変更されていません。 whileの中で変数[a]に変数[PERSON]の値を入れています。 (結果、変数[A]はNULLになります。) その後、[a->nextcard=NULL]の行で変数[a]がNULLのため「例外が発生」しています。 C言語の変数名は小文字から始まり、なるべく小文字で表現するのが通例です。 最初[PERSON]を見たとき、defineで定義されている定数かと思ってしまいました。。。

関連するQ&A

  • C言語のプログラム

    以下のプログラムはハッシュテーブルを用いて文字列を探すプログラムなのですが、コンパイル時にセグメントエラーとなってしまいます。プログラム中に誤った箇所があれば教えて頂きたいです。 #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 10 #define MAX_LEN 64 #define N_WORDS 4 struct list { char word [MAX_LEN]; struct list *next; }; struct list *hash_table[HASHSIZE]; char colors[N_WORDS][MAX_LEN] = {"red", "blue", "green", "yellow"}; void my_strcpy(char* a, const char* b) { int i = 0; while(*b != '\0'){ *(a+i) = *(b+i); i++; } *(a+i) = '\0'; } int hash(char *key) { int hashval = 0; while (*key != '\0') { hashval += *key; key++; } return (hashval % HASHSIZE); } int find_word (char *key) { struct list *p; for (p = hash_table[hash(key)]; p != NULL; p++) if (strcmp(key, p->word) == 0) return 1; return 0; } void init_hash_table() { int i, hashvalue; struct list *p, *q; for (i = 0; i < HASHSIZE; i++) { hash_table[i] = NULL; } for (i = 0; i < N_WORDS; i++) { if ((find_word(colors[i])) == 0){ p = (struct list *)malloc(sizeof(struct list)); my_strcpy(p->word, colors[i]); hashvalue = hash(colors[i]); if (hash_table[hashvalue] = NULL) { hash_table[hashvalue] = p; p->next=NULL; } else { q = hash_table[hashvalue]; while (q->next != NULL) q = q->next; q->next = p; p->next=NULL; } } } } void main(void) { init_hash_table(); printf("result = %d\n", find_word("red")); }

  • プログラミング構造体について。

    include<stdio.h> #include<stdlib.h> #include<string.h> struct person{ char name[10]; int gender; int age; }; void printPersonList(struct person *person_p, int size); void outputPersonList(struct person *person_p, int size); double getAverageOfAge(struct person *person_p, int size); int countMales(struct person *person_p, int size); int countFemales(struct person *person_p, int size); int main(void){ struct person *person_p; int i, count, gender, age, maleCount, femaleCount; char name[20]; double average; printf("登録する人数を入力してください。\n"); scanf("%d", &count); person_p = (struct person*)malloc(sizeof(struct person)* count); for(i=0; i < count; i++){ printf("名前・性別(男性:0, 女性:1)・年齢をスペース区切りで入力してください。\n"); scanf("%s %d %d", name, &gender, &age); strcpy((person_p + i) -> name, name); (person_p + i) -> gender = gender; (person_p + i) -> age = age; } printPersonList(person_p, count); outputPersonList(person_p, count); average = getAverageOfAge(person_p, count); printf("平均年齢:%f\n", average); maleCount = countMales(person_p, count); femaleCount = countFemales(person_p, count); printf("男性:%d名, 女性:%d名\n", maleCount, femaleCount); free(person_p); return 1; } void printPersonList(struct person *person_p, int size){ int i; printf("登録リスト\n"); printf(" name | gender | age\n"); printf("----------+--------+-----\n"); for(i=0; i < size; i++){ printf("%10s | %1d | %2d\n", (person_p + i) -> name, (person_p + i) -> gender, (person_p + i) -> age); } } void outputPersonList(struct person *person_p, int size){ FILE *output; int i; if((output = fopen("meibo.c", "w")) == NULL){ printf("meibo.cを開けませんでした。\n"); return; } for(i=0; i < size; i++){ fprintf(output, "%s, %d, %d\n", (person_p + i) -> name, (person_p + i) -> gender, (person_p + i) -> age); } fclose(output); } 残り3つの関数をすべて定義する(それぞれ10行程度) getAverageOfAge, countMales, countFemales どう定義すればいいのか教えてください。お願いします。

  • プログラミングの質問です

    #include<stdio.h> #include<stdlib.h> #include<string.h> struct person{ char name[10]; int gender; int age; }; void printPersonList(struct person *person_p, int size); void outputPersonList(struct person *person_p, int size); double getAverageOfAge(struct person *person_p, int size); int countMales(struct person *person_p, int size); int countFemales(struct person *person_p, int size); int main(void){ struct person *person_p; int i, count, gender, age, maleCount, femaleCount; char name[20]; double average; printf("登録する人数を入力してください。\n"); scanf("%d", &count); person_p = (struct person*)malloc(sizeof(struct person)* count); for(i=0; i < count; i++){ printf("名前・性別(男性:0, 女性:1)・年齢をスペース区切りで入力してください。\n"); scanf("%s %d %d", name, &gender, &age); strcpy((person_p + i) -> name, name); (person_p + i) -> gender = gender; (person_p + i) -> age = age; } printPersonList(person_p, count); outputPersonList(person_p, count); average = getAverageOfAge(person_p, count); printf("平均年齢:%f\n", average); maleCount = countMales(person_p, count); femaleCount = countFemales(person_p, count); printf("男性:%d名, 女性:%d名\n", maleCount, femaleCount); free(person_p); return 1; } void printPersonList(struct person *person_p, int size){ int i; printf("登録リスト\n"); printf(" name | gender | age\n"); printf("----------+--------+-----\n"); for(i=0; i < size; i++){ printf("%10s | %1d | %2d\n", (person_p + i) -> name, (person_p + i) -> gender, (person_p + i) -> age); } } void outputPersonList(struct person *person_p, int size){ FILE *output; int i; if((output = fopen("meibo.c", "w")) == NULL){ printf("meibo.cを開けませんでした。\n"); return; } for(i=0; i < size; i++){ fprintf(output, "%s, %d, %d\n", (person_p + i) -> name, (person_p + i) -> gender, (person_p + i) -> age); } fclose(output); } 上は、「キーボードで入力した個人データ(名前、性別、年齢)を構造体に入れて、一覧を画面に出し、かつ、ファイルに書き出す」ことをするプログラムです。これを名前が辞書順になるようにしたいです。どう書くのか教えてください。

  • 連結リストによるデータ管理プログラムの解説

    ★から★までのプログラムが、各行ごとにどのような動きをしているのか簡潔な言葉で説明を書いていただきたいのです。必要がないと判断した行はとばして下さって構いません。 (例) printf("hello!"); …hello!と表示 if(a==0){ …aが0なら #include <stdio.h> #include <stdlib.h> struct CELL{ struct CELL *next; char data; }; /* Head CELL CELL CELL +-------+ +-------+ +-------+ +-------+ | ? | *----> | 5 | *----> | 6 | *----> | 8 | / | +-------+ +-------+ +-------+ +-------+ */ main(void){★ struct CELL head; struct CELL *p, *wp; char a; head.next=NULL; printf("?\n"); scanf("%c %*c",&a); while(a!='0'){ printf("mode?\n"); scanf("%c",&mode); if(mode=="a"){ p=&head; while(p->next!=NULL){ p=p->next; } wp=(struct CELL *)malloc(sizeof(struct CELL)); if(wp==NULL){ printf("cannot allocate enough memory.\n"); return 0; } p->next=wp; p->next->data=a; p->next->next=NULL; printf("?\n"); scanf("%c %*c",&a); } if(mode=="p"){ printf("\n\nNow...\n"); p=&head; while(p->next!=NULL){ printf("%c --> \n",p->next->data); p=p->next; } printf("NULL\n"); if(mode=="d"){ p=&head; while(p->next->data==a){ p=p->next; } if(p==NULL) break; wp=p->next->next; while(p->next->data==a) p=wp;★ } } return 0; }

  • ポインタの扱い

    すみません、構造体へのポインタの配列の扱いに困っています。 下記ソースの struct list *hashtable[HASHSIZE]; の箇所をmain部に入れた場合の処理がうまくいきません。。 どのように修正すれば良いのでしょうか。 申し訳ありませんが教えてください。 --------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 40 #define MAX_KW_LEN 256 #define NUM_KW 23 #define TRUE 1 #define FALSE 0 struct list { char keyword[MAX_KW_LEN]; struct list *next; }; struct list *hashtable[HASHSIZE]; static char kw[NUM_KW][MAX_KW_LEN] = { "auto", "break", "double", "enum", "char", "continue", "extern", "float", "for", "int", "long", "register", "short", "signed", "static", "struct", "typedef", "union", "unsigned", "return", "void", "volatile", "while" }; int Hash(char *key); void InitHTable(void); int FindKeyWord(char *key); void ListKeyWord(void); void FreeKeyWord(void); int main(void); int Hash(char *key) { int hashval = 0; while (*key != '\0') hashval += *key++; return (hashval % HASHSIZE); } void InitHTable(void) { int i; struct list *p, *q; int hashval; for (i = 0; i < NUM_KW; i++) { printf("%d\n",i); if ((FindKeyWord(kw[i])) == FALSE) { if ((p = (struct list *)malloc(sizeof(struct list))) == NULL) { fprintf(stderr, "メモリ不足です。\n"); exit(2); } strcpy((*p).keyword, kw[i]); hashval = Hash(kw[i]); if (hashtable[hashval] == NULL) { hashtable[hashval] = p; p->next = NULL; } else { q = hashtable[hashval]; while (q->next != NULL) { q = q->next; } q->next = p; p->next = NULL; } } } } int FindKeyWord(char *key) { struct list *p; for (p = hashtable[Hash(key)]; p != NULL; p = p->next) if (!strcmp(key, (*p).keyword)) return (TRUE); return (FALSE); } void ListKeyWord(void) { int i; struct list *p; for (i = 0; i < HASHSIZE; i++) for (p = hashtable[i]; p != NULL; p = p->next) printf("予約語:%s ハッシュ値:%d:\n", (*p).keyword, Hash((*p).keyword)); } void FreeKeyWord(void) { int i; struct list *p, *q; for (i = 0; i < HASHSIZE; i++) for (p = hashtable[i]; p != NULL; ) { q = p->next; free(p); p = q; } } int main(void) { char word[MAX_KW_LEN]; int i; InitHTable( ); ListKeyWord( ); for (i = 0; i < 4; i++) { printf("Cの予約語を入力して下さい "); fgets(word, 128, stdin); if ((FindKeyWord(word)) == TRUE) printf("%s は登録済みです。\n", word); else printf("%s は未登録です。\n", word); } FreeKeyWord( ); }

  • バブルソートを使って文字列を辞書順に並べるプログラムを作成したいのです

    バブルソートを使って文字列を辞書順に並べるプログラムを作成したいのですがうま... it200189さん バブルソートを使って文字列を辞書順に並べるプログラムを作成したいのですがうまくいきません・・・。 バブルソートを使って文字列を辞書順に並べるプログラムを作成したいのですが、コンパイルはできますが実行してもうまく出力されません・・・。 どこがおかしいのか、わからないので詳しい方よろしくお願いします。 またこのやり方とは異なる方法で作成できるという方せひプログラムを掲載してください! 参考にさせていただきます! #include<stdio.h> #include<string.h> struct QUEUE{ struct QUEUE *prev; struct QUEUE *next; char alpha[]; }; static struct QUEUE name[10]; void InQueue(struct QUEUE * dst ,struct QUEUE *src){ src->prev = dst->prev; src->next = dst->prev->next; dst->prev = src; dst->prev->next = src; } void DeQueue(struct QUEUE *src){ src->prev->next = src->next; src->next->prev = src->prev; } void InitQueue(struct QUEUE *pQueue ,int size){ int i; struct QUEUE *pEndQueue; struct QUEUE *pTempQueue; pEndQueue = pQueue + size-1; pQueue->prev = NULL; pQueue->next = pEndQueue; pEndQueue->prev = pQueue; pEndQueue->next = NULL; pTempQueue = pQueue + 1; pEndQueue = pEndQueue - 1; pTempQueue->prev = NULL; pTempQueue->next = pEndQueue; pEndQueue->prev = pTempQueue; pEndQueue->next = NULL; i = 3; while ( i < size - 2) { pTempQueue = pQueue + i; InQueue(pEndQueue,pTempQueue); i++; } } void BubbleSort(struct QUEUE *pSort ,int size){ int i; int j; // struct QUEUE *pTemp; // pTemp = pSort; while(size > 0){ i = 0; // pSort = pTemp; pSort = name[1].next; while(i < size - 1){ j = 0; while(pSort->alpha[j] != '\0'){ if(pSort->alpha[j]>pSort->next->alpha[j]){ DeQueue(pSort->next); InQueue(pSort,pSort->next); break; } else if(pSort->alpha[j]<pSort->next->alpha[j]){ pSort = pSort->next; break; } j++; } i++; } size--; } } void main(){ int i; // static struct QUEUE name[10]; struct QUEUE *pStr; char str[4][10] = {"tani","okada","naka","oka"}; InitQueue(name,8); i = 0; while(i<4){ strcpy(name[i + 2].alpha,str[i]); i++; } BubbleSort(name[1].next,4); pStr = name[1].next; i = 0; while(i<4){ printf("%s\n",pStr->alpha); pStr = pStr->next; i++; } }

  • 単方向リストに適当な値を入れて、逆順に表示するプログラムの仕組みがわかりません。

    以下のプログラムのReverceShowValue関数の仕組みがわかりません。 申し訳ございませんが、ご教授の方、よろしくお願いします。 #if 1 /* リスト構造の実装 * 再帰関数を用いて逆順に表示 */ #include <stdio.h> #include <stdlib.h> typedef struct object{ int value; struct object *next; }OBJ; OBJ* AllocateBlock(int value) { OBJ *block; block = (OBJ*)malloc(sizeof(OBJ)); if(block == NULL){ printf("Allocate Error\n"); exit(1); } block->value = value; block->next = NULL; return block; } void ReverceShowValue(OBJ *p) { if(p != NULL){ ReverceShowValue(p->next); printf("%d\n", p->value); } } void FreeAllocate(OBJ *p_top) { OBJ *temp; while(p_top != NULL){ temp = p_top->next; free(p_top); p_top = temp; } } int main(void) { OBJ *top = NULL; OBJ *temp; int i; for(i = 0;i < 10;i++){ if(top == NULL){ top = AllocateBlock(i); temp = top; } else{ temp->next = AllocateBlock(i); temp = temp->next; } } ReverceShowValue(top); FreeAllocate(top); return 0; } #endif

  • C言語の自己参照型プログラムについて

    #include <stdio.h> #include <string.h> #include <stdlib.h> struct list { int key; /* キー */ char name[20]; /* 名前 */ struct list *next; /* 次のデータへのポインタ */ }; struct list *add_list(int key, char *name, struct list *head); void show_list(struct list *p); void free_list(struct list *p); int main(void) { struct list *head; /* 先頭ポインタ */ char name[20]; int key = 0; head = NULL; /* 先頭ポインタにNULLを設定 */ printf("キーと名前(MAX:19文字)を入力(終了:CTRL+Z)\n"); while (scanf("%d %s", &key, name) != EOF) { /* リストにデータを登録 */ head = add_list(key, name, head); } /* リストの表示 */ show_list(head); /* リストの開放 */ free_list(head); return 0; } /*** リストにデータを登録 ***/ struct list *add_list(int key, char *name, struct list *head) { struct list *p; /* 記憶領域の確保 */ if ((p = (struct list *) malloc(sizeof(struct list))) == NULL) { printf("malloc error\n"); exit(EXIT_FAILURE); } /* リストにデータを登録 */ p->key = key; strcpy(p->name, name); /* ポインタのつなぎ換え */ p->next = head; /* 今までの先頭ポインタを次ポインタに */ head = p; /* 新たな領域を先頭ポインタに */ return head; } /*** リストの表示 ***/ void show_list(struct list *p) { while (p != NULL) { /* 次ポインタがNULLまで処理 */ printf("%3d %s\n", p->key, p->name); p = p->next; } } /*** リストの開放 ***/ void free_list(struct list *p) { struct list *p2; while (p != NULL) { /* 次ポインタがNULLまで処理 */ p2 = p->next; free(p); p = p2; } } これを実行すると、 新しく入力された順にリストが表示されます。 そうではなく、キーの昇順に表示したいです。 どなたかそのように実行できるようにプログラムを書き換えてくれませんか? 図々しいですがよろしくお願いいたします。m(_ _)m

  • 構造体へのポインタ

    すみません、構造体へのポインタの配列の扱いに困っています。 下記ソースの struct list *hashtable[HASHSIZE]; の箇所をmain部に入れた場合の 他の関数内での使用の仕方が全くわかりません。 どのように修正すれば良いのでしょうか。 申し訳ありませんが教えてください。 --------------------- #include <stdio.h> #include <stdlib.h> #include <string.h> #define HASHSIZE 40 #define MAX_KW_LEN 256 #define NUM_KW 23 #define TRUE 1 #define FALSE 0 struct list {  char keyword[MAX_KW_LEN];  struct list *next;   /* 次の list へのポインタ */ }; struct list *hashtable[HASHSIZE]; /* ハッシュテーブル */ /* キーワード ( Cの予約語 ) */ static char kw[NUM_KW][MAX_KW_LEN] = {   "auto", "break", "double",   "enum", "char", "continue", "extern", "float", "for", "int",   "long", "register", "short", "signed", "static",   "struct", "typedef", "union", "unsigned", "return",   "void", "volatile", "while" }; int Hash(char *key); void InitHTable(void); int FindKeyWord(char *key); void ListKeyWord(void); void FreeKeyWord(void); int main(void); int Hash(char *key) {  int hashval = 0;  while (*key != '\0')   hashval += *key++;  return (hashval % HASHSIZE); } void InitHTable(void) {  int i;  struct list *p, *q;  int hashval;  for (i = 0; i < NUM_KW; i++) {   printf("%d\n",i);   if ((FindKeyWord(kw[i])) == FALSE) { /* 登録されていなかったら */             /* メモリを割り付ける */    if ((p = (struct list *)malloc(sizeof(struct list))) == NULL) {     fprintf(stderr, "メモリ不足です。\n");     exit(2);    }    strcpy((*p).keyword, kw[i]);    hashval = Hash(kw[i]);    /* ハッシュ値を求めて */        if (hashtable[hashval] == NULL) { /* 未登録なら */     hashtable[hashval] = p;  /* p の指すアドレスを登録 */     p->next = NULL;    /* リストの末尾に NULL を追加 */    }    else {        /* 既に登録していたら */     q = hashtable[hashval];     while (q->next != NULL) {  /* データがなくなるまで */      q = q->next;    /* リストをたどる */     }     q->next = p;     /* リストの末尾に p の指すアドレスを登録 */     p->next = NULL;    /* その末尾に NULL を追加 */    }   }  } } int FindKeyWord(char *key) {  struct list *p;  for (p = hashtable[Hash(key)]; p != NULL; p = p->next)   if (!strcmp(key, (*p).keyword))  /* 登録済みなら */    return (TRUE);     /* TRUE を返す */   return (FALSE);      /* 未登録ならFALSE を返す */ } void ListKeyWord(void) {  int i;  struct list *p;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; p = p->next) /* p が NULL でなければ */               /* ハッシュ値とキーワードを表示 */    printf("予約語:%s ハッシュ値:%d:\n", (*p).keyword, Hash((*p).keyword)); } /* malloc( ) で割り付けたメモリを解放 */ void FreeKeyWord(void) {  int i;  struct list *p, *q;  for (i = 0; i < HASHSIZE; i++)   for (p = hashtable[i]; p != NULL; ) { /* p が NULL でなければ */    q = p->next;      /* p->next を保存 */    free(p);       /* メモリを解放 */    p = q;        /* p->next を p に代入 */   } } int main(void) {  char word[MAX_KW_LEN];  int i;  InitHTable( );  ListKeyWord( );  for (i = 0; i < 4; i++) {   printf("Cの予約語を入力して下さい ");   fgets(word, 128, stdin);   if ((FindKeyWord(word)) == TRUE)    printf("%s は登録済みです。\n", word);   else    printf("%s は未登録です。\n", word);  }  FreeKeyWord( ); }

  • 双方向リストのバブルソートについて

    双方向リストをバブルソートを用いてソートしたいです。 下記がプログラム(一部)ですが、ソートした後にリスト表示すると 無限ループに陥ります。 どこがいけないのでしょうか。 #include <stdio.h> #include <stdlib.h> struct cell{ int data; struct cell *next, *prev; }; void insert_head(struct cell **head, int num){ struct cell *p, *p1; p = *head; p1 = make_cell(); *head = p1; p1->data = num; p1->next = p; if(p1->next != (struct cell *)NULL){ p1->next = p; p->prev = p1; } } void print_list(struct cell *head){ struct cell *p; p = head; printf("data = \n"); while(p != (struct cell *)NULL){ printf("%d\n", p->data); p = p->next; } } void sort_list(struct cell **head){ struct cell *p, *p2; int i, n; n = 0; p = *head; while(p->next != (struct cell *)NULL){ p = p->next; n++; } for(i = 0, p = *head; i < n-2; i++){ if(p->data > p->next->data){ if(p == *head){ *head = p->next; }else{ p->prev->next = p->next; } p2 = p->next; p->next = p->next->next; p->next->next = p; p->next->next->prev = p; p->next->prev = p->prev; p->prev = p2; }else p = p->next; } } int main(void){ struct cell *head = (struct cell *)NULL; int n; while(1){ printf("1:Insert head 2:Insert tail 3:Delete 4:List 5:Sort 6:Exit\n"); scanf("%d", &n); switch(n){ case 1: printf("num = "); scanf("%d", &n); insert_head(&head, n); break; case 2: printf("num = "); scanf("%d", &n); insert_tail(&head, n); break; case 3: printf("num = "); scanf("%d", &n); delete_cell(&head, n); break; case 4: print_list(head); break; case 5: sort_list(&head); break; case 6: return 0; break; } } }

専門家に質問してみよう