ハマっている「お菓子」を教えて!

Cygwinにてアルゴリズムの勉強のためにC言語で
コーディングしているのですが、Segmentation fault (core dumped)
という言葉が出てファイルを実行できません。
試行錯誤しているのですが手に負えません。
よろしくお願いします。

#include <stdio.h>
#include <stdlib.h>

#define MAX_LINE 30


int main(void);

int main(void){
char buffer[3];
int taro,hanako,number;

int judge[4][4] = {{3,1,2,2,},
           {2,3,1,2,},
            {1,2,3,2,},
            {1,1,1,3,},
               };

char kekka[3][MAX_LINE] = {"太郎の勝ち",
"花子の勝ち",
"あいこ"
};

gets(buffer);
taro = atoi(buffer);
taro = taro-1;
gets(buffer);
hanako = atoi(buffer);
hanako = hanako-1;

number = judge[taro][hanako];

printf("じゃんけんの結果は%sです。",kekka[number][MAX_LINE]);

return(0);
}

A 回答 (6件)

大事なことは、せっかく配列の添字が0から始まるのを考慮して、


taro=taro-1;
hanako=hanako-1;
しているのに、judgeの時にそれを忘れている事。
だから、kekka[number]のnumberは、-1してやらねばなりません。
もう一つ大事なこと、
kekka[number][MAX_LINE]は、評価結果が文字型である、という事。
で、printfは、%sと解釈しますので、それを参照先として、つまりポインタとして読もうとします。
ここで表示したいのは、「勝ち」「負け」などの文字列ですので、その先頭へのポインタを渡さねばなりません。
kekka[number]は、それぞれの文字列の先頭へのポインタになります。
以下のコメントの後の文を追加すると、いいでしょう。
あ、あと、入力の前には、プロンプトくらい出したほうがいいと思いますよ。

#include <stdio.h>
#include <stdlib.h>

#define MAX_LINE 30


int main(void);

int main(void){
char buffer[3];
int taro,hanako,number;

int judge[4][4] = {{3,1,2,2,},{2,3,1,2,},{1,2,3,2,},{1,1,1,3,}};

char kekka[3][MAX_LINE] = {"太郎の勝ち",
"花子の勝ち",
"あいこ"
};
/**********************/ printf("1=グー 2=チョキ 3=パー\n");
/**********************/ printf("太郎 : ");
gets(buffer);
taro = atoi(buffer);
taro = taro-1;
/**********************/ printf("花子 : ");
gets(buffer);
hanako = atoi(buffer);
hanako = hanako-1;

number = judge[taro][hanako];

/**********************/ number-=1;

printf("じゃんけんの結果は%sです。\n",kekka[number]
/**********************/ /*[MAX_LINE]*/ /* ←削除 */
);

return(0);
}
    • good
    • 0
この回答へのお礼

ご丁寧にやさしく教えていただいてありがとうございます(^O^)/

Cygwinの日本語表示が文字化けで・・・これを解決するのに
時間がかかりました(汗)

KAZUMI2003さんのおっしゃるようにnumberも1引かないといけないですね。
言われて考えてみたら納得です。

hitomuraさんとkmeeさんのおっしゃって下さっているようにCでの文字列の
扱い方が良くわかっていないみたいです。

2次元配列としてkekkaを定義しているのに、printf内で引数として
1次元配列のように扱っているところは初めて見てよくわかりません↓

お礼日時:2011/08/30 04:17

#define MAX 3


#define MAX_STR 30
int a=123;
printf("%d\n", a ) ;

int b[MAX]={223,323,423};
printf("%d\n", b[0] ) ; /* ok */
printf("%d\n", b[MAX] ) ; /* NG */

↑は理解できますか?

char str[MAX_STR]="テスト" ;
printf("str=%s\n", str ) ; /* str=テスト */
printf("str=%s\n", str[0] ) ; /* warning発生, segmentantion fault発生可能性大 */
printf("str=%S\n", str[MAX_STR] ) ; /* NG , warning発生, segmentantion fault発生可能性大 */
printf("str=%d\n", str ) ; /* warning発生, str=(なんかの数値) */
printf("str=%d\n", str[0] ) ; /* str=(なんかの数値) */
printf("str=%d\n", str[MAX_STR] ) ; /* NG */

↑の違いは理解できますか? printfの%が何するものか理解できてますか?

char kekka[3][MAX_LINE] をC言語の文字列として解釈すると
( char [MAX_LINE] )の文字列が [3]個ある配列「kekka」
となっているのは理解できてますか?

segmentantion fault は不正な領域にアクセスしたことで発生するエラーです。
配列の添字が確保した範囲をはみだすとか、ポインタが有効な値になっていないとか、が主な発生原因です。
当然、デバグ時にまっさきにチェックするのは上の項目になります。 printfの%s→%dなど無意味もいいところです。

この回答への補足

みなさん、お知恵貸していただいてありがとうございました。
おかげさまでプログラムがSegmentation faultを出すことなく
実行できるようになりました。

ベストアンサー選びに悩みましたが、Segmentation fault
以外のプログラムの間違いなどにもご指摘いただき
正常な実行ができましたのは有難かったので
ベストアンサーはKAZUMI2003さんにします。

最後にkmeeさんの返信がないのは残念ですが、プログラムが正常に
実行できましたので質問を閉め切ります。

補足日時:2011/09/04 23:18
    • good
    • 0
この回答へのお礼

ご丁寧にご回答ありがとうございます<m(__)m>

当方の所持しているC言語の入門書を読み返しているのですが文字型の2次元配列に関して詳しい解説がありません。

kmeeさんのはじめのご質問はMAXは3なのでprintfの引数b[MAX]では、定義している配列の数、要素番号0,1,2をこえる要素番号3の配列を引数としているので間違いでよろしいのでしょうか?

2つ目のご質問はコンパイルして実行してみるとSegmentation fault可能性大の両方にSegmentation faultが出ました。
当方の認識ではprintf("str=%s\n", str[0] ) ;ではstr[0]には16バイトの16進数(文字コード)が格納されていて、printfの%sは文字型で、str[0]は整数なのでsegmentantion faultになるのかと?
printf("str=%s\n", str[MAX_STR] );ではprintf内での文字型の配列の引数の書き方の文法違反ということでいいのでしょうか?

正しくはこれらの原因は「配列の添字が確保した範囲をはみだす」と「ポインタが有効な値になっていない」のどちらにあたるのでしょうか?

printf内の%sの引数に文字型の配列str[MAX_STR]とするときにはstrでよく、要素番号は不要なんですね。


printfの%sは文字列、%dは整数を引数とすると理解していますがいかがでしょうか?

char kekka[3][MAX_LINE] をC言語の文字列として解釈すると
( char [MAX_LINE] )の文字列が [3]個ある配列「kekka」
となっているのはわかった気になっています。

Segmentation faultのご説明ありがとうございます。

なにぶん、力量不足なものでお手数おかけしますがご教授お願い致します。

お礼日時:2011/08/30 23:58

この規模ならgetsとatoiを組あわせるのとscanf一つで済ませるのに大差はないような。


#まぁfgets+余剰stdin読み捨て+strtolでもいいけどそういった「完全性」を求められてないことも多々ありますし

あと出てきているエラーは確実に意味をとらえましょう。質問文を読む限りSegmentation faultがどういうエラーなのか全く理解してないようですので、それを抜きに試行錯誤したところで意図通りに修正出来る確率はくじを引くようなものです。
    • good
    • 0
この回答へのお礼

回答ありがとうございます<m(__)m>

Segmentation faultの意味は全然わかりません。

というか、Segmentation faultについて調べる努力が
足りなかったのかと思います。

言い訳になりますが、プログラムのどの部分が原因で
Segmentation faultが出ているのかを調べようとは
努力しました。結果は出ませんでしたが・・・。

お礼日時:2011/08/30 04:38

今回のSegmentation faultとは関係ありませんが


≻char buffer[3];
≻gets(buffer);
は問題ありです。入力時に1文字か2文字と改行のときは大丈夫ですが、3文字以上と改行の入力でSegmentation faultの可能性があります。「fgets(buffer,3,stdin);」に変更しましょう。
    • good
    • 0
この回答へのお礼

回答ありがとうございます<m(__)m>

確かに入力が多くなるとSegmentation faultになるかもしれません。

お礼日時:2011/08/30 04:22

> Segmentation fault (core dumped)


> という言葉が出てファイルを実行できません。

実行はできているでしょ。
2つ数字を入力したら、その後で「Segmentention fault」で止まるだけで。

> printf("じゃんけんの結果は%sです。",kekka[number][MAX_LINE]);

に3点、問題があります。
うち2点は#1で指摘があること。
もう1点はprintfの使い方、あるいは、Cでの文字列についての誤解によるものです。

Cygwinということなので、gccを使っていると思います。
コンパイル時に -Wall オプションを付けること、出た警告はすべて修正すること(あるいは、警告が問題無い理由を説明できること)を推奨します。
    • good
    • 0
この回答へのお礼

回答ありがとうございます<m(__)m>

-Wallオプションを付けて出てきた警告の意味は、
考えてみましたが力量不足でわかりません。

%sを%dに変えてみました。警告こそ出なくなりましたが、
実行することができなくなりました。

お礼日時:2011/08/30 02:12

まず、


> char kekka[3][MAX_LINE] = {"太郎の勝ち",
> "花子の勝ち",
> "あいこ"
> };
でkekkaの各要素がどうなるか考えましょう。
次に、
> int judge[4][4] = {{3,1,2,2,},
>            {2,3,1,2,},
>             {1,2,3,2,},
>             {1,1,1,3,},
>                };
でjudge[0][0]の値がいくつか考えましょう。

そうすれば、どう直せばいいか分かると思います。
    • good
    • 0
この回答へのお礼

迅速な回答ありがとうございます<m(__)m>

kekkaの各要素はシフトJISコードの16進数の2バイトが入っているのかと。

judge[0][0]は3かと思います。

自信なし(涙)。

お礼日時:2011/08/30 01:55

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報