みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

テキストの読み込みとmalloc()についてです

こんにちは。

二つのベクトルの次元と要素をテキストファイルから読み取ってそのベクトルの和を出したいのですがうまくいきません。


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

double vector_sum(double *x, double *y, int n){
int i;
double z[256]={0};
for(i=0;i<n;i++){
z[i] = x[i] + y[i] ;
}
return *z;
} //ベクトル和を出す関数(のつもり)//


int main(void){
int i,j,e;
double *a,*b,c[256][256]; //a,bはベクトル//
FILE *fp;
char fname[64];
char str[256];
double z[256];

printf("二つのベクトルが書き込まれているファイル名を入力してください.");
scanf("%s",fname);
fp = fopen(fname,"r");
if(fp==NULL){
printf("そのようなファイルを見つけることができません。");
}
while (fgets(str, 256, fp) >= 0) {
i++;

fgets(str, 256, fp);
printf("%s",str); //テキストの読み取り//
if(fgets(str,256,fp)==NULL) break; //読み取り終了時の動作//
sscanf(str,"%lf", &c[i]);//c[i][0]は要素数、c[i][1以上]はベクトルの中身を指すことにする。//
printf("%lf%lf%lf%lf%lf%lf%lf%lf\n",c[0][0],c[0][1],c[1][2]);
if(sscanf(str,"%lf", &c[i])<1){
printf("Format error");
}

}

if(c[0][0]!=c[1][0]){
printf("要素数が違います。");

}

a = malloc(sizeof(double) * c[0][0]);
b = malloc(sizeof(double) * c[1][0]);
if(a==NULL||b==NULL){
printf("記憶領域の確保に失敗しました。");

}
e = c[0][0]; //要素数//
for(i=0;i<=e-1;i++){
a[i]=c[0][i+1]; //ベクトルの中身のみをa,bに代入する。//
b[i]=c[1][i+i];
}
*z= vector_sum(a,b,e);
printf("ベクトル和は{");
for(i=0;i<=e-1;i++){
printf("%lf,",z[i]);
}
printf("}です。");
return 0;
}

テキストファイルは下のものを使いました。(ファイル名はvector.txt)

element: 7 { 4, 4 ,4 ,4 ,4 ,4 ,4 }
element: 7 { 8, 8, 8, 8, 8, 8, 8 }



結果は
「二つのベクトル名が書き込まれているファイルを入力してください。(vector.txtを入力)
element: 7 { 8, 8, 8, 8, 8, 8, 8 } 要素数が違います。記憶領域の確保に失敗しました。ベクトル和は{}です。」
と表示されてしまい、困っています。

初歩的なミスかもしれず恐縮ですがよろしければ回答お願いします。

投稿日時 - 2008-04-28 14:30:15

QNo.3982231

すぐに回答ほしいです

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

端的に申し上げますが、初歩的なミスどころの騒ぎではないです。

問題点を修正すると文字数制限に引っかかりそうなので、アドバイスだけします。
・vector_sum関数の戻り値が配列になっていません。(変数zのアドレスを返すよう修正した場合は変数のスコープに気をつけて下さい)
・fgetsはファイルポインタのファイル位置指示子を操作します。コールする度にファイルの読み取り位置が進んでしまいます。
・データの管理が煩雑です。構造体を使いましょう。
・エラー処理をしましょう。

特にファイルの読み込みが致命的です。
「要素数が違います。記憶領域の確保に失敗しました。」というエラーメッセージはファイルが正常に読み込まれていないため起こっていますが、メモリ内容の状況によってはすり抜ける可能性もあります。

まずはファイルの読み込み部分だけを抜き出して、デバッガで追ってください。
while (fgets(str, 256, fp) >= 0) { の部分にブレークポイントを仕掛けて変数strの内容がどう変化するのか観察するのをお勧めします。

投稿日時 - 2008-04-28 15:41:22

お礼

「・vector_sum関数の戻り値が配列になっていません。(変数zのアドレスを返すよう修正した場合は変数のスコープに気をつけて下さい)
・fgetsはファイルポインタのファイル位置指示子を操作します。コールする度にファイルの読み取り位置が進んでしまいます。」

なんとなく理解できるのですがそこからどう行けばいいのかわからない状況です。


「端的に申し上げますが、初歩的なミスどころの騒ぎではないです。」

おっしゃるとおりでございます。ポインタとかファイル入出力の理解があやふやなままとにかく進めとばかり焦ってきたもので、実力のほどが泣くほど薄い状況です。(アドバイスの箇所を中心に)もう一度勉強しなおしてからこのプログラムにあたってみようと思います。
 きりが悪いかもしれませんがここで一回締めろうかと思います。地に足つけてからからもう一度このプログラムに取り組んでみます。

 何か大切なことを思い出せた気がします(←?)
 ありがとうございます。

投稿日時 - 2008-04-29 18:03:23

ANo.2

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

> fp = fopen(fname,"r");
> if(fp==NULL){
> printf("そのようなファイルを見つけることができません。");
> }
> while (fgets(str, 256, fp) >= 0) {

入力ファイルがオープンできなかったときでも
強引に読みにいこうとしている点も、大きな問題です。

投稿日時 - 2008-04-28 22:17:30

お礼

あ、ほんとだ。
まずいですね。
ありがとうございます。これはいけないです。

投稿日時 - 2008-04-29 18:05:01

ANo.1

fgetsで読み取ったデータを捨ててしまっています
strにwhileループにはいる時点で1度読んでいる
2回目のfgetsで2行目が読み込まれます

3回目のif文のfgetsはファイルの終端なのでNULLが返却されるでしょう
したがって sscanfへは到達しません

sscanfの引数に "%lf"を使っていますが受ける変数がchar型では期待通りの結果になら無いでしょう …

受けの変数を &c[i]で与えていますが iは初期化されてい無いので何処を指すのか分かりませんよ

sscanfでループさせたいなら 基のstrアドレスを操作しないと期待通りになら無いでしょう

投稿日時 - 2008-04-28 14:55:54

お礼

「sscanfの引数に "%lf"を使っていますが受ける変数がchar型では期待通りの結果になら無いでしょう …

受けの変数を &c[i]で与えていますが iは初期化されてい無いので何処を指すのか分かりませんよ

sscanfでループさせたいなら 基のstrアドレスを操作しないと期待通りになら無いでしょう」

ニュアンスはわかるのですが、どう記述するのかがちょっと……
文法が弱くて……(爆)

わかるようになるまでもっかい勉強しなおします。

投稿日時 - 2008-04-29 18:10:48

あなたにオススメの質問