質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

6398閲覧

c言語 構造体配列にファイルから値を読み込みたい

tamintya

総合スコア34

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2021/07/04 02:41

編集2021/07/04 09:31

前提・実現したいこと

ファイルから読み込んだ文字を構造体配列に格納した後、それを2分探索で調べ構造体配列に格納されているなら構造体の中身を表示するプログラムを作りたいのですが思うような結果になりません。
原因はファイルからの読み込みにあるようなのですが直し方がわからないので教えて欲しいです。

発生している問題・エラーメッセージ

ファイルから読み込むとすべての構造体配列の値が同じになる 例:2回目の読み込みを行うと p[0].english = bear , p[1].english = bear となってしまう。 実行結果は 英単語を入力して下さい --->wolf min = 0 , max = 49 , middle = 24 wolfの意味 : 狼 続けますか? (yes/no) --->yes 英単語を入力して下さい --->dog min = 0 , max = 49 , middle = 24 min = 0 , max = 23 , middle = 11 min = 0 , max = 10 , middle = 5 min = 0 , max = 4 , middle = 2 min = 0 , max = 1 , middle = 0 dogの意味 : 辞書に登録されていません 続けますか? (yes/no) --->no プログラムを終了します.

該当のソースコード

c

1#include<stdio.h> 2#include<string.h> 3#include<stdlib.h> 4 5typedef struct DIC_CELL{ 6 char *english; 7 char *mean; 8}DIC_CELL; 9 10char *search(DIC_CELL *p , int min, int max, char *name){ 11 int middle; 12 char *not = "NOT"; 13 while(min <= max){ 14 middle = (min + max) / 2; 15 //確認 16 printf("min = %d , max = %d , middle = %d\n" , min,max,middle); 17 18 if(strcmp(p[middle].english,name) == 0){ 19 return p[middle].mean; 20 } 21 else if(strcmp(p[middle].english,name) < 0){ 22 min = middle + 1; 23 } 24 else{ 25 max = middle -1; 26 } 27 } 28 29 30 return not; 31 32} 33 34int main(int argc , char *argv[]){ 35 char name[100]; 36 char *mean; 37 char dat[100],zat[100]; 38 DIC_CELL p[50]; 39 int i; 40 FILE *fp; 41 char end[3]; 42 43 // プログラム利用方法表示 44 if ( argc != 2 ) { 45 fprintf( stderr, "Usage: %s filename\n", argv[0] ); 46 exit( 1 ); 47 } 48 49 //ファイルオープン 50 if (( fp = fopen( argv[1], "r" ) ) == NULL ) { 51 fprintf( stderr, "File open error %s\n", argv[1] ); 52 exit( 1 ); 53 } 54 55 // データ読み込み&作成 56 while( fscanf( fp, "%s %s", dat,zat ) != EOF ) { 57 p[i].english = dat; 58 p[i].mean = zat; 59 i++; 60 } 61 62 while(1){ 63 printf("英単語を入力して下さい --->"); 64 scanf("%s" , name); 65 66 //検索 67 mean = search(p , 0 , 49 , name); 68 69 //表示 70 if(strcmp(mean,"NOT") == 0){ 71 printf("%sの意味 : 辞書に登録されていません\n" , name); 72 } 73 else{ 74 printf("%sの意味 : %s\n" , name,mean); 75 } 76 77 //継続の確認 78 printf("続けますか? (yes/no) --->"); 79 scanf("%s" , end); 80 if(strcmp(end,"no") == 0) break; 81 } 82 printf("プログラムを終了します.\n"); 83 84 fclose(fp); 85 return 0; 86} 87

###読み込みファイル

alligator 鰐 bear 熊 camel ラクダ cat 猫 caterpilar 毛虫 catfish なまず cattle 牛 crow 烏 deer 鹿 dog 犬 dolphin イルカ duck アヒル eagle 鷲 elephant 象 fowl 鶏 frog 蛙 giraffe 麒麟 gorilla ゴリラ hawk 鷹 horse 馬 jaguar 豹 kangaroo カンガルー koala コアラ lion ライオン monkey 猿 ostrich 駝鳥 panda パンダ peacock 孔雀 penguin ペンギン pig 豚 rat 鼠 seal アザラシ sheep 羊 snake 蛇 sparrow 雀 tiger 虎 whale 鯨 wolf 狼

試したこと

gdbコマンドによる値の確認

###追記

#include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct DIC_CELL{ char *english; char *mean; }DIC_CELL; char *search(DIC_CELL *p , int min, int max, char *name){ int middle; char *not = "NOT"; while(min <= max){ middle = (min + max) / 2; //確認 printf("min = %d , max = %d , middle = %d\n" , min,max,middle); if(strcmp(p[middle].english,name) == 0){ return p[middle].mean; } else if(strcmp(p[middle].english,name) < 0){ min = middle + 1; } else{ max = middle -1; } } return not; } int main(int argc , char *argv[]){ char name[100]; char *mean; char dat[100],zat[100]; DIC_CELL p[50]; int i=0; FILE *fp; char end[3]; // プログラム利用方法表示 if ( argc != 2 ) { fprintf( stderr, "Usage: %s filename\n", argv[0] ); exit( 1 ); } //ファイルオープン if (( fp = fopen( argv[1], "r" ) ) == NULL ) { fprintf( stderr, "File open error %s\n", argv[1] ); exit( 1 ); } // データ読み込み&作成 while( fscanf( fp, "%s %s", dat,zat) != EOF ) { strcpy(p[i].english, dat); strcpy(p[i].mean, zat); i++; } while(1){ printf("英単語を入力して下さい --->"); scanf("%s" , name); //検索 mean = search(p , 0 , 49 , name); //表示 if(strcmp(mean,"NOT") == 0){ printf("%sの意味 : 辞書に登録されていません\n" , name); } else{ printf("%sの意味 : %s\n" , name,mean); } //継続の確認 printf("続けますか? (yes/no) --->"); scanf("%s" , end); if(strcmp(end,"no") == 0) break; } printf("プログラムを終了します.\n"); fclose(fp); return 0; }

###追記2

#include<stdio.h> #include<string.h> #include<stdlib.h> typedef struct DIC_CELL{ char *english; char *mean; }DIC_CELL; char *search(DIC_CELL *p , int min, int max, char *name){ int middle; char *not = "NOT"; while(min <= max){ middle = (min + max) / 2; //確認 printf("min = %d , max = %d , middle = %d\n" , min,max,middle); if(strcmp(p[middle].english,name) == 0){ return p[middle].mean; } else if(strcmp(p[middle].english,name) < 0){ min = middle + 1; } else{ max = middle -1; } } return not; } int main(int argc , char *argv[]){ char name[100]; char *mean; char dat[100],zat[100]; DIC_CELL p[50]; int i=0; FILE *fp; char end[3]; // プログラム利用方法表示 if ( argc != 2 ) { fprintf( stderr, "Usage: %s filename\n", argv[0] ); exit( 1 ); } //ファイルオープン if (( fp = fopen( argv[1], "r" ) ) == NULL ) { fprintf( stderr, "File open error %s\n", argv[1] ); exit( 1 ); } for(i=0;i<50;i++){ p[i].english = (char*)malloc(sizeof(char)); p[i].mean = (char*)malloc(sizeof(char)); } // データ読み込み&作成 while( fscanf( fp, "%s %s", dat,zat) != EOF ) { strcpy(p[i].english, dat); strcpy(p[i].mean, zat); i++; } while(1){ printf("英単語を入力して下さい --->"); scanf("%s" , name); //検索 mean = search(p , 0 , 49 , name); //表示 if(strcmp(mean,"NOT") == 0){ printf("%sの意味 : 辞書に登録されていません\n" , name); } else{ printf("%sの意味 : %s\n" , name,mean); } //継続の確認 printf("続けますか? (yes/no) --->"); scanf("%s" , end); if(strcmp(end,"no") == 0) break; } printf("プログラムを終了します.\n"); fclose(fp); return 0; }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

質問の追記のコードなら次のようにすれば strcpy で読み込めます。

C

1typedef struct DIC_CELL { 2 char english[100]; 3 char mean[100]; 4} DIC_CELL;

質問の最初のコードなら、strdup で領域確保とコピーを同時に行えます。

C

1 p[i].english = strdup(dat); 2 p[i].mean = strdup(zat);

strdup は多くの処理系に用意されていますが、標準関数ではありません。
その時は、自分で定義すればいいでしょう。

C

1char *strdup(const char *s) 2{ 3 char *p = malloc(strlen(s)+1); 4 if (p) strcpy(p, s): 5 return p; 6}

投稿2021/07/04 08:19

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tamintya

2021/07/04 09:30

回答ありがとうございます。 ほしい結果を得ることができました。
kazuma-s

2021/07/04 13:25

ほしい結果を得ることができたのは偶然です。 読み込みファイルの行数は何行ですか? データが 50個ないのに、mean = search(p , 0 , 49 , name); はダメでしょう。
tamintya

2021/07/04 13:53

確かにその通りですね。 mean = search(p , 0 , i , name)と直したのですがこれで問題ないでしょうか? またほかに危ない個所はありますか。
kazuma-s

2021/07/04 14:44

問題あるかないか、なぜ分からないのでしょうか? i の値はいくつですか? 「試したこと gdbコマンドによる値の確認」と書いていますが本当に確認していますか? mean = search(p , 0 , i-1 , name); ではないのですか?
tamintya

2021/07/05 05:51

i がデータの数になっていたので問題ないと思ってしまいました。 注意していただきありがとうございます。
guest

0

ベストアンサー

C

1 // データ読み込み&作成 2 while (fscanf(fp, "%s %s", dat, zat) != EOF) { 3 p[i].english = dat; 4 p[i].mean = zat; 5 i++; 6 }

ここがダメ。同じアドレス値(dat, zat) をセットすれば同じ文字列になるのはアタリマエ。

C

1int x = 1; 2int* p0 = &x; 3x = 2; 4int* p1 = &x; 5// *p0、*p1 ともに 2 となる。 6// あなたはコレと同じことしてる。

投稿2021/07/04 02:50

編集2021/07/04 03:01
episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tamintya

2021/07/04 03:10

回答ありがとうございます。 知識不足で理解できなかったのでもう少し詳しい説明をお願いしたいです。
tamintya

2021/07/04 03:17

理解することができました。
tamintya

2021/07/04 03:31

間違いを理解することは出来たのですが、 解決方法が分からないので少し教えてもらいたいです。
episteme

2021/07/04 04:49

datそのものをp[i]にセットするのがマチガイなんだから、"複製"を セットすればいいんだがな。
tamintya

2021/07/04 06:42

複製をセットするとは strcpy を用いて値を代入するということであっていますか? またそれを行うとセグメンテーション違反が発生してしまうのですがそれはなぜなのでしょうか?
episteme

2021/07/04 07:09

コピー先:p[i] がドコを指してるんです?
tamintya

2021/07/04 08:07

mallcを用いて動的確保を行ったのですがまだセグメンテーション違反が発生してしまいます。 やり方が違うのでしょうか?
episteme

2021/07/04 08:13

コード見せてもらわんことにはなんとも...
tamintya

2021/07/04 09:24

コードは質問文に追記しました。
pepperleaf

2021/07/04 09:37

malloc()で 一バイト分しか確保してないですが、OK ?
tamintya

2021/07/04 09:47

確かにそうですね。 見落としていました。 しかしその部分を p[i].english = (char*)malloc(sizeof(char)*100) に変更しても セグメンテーション違反が直らないのですがそれはどうしてなのでしょうか?
pepperleaf

2021/07/04 10:21

ここの iの値は ? 多分、その前の for()の終わったあたいなので、 51から? デバッグできてます?
episteme

2021/07/04 10:34

いや、デバッグしてないよね...
tamintya

2021/07/04 13:42

ほしい結果を得ることができました。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問