定積分の計算 パート2

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら

定積分の計算 パート2

#1

投稿記事 by » 17年前

こんにちは、幻です。
前回もありがとうございました。
その前回に続き、再び実行結果が上手くいかない状況になりました。

今回は前回の『定積分の計算』スレで出来たプログラムにおいて、
read_file関数内で、配列用の記憶領域を動的に割り当てるというものです。

作ってみたソースです。
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

//ファイル名を入力させる関数

void file_input(char *fn)
{
	printf("ファイル名を入力--> ");
	gets(fn);
}

//ファイルから入力データを読み込む関数

void read_file(FILE *fp, char *fn, double *x, double *y, int *n)
{
	int i;
	
	if ((fp = fopen(fn, "r")) == NULL) {
		printf("ファイルをオープンできません.\n");
		exit(1);
	} 
	fscanf(fp, "%d", n);
	
	x = (double *)malloc(sizeof(double) * (*n));
	y = (double *)malloc(sizeof(double) * (*n));
	
	if (x == NULL || y == NULL) {
		perror("メモリの確保に失敗しました.\n");
		exit(1);
	}
	
	for (i = 0; i < *n; i++)
		fscanf(fp, "%lf%lf", &x, &y);
	
	free(x);
	free(y);
	fclose(fp);
}

//定積分をする関数

double integrate(double *x, double *y, int n)
{
	int i;
	double ss = 0.0;
	
	for (i = 0; i < n -1; i++)
		ss = ss + (y + y[i+1]) * (x[i+1] - x) / 2.0;
	
	return ss;
}

//結果を出力する関数

void output(double S)
{
	printf("面積 ≒ %f\n", S);
}

//以下、main関数

int main(void)
{
	FILE *fp;
	char fn[32];
	int n;
	double *x, *y, S;
	
	file_input(fn);
	read_file(fp, fn, x, y, &n);
	S = integrate(x, y, n);
	output(S);
	
	return 0;
}


結果は

面積 ≒ -NAN

という具合に表示されます。
何回も見直しているのですが原因が分かりません。
もしかして、xとy2つ同時に記憶領域の動的確保は無理なのでしょうか?

ご教授お願いします。

※読み込むファイルを再度添付しておきますね。

フリオ

Re:定積分の計算 パート2

#2

投稿記事 by フリオ » 17年前

 
  "main"関数内で"double へのポインタ型"として宣言された変数 x、y を、
呼び出した"read_file"関数内で値を変更し、それを"main"関数に反映させるには、
変数 x、y へのポインタ、つまり、"double へのポインタ型"へのポインタ を
"read_file"関数に渡してやる必要があります。
 

Re:定積分の計算 パート2

#3

投稿記事 by » 17年前

>フリオさん
返信ありがとうございます。

ポインタのポインタを使うということですよね。
ちょっと考えてみますね。

あと前々から感じていたのですがポインタのポインタの使いどころやメリット
がイマイチ理解できません。
よく名前は聞いてはいたのですが、使うのは今回が初めてになるので…
出来れば、分かりやすい例で説明して頂けるとうれしいです。

Re:定積分の計算 パート2

#4

投稿記事 by » 17年前

どうも、幻です。
取り合えずポインタのポインタを使って(つもり?)、ソースを書き直してみました。
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>

//ファイル名を入力させる関数

void file_input(char *fn)
{
	printf("ファイル名を入力--> ");
	gets(fn);
}

//ファイルから入力データを読み込む関数

void read_file(FILE *fp, char *fn, double **x, double **y, int *n)
{
	int i;
	
	if ((fp = fopen(fn, "r")) == NULL) {
		printf("ファイルをオープンできません.\n");
		exit(1);
	} 
	fscanf(fp, "%d", n);
	
	x = (double **)malloc(sizeof(double *) * (*n));
	y = (double **)malloc(sizeof(double *) * (*n));
	
	if (x == NULL || y == NULL) {
		perror("メモリの確保に失敗しました.\n");
		exit(1);
	}
	
	for (i = 0; i < *n; i++)
		fscanf(fp, "%lf%lf", &x, &y);
	
	free(x);
	free(y);
	fclose(fp);
}

//定積分をする関数

double integrate(double *x, double *y, int n)
{
	int i;
	double ss = 0.0;
	
	for (i = 0; i < n -1; i++)
		ss = ss + (y + y[i+1]) * (x[i+1] - x) / 2.0;
	
	return ss;
}

//結果を出力する関数

void output(double S)
{
	printf("面積 ≒ %f\n", S);
}

//以下、main関数

int main(void)
{
	FILE *fp;
	char fn[32];
	int n;
	double **x, **y, S;
	
	file_input(fn);
	read_file(fp, fn, x, y, &n);
	S = integrate(*x, *y, n);
	output(S);
	
	return 0;
}


色々なサイトのポインタのポインタを使った例題を見ながら手を加えてみたのですが、
やはり不備があるようで、
コンパイルは通りますが、実行時にエラー報告が出てしまいます。
かなりのお手上げ状態です。
どこが誤っているのかご指摘お願いします。

Re:定積分の計算 パート2

#5

投稿記事 by » 17年前

ほとんど質問なのですが、、、

mallocで動的にメモリを確保してますが、それを配列で使用できるのですか?
インクリメントしているのは見かけたのですが、配列は見かけなかったので・・・
開放時にポインタが必要になるので、利用するのかな?と思いましたがどうでしょうか?

また、開放した時その後にアクセスをするとエラーとなるようです。
開放が早すぎると思いますがどうでしょうか?

参考URL:
http://www.geocities.co.jp/SiliconValle ... ic/12.html
http://wisdom.sakura.ne.jp/programming/c/c25.html
http://ja.wikipedia.org/wiki/Malloc

今までの質問をほぼ無視して…(integrateをread_fileに突っ込んだ)
変更してみた。(一番上のを
面積 ≒ 3.101569

が回答となった。いいのかな?
ポインタのポインタなんて使ってないけど…w
#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
//定積分をする関数

double integrate(double *x, double *y, int n)
{
	int i;
	double ss = 0.0;
	
	for (i = 0; i < n -1; i++)
		ss = ss + (y + y[i+1]) * (x[i+1] - x) / 2.0;
	
	return ss;
}

//ファイル名を入力させる関数
/*
void file_input(char *fn)
{
	printf("ファイル名を入力--> ");
	gets(fn);
}
*/
//ファイルから入力データを読み込む関数

double read_file(FILE *fp, char *fn, double *x, double *y, int *n)
{
	int i;
	double ss;
	
	if ((fp = fopen(fn, "r")) == NULL) {
		printf("ファイルをオープンできません.\n");
		exit(1);
	} 
	fscanf(fp, "%d", n);
	
	x = (double *)malloc(sizeof(double) * (*n));
	y = (double *)malloc(sizeof(double) * (*n));
	
	if (x == NULL || y == NULL) {
		perror("メモリの確保に失敗しました.\n");
		exit(1);
	}
	
	for (i = 0; i < *n; i++)
		fscanf(fp, "%lf%lf", &x, &y);
	
	ss = integrate(x,y,*n);
	
	free(x);
	free(y);
	fclose(fp);
	
	return ss;
}


//結果を出力する関数

void output(double S)
{
	printf("面積 ≒ %f\n", S);
}

//以下、main関数

int main(void)
{
	FILE *fp;
	char fn[32]="test_1.txt";
	int n;
	double *x, *y, S;
	
	//file_input(fn);
	 S = read_file(fp, fn, x, y, &n);
	output(S);
	
	return 0;
}

box

Re:定積分の計算 パート2

#6

投稿記事 by box » 17年前

> mallocで動的にメモリを確保してますが、それを配列で使用できるのですか?

提示なさったコードでも使われていますよね。
ただし、配列で、というよりは、あたかも配列であるかのように、
の方が正確です。

動的に確保した領域の先頭アドレスをpとして、
そこからiだけ離れた領域の内容を取得する際
*(p+i)
と書きますが、これは
p
とも書けます(シンタックスシュガー:糖衣構文)。後者は、配列と同じ書き方ですね。

Re:定積分の計算 パート2

#7

投稿記事 by » 17年前

>雷さん
>boxさん

返信が遅れてしまい申し訳ありません。
お二方、返信ありがとうございます。

ご指摘を参考にもう少し自分で吟味してみたいと思います。
また分からない事が出てくるとは思いますが、その時はまた宜しくお願いします。

閉鎖

“C言語何でも質問掲示板” へ戻る