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

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

構造体のプログラミング...練習です。

構造体のプログラミング...練習です。 #include <stdio.h> int main ( void ) { int i; struct rool{ char name[20]; float height; char bloodType; }date[128]; for(i = 0;; i++) { printf("%d人目のデータ:", i + 1 ); scanf("%s %f %c",date[i].name[i], &date[i].height, &date[i].bloodType); if((date[i].name[0] == '0') && (date[i].height == 0) && (date[i].bloodT\ ype == 0)) { break; } } printf("名前    体重     歳\n"); for(i = 0; (date[i].name[0] == '0') && (date[i].height == 0) && (date[i].bl\ oodType == 0); i++) { printf("%s, %10s, %10s\n",date[i].name[i], date[i].height, date[i].bloodTy\ pe); } return 0; } 構造体を使ったプログラミングです。 名前と体重、歳を入力して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% (2126/6288)
回答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; }

関連するQ&A

  • C言語での構造体

    C言語の構造体で配列を扱うとき、 struct ○○{  char ○○[○] とすれば出来ますが、同じようにして構造体で二次元配列を扱うことは出来ますか? 一度組んでみたのですが、 #include<stdio.h> struct aaa{ int no; char name[128]; char y_name[128]; char n_name[128]; char s_name[128][128]; }; int main(void){ int i; struct aaa iryo[99]; printf("入力前\n"); /* 構造体配列に scanf()でデータを入力 */ for(i = 0; i < 3; i++) { // printf("input...\n"); scanf("%d", &iryo[i].no); scanf("%s", iryo[i].name); scanf("%s", iryo[i].y_name); scanf("%s", iryo[i].n_name); scanf("%s", iryo[i].s_name); } printf("入力後\n"); printf("出力前\n"); /* 入力データの確認 */ for(i = 0; i < 3; i++) { printf("番号:%02d 内容:%s Y分岐:%s N分岐:%s 他分岐:%s\n", iryo[i].no, iryo[i].name, iryo[i].y_name, iryo[i].n_name, iryo[i].s_name); } printf("出力後\n"); printf("%d",sizeof(struct aaa)); return 0; } としたら、エラーは出ませんが、実行すると何も表示されませんでした。

  • このプログラムの処理の流れを教えて下さい

    初心者です。構造体のプログラムの勉強をしているのですが、このプログラムの処理の流れを考えたのですがよくわかりませんでした。理解を深めるために必要なので、どうかよろしくお願いします。 #include<stdio.h> #include<string.h> int main(void) { struct roll { char name[32]; float height; char bloodType[3]; }; struct roll data[128]; int i; for(i = 0;i < 128;i++){ printf("%d人目のデータ: ", i + 1); scanf("%s %f %s", &data[i].name, &data[i].height, &data[i].bloodType); if( data[i].name[0] == '0', data[i].height == 0, data[i].bloodType[0] == '0' ){ break; } } printf("名前\t身長\t血液型\n"); for(i = 0;i < 128;i++){ if( data[i].name[0] == '0', data[i].height == 0, data[i].bloodType[0] == '0' ){ break; } printf("%s\t%3.1f\t%s\n", data[i].name, data[i].height, data[i].bloodType); } } <実行例> 1人目のデータ: 太郎 175.5 A ←キーボードからそれぞれ入力する 2人目のデータ: 花子 169.0 B ←キーボードからそれぞれ入力する 3人目のデータ: 一郎 180.4 O ←キーボードからそれぞれ入力する 4人目のデータ: 0 0 0 ← 0 0 0 とキーボードから入力すると終わる 名前 身長 血液型 太郎 175.5 A 花子 169.0 B 一郎 180.4 O

  • 構造体についてです。

    身体測定表を作っていて最初に作ったデータを変更して表示したいのですがNo1の168cm→162cm No2の74kg→74.5kg  No3の20歳→19歳 No4の田中三郎→小林三郎 (No3と4は構造体ポインタを使ってデータを変更) 全データを表示させてその後No1と3の名前~体重を丸ごと入れ替えて全データを表示させたいのですがエラーがでてしまいます。 分かる人がいましたらどこを直したらいいか教えて下さい。 #include <stdio.h> #include <string.h> struct data{ int no; char name[21]; int age; int height; float weight; }; struct data *sp; void main(){ int i; struct data a[4]={ {1,"鈴木太郎",23,168,60}, {2,"山本次郎",17,180,74}, {3,"山田花子",20,156,53}, {4,"田中三郎",35,172,68}, }; struct data b; for(i=0;i<4;i++){ printf("番号 :%d\n",a[i].no); printf("名前 :%s\n",a[i].name); printf("年齢 :%d歳\n",a[i].age); printf("身長 :%dcm\n",a[i].height); printf("体重 :%4.1fkg\n\n",a[i]. weight); } a[0].height=162; a[1].weight=74.5; *sp[2].age=19; strcpy(*sp[3].name,"小林三郎"); for(i=0;i<=4;i++){ b=a[0]; a[0]=a[2]; a[2]=b; a[0].no=1; a[2].no=3; } for(i=0;i<=4;i++){ printf("番号 :%d\n",a[i].no); printf("名前 :%s\n",a[i].name); printf("年齢 :%d歳\n",a[i].age); printf("身長 :%dcm\n",a[i].height); printf("体重 :%4.1fkg\n\n",a[i].weight); } }

  • 構造体配列

    いつもお世話になっています。 今日構造体配列を勉強した際に下の演習をしていたのですが、いまいち基礎的な関数や配列のことやコマンドライン引数のことが理解できていません。一応自分なりにプログラムを書いてみたのですが、エラーがでます。 どなたかアドバイス・ご指摘・解説・例などをおねがいいたします。 問題はコマンドライン引数で人数を指定し,人数分のデータを標準入力(キーボード)から構造体配列に入力し,標準出力(ディスプレイ)に出力するプログラムです。 #include<stdio.h> typedef struct{ char name[100]; int age; double height; double weight; } PERSONAL_DATA1; typedef struct{ int person[10]; }PERSONAL_DATA2; PERSONAL_DATA1 input_personal_data(int num); void output_personal_data(PERSONAL_DATA2 person[10],int num); int main(int argc, char *argv[]){ PERSONAL_DATA1 x; int num,i; char person[10]; if(argc != 2){ printf("Usage ./test number"); return 0; } num=atoi(argv[1]); for(i=0;i<10&&i<num;i++){ person[i]=input_personal_data(); output_personal_data(person,num); return 0; } } PERSONAL_DATA input_personal_data(void){ PERSONAL_DATA1 x; printf("name>"); scanf("%c" ,&x.name); printf("age>"); scanf("%d" ,&x.age); printf("height>"); scanf("%lf" ,&x.height); printf("weight>"); scanf("%lf" ,&x.weight); return x; } void output_personal_data(PERSONAL_DATA2 person[10],int num){ PERSONAL_DATA1 x; printf("name>>%s\n" ,x.name); printf("age>>%d\n" ,x.age); printf("height>>%lf[cm]\n" ,x.height); printf("weight>>%lf[kg]\n" ,x.weight); } またコマンドライン引数で指定したデータファイルAから入力した個人データ集合を構造体配列に取り込み,標準出力(ディスプレイ)と同じくコマンドライン引数で指定したデータファイルBへファイル出力に出力するプログラムというおまけの問題もあります。 こちらの問題のヒントもいただけませんか?

  • 構造体の構造体 引数

    構造体の中の構造体の関数の引き渡し方法がわかりません。 下記ソースで試したのですが、うまくいきませんでした。 助言お願いいたします。 //repo.c #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #define NUM 20 #define MAX 15 struct seiseki{ float shu[3]; }; struct seito{ char name[NUM]; int age; struct seiseki kekka; }; void input(struct seito *p); void s_input(struct seiseki *p); void ss_input(struct seiseki *data); int main(){ int i; struct seito data[2]; for(i=0;i<2;i++){ printf("------------------------------\n"); printf("%d人目",i+1); input(&data[i]); } printf("%f\n",data[0].kekka.shu[0]); printf("%f\n",data[0].kekka.shu[1]); printf("%f\n",data[0].kekka.shu[2]); //data[1]に格納できない。 printf("%f\n",data[1].kekka.shu[0]); printf("%f\n",data[1].kekka.shu[1]); printf("%f\n",data[1].kekka.shu[2]); return 0; } void input(struct seito *p){ printf("名前->"); scanf("%s",p->name); printf("年齢->"); scanf("%d",p->age); s_input(&(p->kekka)); } void s_input(struct seiseki *data){ printf("国語->"); ss_input(data); printf("算数->"); ss_input(data); printf("英語->"); ss_input(data); } //下記関数で成績をchar型で受け取り、数値化したい。 void ss_input(struct seiseki *data){ char p[100]; int i=0; static int o=0; scanf("%s",p); while( p[i] != '\0'){ if(isdigit(p[i])==0){ printf("再入力してください"); scanf("%s",p); } i++; } data->shu[o]=atof(p); printf("%f\n",data->shu[o]); o++; }

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

    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 どう定義すればいいのか教えてください。お願いします。

  • プログラミング教えてください!!!お願いします。

    プログラミング教えてください!!!お願いします。 次の文が実行されると何がどのようにプリントされるか。何もプリントされない時は「なし」と記せ。 また、途中に「ブランク」が入る場合は、”b”と記せ。 (1) int func1(), func2(); int data = 100; main() { int w = 1; static x =10; printf("** %d, %d, %d\n" ,w,x,data); func1(); printf("** %d, %d, %d\n" ,w,x,data); } int func1(){ int w = 2; static int x = 20: printf("*** %d, %d, %d\n", w, x, data); x += 10; func2(); printf("*** %d, %d, %d\n" , w,x,data); x *= 2; data = data - x; } int func2() { int w = 3; static int x = 30; printf("**** %d, %d, %d\n" ,w,x,data); data -= x; } (2) int func1(char *, char *, char *); int func2(char *, char *, char *); main() { char sta[20], stb[20], stc[20], std[20]; int i=0; func1("abc","xyz",sta); printf("%d -- %s\n" ,++i,sta); func1("123","456",stb); printf("%d -- %s\n" ,++i,stb); func1(sta,stb,stc); printf("%d -- %s\n" ,++i,stc); func2(sta,stb,std); printf("%d -- %s\n" ,++i,std); } int func1(char *a, char *b, char *c){ while(*a) *c++ = *a++; while(*b) *c++ = *b++; * c = 0x00; } int func2(char *a, char *b, char *c){ int i = 0; while(*b){ if(i%2 == 0) *c++ = *a++; else *c++ = *b++; i++; } *c = 0x00; }

  • C言語 プログラミング

    C言語、プログラミングの質問です。 構造体について、 プログラムを組んでみたのですが、上手く出力されません。実行時にはエラーはないのですが、出力時に上手くいきません。どなたかどこがおかしいかわかる方、教えていただけませんでしょうか? #include <stdio.h> struct user{ char *name; char *id; int books; }; int main (void) { struct user u; printf("氏名を入力して下さい。"); scanf("%s",u.name); printf("パスワードを入力してください。"); scanf("%s",u.id); printf("年齢を入力してください。"); scanf("%d",&u.age); printf("氏名 %s\n",u.name); printf("パスワード %s\n",u.id); printf("年齢 %d\n",u.age); return 0; } よろしくお願いします。

  • 構造体

    下記プログラムの2次元配列を構造体の配列に作り変え,構造体を利用して生年月日の項目を追加し,形式は日を除いたYYYY/MMで持ち,生年月日の入出力は,YYYY/MM形式で行い,西暦が数字4桁で,西暦と月の間に'/'があり,月が01~12の範囲の数字の2桁になっている7文字の入力のみ受け付け,正しく入力されるまでそれ以外は再入力させたい。あとdo-while文をつかっている箇所をwhile文に直したいです.自力でやったのですが,わかりませんでした. どのようにしたらよいか教えてください. お願いします. include <stdio.h> #define BUFFERSIZE 11 #define MAX_PERSON 10 #define MAX_CHARS 10 int main(void) { char name[10][BUFFERSIZE]; int c; int count = 0; int i; int j; for (i = 0; i < MAX_PERSON; i++) { printf("氏名入力 : "); j = 0; /* 氏名の1文字目が'0'なら入力を終了 */ if ((c= getchar()) == '0'){ break; } if (c == '\n') { /* 改行のみの入力は再入力 */ do { printf( "再入力\n" ); /*再入力*/ printf("氏名入力 : "); } while ((c = getchar()) == '\n'); } name[i][j++] = c; /*1文字目を格納*/ if (name[i][0] == '0') { break; } while ((c = getchar()) != '\n' && c != EOF) { if (j < BUFFERSIZE - 1) { name[i][j++] = c; } } name[i][j] = '\0'; count++; /* 実際に入力した人数を記録*/ printf("累計 : %d \n", count); } /* 氏名と生年月日を出力したいです */ for (i = 0; i < count; i++) { for (j = 0; j < MAX_CHARS; j++) { if (name[i][j] == '\0'){ break; } putchar(name[i][j]); } putchar('\n'); } return 0; }

  • リスト構造がうまく動きません!!

    C言語で以下のようなプログラムを作りました。 「main関数内で下記のデ-タを構造体に格納し、キーボードから入力された名前と該当する学生の身長と年齢を画面に表示するプログラムを作成せよ。」というものです。 このプログラムはコンパイルは通るのですが、2人目以降のデータを表示させようとしても表示してくれません。。。どうもリスト構造のfor文がうまくループしていないみたいなんですが原因が分かりません。どなたか原因の分かる方アドバイスをお願いしますm(_ _)m #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct data{ char name[20]; int height; int age; struct data *next; }person; person *newperson(void); int main(void){ char namae[20],s[20]; int toshi,shinchou,i; person *head; person *list; person *nlist; person *LIST; head = newperson(); nlist = head; printf("データを入れてください。\n"); for(i=0;i<=4;i++){ scanf("%s",namae); scanf("%d",&shinchou); scanf("%d",&toshi); list = newperson(); strcpy(list ->name,namae); list -> height = shinchou; list -> age = toshi; nlist -> next = list; nlist = list; } printf("知りたい人の名前は?\n"); scanf("%s",s); for(LIST = head->next;LIST ->next != NULL;LIST = LIST->next){ if(strcoll(s,LIST ->name)==0){ printf("%s\t%d\t%d\n",LIST->name,LIST->height,LIST->age); break; } printf("%s\n",LIST->name); printf("%s\n",LIST->next->name); } return(0); } person *newperson(){ person *dummy; dummy = (person*)malloc(sizeof(person)); dummy -> next = NULL; return(dummy); }

専門家に質問してみよう