• ベストアンサー

碁石、順列

こんばんわ。 つい最近 別件で質問させていただいたばかりですが、 またプログラミングに関して 解決できないことがありまして ここに来ました(汗) タイトルの通りの問題なのですが、 何個かある碁石の中から いくつか取り出して、それを並べる には 何通りの順列がありうるかを算出するプログラムを 作りたいのですが、 たとえば 白が2個、黒が2個あったとして そこからランダムに3個とった場合について説明 させていただきます。 今書いているプログラムは、 ランダムに取り出してきた3個を choice[]という配列に格納します。 そして、順列ですから 重複してはいけないということで 今まで生成した順列にかぶるものがないか 確認できなければ いけないので、重複のないように、今までに選んだ3個の並びを stock[][]という二次元配列に格納していくようにしました。 ここが問題になっています。ここでバグがおきていて(私の 無知により間違った記述をしているためと思われますが、) for(i=0;i<5;i++){ for(j=0;j<3;j++){ stock[i][j] = choice[j]; } } printf("stock:%s\n",stock[0]); *stock[i][j]は、あらかじめ'E'で初期化をしております。 上記のように書きました。 これは、選択した3つが入ったchoice[j]を、stockの中に 同じものがないかを確認して、なければ代入する という感じで 書いたものです。 で、printf文は、stock[0]つまり stock[0][0]~stock[0][2] を表示させて、choiceと同じ3つが入っているか確認したかった ためなのですが、 choiceがWBB(白、黒、黒の意味)のとき stock:WBBEEEEEEEEEEEE と表示されてしまいます。 私は、stock:WBB となることを期待していたのですが。。。 で、たとえば次に選択した3つがBWBだとしたら 前にストックしたWBBとは違うから またstock[][]に代入する ことにして、 stock[1]が、BWB となるようにしたいのです。 そうやって貯めていければ、たとえば 上記のように 2回目に選択したとき、 choiceが stock[][]の中にあるものと、一致したら 重複順列だからカウントしない というようなことができるのですが、 そもそもstockへの入り方が期待したものと違い よくわからないことになっているものですから、 すべて、”一致していない”のほうを通ってしまい、 正常に実行できないでおります。 いったい、何を勘違いしており、どのようにすれば 解決できるのでしょうか(>_<) どなたかアドバイスいただけますでしょうか。 お手数ですが、よろしくお願いいたしますm(_ _)m

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

  • ベストアンサー
  • yama5140
  • ベストアンサー率54% (136/250)
回答No.4

>choiceがWBB(白、黒、黒の意味)のとき >stock:WBBEEEEEEEEEEEE >と表示されてしまいます。 >私は、stock:WBB >となることを期待していたのですが。。。  みなさん言われるように文字列の終端には、\0 があること。  その \0 を入れるための配列の確保が必要です。 >stock[i][j]は、あらかじめ'E'で初期化をしております。  たっぷり(今回の例では、[ 5 ][ 3 ] → [ 5 ][ 8 ] 位)配列を用意し、  ★あらかじめ '\0' で初期化をするか、   nn = 0;   ・・   stock[ i ][ nn++ ] = choice[ j ];   stock[ i ][ nn ] = '\0';   ・・と  ★1文字代入の都度、次を '\0' で終端処理すれば間違いがないかと思います。   何度も繰り返すときは、こちらがもちろんお勧め。 なお、文字列の比較には、strcmp() を使えば平易かと思います。  http://www.bohyoh.com/CandCPP/C/Library/strcmp.html #include <stdio.h> #include <string.h> void main() {  char cStokA[ 5 ][ 3 ] = { "123", "456", "789" };  char cStokB[ 5 ][ 8 ] = { "123", "456", "789" }; // コンパイラが、\0 を  char cStokC[ 5 ][ 8 ] = { "123\0", "456\0", "789\0" }; // 冗長  char cStokD[ 5 ][ 8 ] = { { '\0' } }; // あらかじめ全てを '\0' で初期化  printf( "[%s]\n", cStokA[ 0 ] );  printf( "[%s]\n", cStokB[ 0 ] );  printf( "[%s]\n", cStokC[ 0 ] );  printf( "[%s]\n", cStokD[ 0 ] );  if( 0 == strcmp( cStokA[ 0 ], cStokB[ 0 ] ) ) printf( "cStokA[ 0 ] == cStokB[ 0 ]\n" );  if( 0 == strcmp( cStokA[ 0 ], cStokC[ 0 ] ) ) printf( "cStokA[ 0 ] == cStokC[ 0 ]\n" );  if( 0 == strcmp( cStokB[ 0 ], cStokC[ 0 ] ) ) printf( "cStokB[ 0 ] == cStokC[ 0 ]\n" ); } 注:インデントに全角空白を用いています。コピペ後、タブに一括変換して下さい。

すると、全ての回答が全文表示されます。

その他の回答 (3)

  • takoashi
  • ベストアンサー率39% (21/53)
回答No.3

char stock[3][3]; を char stock[3][4]; みたいにするんですよ。 stock[0][3] = 0: stock[1][3] = 0: stock[2][3] = 0: 文字列というのが、C言語ではどいうものなのか? 2重配列では、どのようにメモリが確保されるのか? ということを勉強しなおしたほうがいいです。

すると、全ての回答が全文表示されます。
  • salsberry
  • ベストアンサー率69% (495/711)
回答No.2

printf()の%sで出力するにはC言語の文字列の形になっている必要があります。"WBBEEEEEEEEEEEE"と表示されてしまうということは、文字列の終端を示す'\0'が"WBB"の直後に入っていないということです。おそらく最後の'E'の後にも'\0'を入れていないだろうと思うので、出力がそこで終わっているのは単なる偶然です。 配列の大きさを変えて'\0'を追加する、あるいは%sを使うのをやめるなどの方法を考える必要があるでしょう。

donntakosu
質問者

補足

ありがとうございます! いただいたアドバイスの '\0'を付加する というのを明示的に付け加えたところ ほんの少し解決に近づきました。 たとえば、今まで stock:WBBWEEとなっていたのが stock:WBBWとなってくれました。 しかし 本当はstock:WB と    stock:BW に分かれてほしいのですが stock[0]として表示させても やはり stock[0]とstock[1]がくっついて表示されます。。。 そういう現象が起きているので、 やはり stockの中とchoiceを比較して 同じ2文字があったら 重複するので追加しない という機能もうまくいっておらず 重複したのもかまわずにstockの中に追加してしまっているようなんです。。。 いったい 何が間違っているのでしょうか(>_<)

すると、全ての回答が全文表示されます。
  • takoashi
  • ベストアンサー率39% (21/53)
回答No.1

Eで初期化しているのだから、Eが出力されるのは正しいのでは?

donntakosu
質問者

補足

回答ありがとうございます。 プログラムはほぼ独学で もしかしたらとても基礎の 部分で勘違いしたまま覚えていることもあるかもしれず おばかな質問しているとしたらすみません 汗 Eで形だけ初期化しておりますが たとえば stockがstock[3][3]の大きさだとすると □□□ □□□ □□□ ですよね。。。 そこに Eで初期化したのだから E E E E E E E E E となるわけですよね。 そして、stock[0]にchoice(=WWB)を入れたとしたら W W B E E E E E E になりますよね。 この状態で printf("stock:%s \n",stock[0]); としたとき、 stock:WWBEEEEEE と表示されてしまうのですが、 stock[0] と記すと stock[0][0]~stock[0][2]の 行が0の部分だけをさすようにはならないのですか?? stock:WWBというふうに、行が0の部分だけ表示される と思っていたのですが。。。 なぜそこにこだわるかといいますと、 たとえば stock[0]: W W B stock[1]: W B W stock[2]: B B W となっていたとして、そこに新たにchoice(=WBW)という順列が 生成されても、choice とstock[0]~[2]を順に比較していき、 choice == stock[1]だから これは重複している、stockリスト には追加しない! と判定させたいのですが、 stock[0]といったとき、まるでこの行列すべてをさしているかのように 見えていたので、頭が混乱してしまっているところなのです。。。 この説明でも分かりづかたっらすみません(>_<)

すると、全ての回答が全文表示されます。

関連するQ&A