質問 |
||
| QNo.3982231 | テキストの読み込みとmalloc()についてです | |
|---|---|---|
| 質問者:gariben |
こんにちは。 二つのベクトルの次元と要素をテキストファイルから読み取ってそのベクトルの和を出したいのですがうまくいきません。 #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 } 要素数が違います。記憶領域の確保に失敗しました。ベクトル和は{}です。」 と表示されてしまい、困っています。 初歩的なミスかもしれず恐縮ですがよろしければ回答お願いします。 |
|
困り度:
|
||
| 質問投稿日時: 08/04/28 14:30 |
||
回答 |
|
| ANo.3 | > fp = fopen(fname,"r"); > if(fp==NULL){ > printf("そのようなファイルを見つけることができません。"); > } > while (fgets(str, 256, fp) >= 0) { 入力ファイルがオープンできなかったときでも 強引に読みにいこうとしている点も、大きな問題です。 |
|---|---|
| 回答者:asuncion | |
| 種類:アドバイス どんな人:一般人 自信:参考意見 |
|
| 回答日時: 08/04/28 22:17 |
|
| |
| この回答へのお礼 | あ、ほんとだ。 まずいですね。 ありがとうございます。これはいけないです。 |
回答良回答20pt |
|
| ANo.2 | 端的に申し上げますが、初歩的なミスどころの騒ぎではないです。 問題点を修正すると文字数制限に引っかかりそうなので、アドバイスだけします。 ・vector_sum関数の戻り値が配列になっていません。(変数zのアドレスを返すよう修正した場合は変数のスコープに気をつけて下さい) ・fgetsはファイルポインタのファイル位置指示子を操作します。コールする度にファイルの読み取り位置が進んでしまいます。 ・データの管理が煩雑です。構造体を使いましょう。 ・エラー処理をしましょう。 特にファイルの読み込みが致命的です。 「要素数が違います。記憶領域の確保に失敗しました。」というエラーメッセージはファイルが正常に読み込まれていないため起こっていますが、メモリ内容の状況によってはすり抜ける可能性もあります。 まずはファイルの読み込み部分だけを抜き出して、デバッガで追ってください。 while (fgets(str, 256, fp) >= 0) { の部分にブレークポイントを仕掛けて変数strの内容がどう変化するのか観察するのをお勧めします。 |
|---|---|
| 回答者:kusa_cw | |
| 種類:アドバイス どんな人:経験者 自信:参考意見 |
|
| 回答日時: 08/04/28 15:41 |
|
| |
| この回答へのお礼 | 「・vector_sum関数の戻り値が配列になっていません。(変数zのアドレスを返すよう修正した場合は変数のスコープに気をつけて下さい) ・fgetsはファイルポインタのファイル位置指示子を操作します。コールする度にファイルの読み取り位置が進んでしまいます。」 なんとなく理解できるのですがそこからどう行けばいいのかわからない状況です。 「端的に申し上げますが、初歩的なミスどころの騒ぎではないです。」 おっしゃるとおりでございます。ポインタとかファイル入出力の理解があやふやなままとにかく進めとばかり焦ってきたもので、実力のほどが泣くほど薄い状況です。(アドバイスの箇所を中心に)もう一度勉強しなおしてからこのプログラムにあたってみようと思います。 きりが悪いかもしれませんがここで一回締めろうかと思います。地に足つけてからからもう一度このプログラムに取り組んでみます。 何か大切なことを思い出せた気がします(←?) ありがとうございます。 |
回答良回答10pt |
|
| ANo.1 | fgetsで読み取ったデータを捨ててしまっています strにwhileループにはいる時点で1度読んでいる 2回目のfgetsで2行目が読み込まれます 3回目のif文のfgetsはファイルの終端なのでNULLが返却されるでしょう したがって sscanfへは到達しません sscanfの引数に "%lf"を使っていますが受ける変数がchar型では期待通りの結果になら無いでしょう … 受けの変数を &c[i]で与えていますが iは初期化されてい無いので何処を指すのか分かりませんよ sscanfでループさせたいなら 基のstrアドレスを操作しないと期待通りになら無いでしょう |
|---|---|
| 回答者:redfox63 | |
| 種類:アドバイス どんな人:専門家 自信:参考意見 |
|
| 回答日時: 08/04/28 14:55 |
|
| |
| この回答へのお礼 | 「sscanfの引数に "%lf"を使っていますが受ける変数がchar型では期待通りの結果になら無いでしょう … 受けの変数を &c[i]で与えていますが iは初期化されてい無いので何処を指すのか分かりませんよ sscanfでループさせたいなら 基のstrアドレスを操作しないと期待通りになら無いでしょう」 ニュアンスはわかるのですが、どう記述するのかがちょっと…… 文法が弱くて……(爆) わかるようになるまでもっかい勉強しなおします。 |