• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:構造体のプログラミング...練習です。)

構造体のプログラミングでセグメントエラーが発生して困っています

このQ&Aのポイント
  • 構造体を使ったプログラミングで、名前と体重、歳を入力して0 0 0が入力されたら、これまで入力した内容を表示する方法について教えてください。
  • セグメントエラーが発生して困っています。入力をすると、何人目のデータを入力するかのメッセージが表示され、セグメントエラーでプログラムが停止してしまいます。
  • 解決策を教えてください。エラーが発生しないようにしたいです。

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

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

http://ja.wikipedia.org/wiki/Scanf scanfは、いろいろと面倒なことの多い関数です。 おそらく scanf失敗:ファイルポインタはそのまま →終了チェックにはひっからない 初期化していない構造体の中身は不定で、なにが入っているかわからない。 全部0で初期化されていたとしても、0と'0'とは違う。 → i++してループ続行 →さっきエラーになったところか読み出し →ずれていたり、最初から変化してなかったりで正確に読めない →終了チェックにはひっからない → i++してループ続行 .... → i >= 128 になる → 宣言より data[128]以上は保証されない →セグメントエラー という流れだと思われます。 ・fgets等で1行読み込む→sscanfや別の方法で解析する ・scanfのエラーチェックと、エラーの際の復帰処理をきちんと行う といった対策が必要です。 あと気付いたことは > 名前と体重、歳を入力 とあるのに、構造体のメンバは > float height; > char bloodType; と、身長と血液型を連想させるものになっている。 文法的にはあっているけど、作法としては問題。 また、歳を扱うのなら、charの範囲(普通は-128~127)を越えることはほぼ無いけれど、intを使うのが自然。 > scanf("%s %f %c",date[i].name[i], &date[i].height, &date[i].bloodType); %sと%fの間に「全角スペース」が入っていますが、これは、ここへの打ち込み間違いでしょうか? もし、プログラムをコピペしたものだとしたら、入力時には、名前と体重との間に「全角スペース」が無いとこのscanfは成功しません。 名前を読み込んだところで、読み込みポインタは体重の前で止ってしまい、次回のscanfはそこからに →名前は空文字列、体重の前に「全角スペース」がないのでエラー、読み込みポインタは体重の前 →名前は空文字列、体重の前に「全角スペース」がないのでエラー、読み込みポインタは体重の前 .... と無限ループになります。 また、%cは文字を読み込むものです。 歳に25を入れたとして、%cで読み込まれるのは '2' だけであって、 通常は '2' != 2 です。 '5'はバッファにそのまま残り、次の入力はここからになります。 整数を読み込むなら 変換文字は d です。 > if((date[i].name[0] == '0') これだと、 0taro氏も条件に合致します。 > (date[i].bloodType == 0)) 現在のままだと、 歳に0を入れた場合は、 bloodType = '0' であって 0ではありません。 > printf("%s, %10s, %10s\n",date[i].name[i], date[i].height, date[i].bloodType) 2番目は %sに対して height、つまりfloatを指定しています。 floatをムリヤリchar *だと思いこんで、まったく意味のないアドレスから文字列として出力しようとします。 3番目は %sに対して bloodType、つまりcharを指定しています。 charをムリヤリchar *だと思いこんで、まったく意味のないアドレスから文字列として出力しようとします。 charは1文字を表現できる数値であって、文字列ではありません。

tonyemly
質問者

お礼

大変細かい説明を、ありがとうございました。 一応やみなおしてみたら、思う通りに動くことができました。 とっても助かりました!

その他の回答 (3)

回答No.4

エラーになるのは scanf("%s %f %c",date[i].name[i], &date[i].height, &date[i].bloodType); の引数date[i].name[i]が date[i].name または &date[i].name[0] になっていないからです。 あとの変なところは他の回答者の指摘どうりです。

  • asuncion
  • ベストアンサー率33% (2127/6290)
回答No.2

>scanf("%s %f %c",date[i].name[i], i は「何人目のデータか」を表わす変数ですよね。 name[i] の i は、どういう意味ですか? >for(i = 0; (date[i].name[0] == '0') && (date[i].height == 0) && (date[i].bl\ oodType == 0); i++) 入力がうまくいったとしても、これだと何も出力しないのではありませんか? for文の継続条件を見直す必要があると思います。

  • tyatsumi
  • ベストアンサー率58% (30/51)
回答No.1

データを手入力するときにscanf()をループで複数回呼ぶとうまくいかないようですね。 fgets()で1行ごと入力してからsscanf()を使うのがいいと思います。 (それと、載せられたプログラムは表示部のforループの継続条件の論理が逆ですよ。) 簡略化したサンプルプログラムを作ってみました。 これは整数を1行に1個ずつ入力して配列に格納し、0が入力されたら入力を終わって、 配列の中身を表示する、というものです。参考にしてください。 #define LINE_SIZE 1024 #include <stdio.h> int main(void) { char line[LINE_SIZE + 1]; int numbers[256]; int count; int i; count = 0; for (;;) { int r; int n; if (fgets(line, LINE_SIZE, stdin) == NULL) { break; } line[LINE_SIZE] = '\0'; r = sscanf(line, "%d", &n); if (r != 1) { break; } if (n == 0) { break; } numbers[count] = n; count++; } for (i=0; i<count; i++) { printf("%d: %d\n", i, numbers[i]); } return 0; }