数値の二次元配列の格納

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
べけん
記事: 21
登録日時: 5年前

数値の二次元配列の格納

#1

投稿記事 by べけん » 4年前

1自分は今何がしたくて
csvファイルに保存されている行数不明の数値を二次元配列に格納をし格納された数値同士の比較(具体的には座標表記されているもの同士の距離の算出)を行いたい。

ファイルの中身

番号 mean x y
1 100 5 10
2 93 7 7
3 120 13 4
4 30 8 6

といった中身

2どう取り組んで(作ったプログラムはどれで
まずは二次元配列に格納を行うために以下のようなことを行った

コード:


#include <stdio.h>

int main(void){
  FILE *fp;
  char *fname = "Results2.csv";
	long i;
  int line=0;
  int arr[1000][10];

  fp = fopen( fname, "r" );
  if( fp == NULL ){
    printf( "%sfile cannnot open\n", fname );
    return -1;
  }
	  for(i = 0; i < sizeof(arr)/sizeof(arr[0]) && fgets(arr[i], sizeof(arr[i]), fp); i++)
	{
		line++;
	}
	for(i = 0; i < line; i++){
			printf("%d\n",arr[i][1]);
		}
  fclose(fp);
	
  return 0;
}

3どのようなエラーやトラブルで困っていて
sizeofを使った場合列数を数えることができるのは良いのだがint型に対応していないため数値の記入が正しくできない。

4自分は何が解らないのか、知りたいのか
sizeofを使わずに数値の列数を数えるあるいは数値をchar型として読み取ったのちにint型への変換を行う方法が知りたい。(感覚的に後者より前者の方がやりやすそうだとは思う)

5今のCの知識はどの程度なのか
初心者に近い状態

osはwindowsでコンパイラはvisual studioです

Math

Re: 数値の二次元配列の格納

#2

投稿記事 by Math » 4年前

落ち着いて文章を読み直してください。

ファイルの中身

番号 mean x y
1 100 5 10
2 93 7 7
3 120 13 4
4 30 8 6

といった中身

Results2.csv ファイル(^^;  csv って コンマで区切られた(普通エクセルで読める)ものでしょう?

かずま

Re: 数値の二次元配列の格納

#3

投稿記事 by かずま » 4年前

べけん さんが書きました:
4年前
1自分は今何がしたくて
csvファイルに保存されている行数不明の数値を二次元配列に格納をし格納された数値同士の比較(具体的には座標表記されているもの同士の距離の算出)を行いたい。
距離の算出は分かりますが、何と何を比較したいのかがよく分かりません。
べけん さんが書きました:
4年前
4自分は何が解らないのか、知りたいのか
sizeofを使わずに数値の列数を数えるあるいは数値をchar型として読み取ったのちにint型への変換を行う方法が知りたい。(感覚的に後者より前者の方がやりやすそうだとは思う)
入力ファイルの内容は char の列です。
それを int に変えるのは、fscanf の "%d" が最適でしょう。

それから、Results2.csv の 1行目は「番号 mean x y」で
これは読み飛ばさないといけないのですよね。

コード:

#include <stdio.h>  // fopen, fclose, feof, fgetc, fscanf, printf
#include <math.h>   // sqrt

int main(void)
{
	char *fname = "Results2.csv";
	int arr[1000][4];
	const int MAX_LINE = sizeof arr / sizeof *arr;
	int line = 0;

	FILE *fp = fopen(fname, "r");
	if (fp == NULL) { printf("%s: file cannnot open\n", fname); return 1; }

	while (fgetc(fp) != '\n' && !feof(fp)) ;  // skip the first line
	while (line < MAX_LINE && fscanf(fp, "%d%d%d%d",
		arr[line], arr[line]+1, arr[line]+2, arr[line]+3) == 4) line++;
	fclose(fp);

	for (int i = 0; i < line; i++) {
		double x = arr[i][2], y = arr[i][3], d = sqrt(x*x + y*y);
		printf("%4d %4d %4d %4d : %8.3f\n",
				arr[i][0], arr[i][1], arr[i][2], arr[i][3], d);
	}
	return 0;
}
これでよいのかどうか、必ず返事をください。お待ちしております。

Math

Re: 数値の二次元配列の格納

#4

投稿記事 by Math » 4年前

csv ファイルの読み込みはviewtopic.php?f=3&t=20649
に私が書いた方法をアレンジすればいいでしょう。

空白セパレート を コンマ・セパレートにすればいいからね。
過去ログに何度も答えたから検索すればすぐわかるはずです。

べけん
記事: 21
登録日時: 5年前

Re: 数値の二次元配列の格納

#5

投稿記事 by べけん » 4年前

かずまさん

上記のコードを打ち込んだところコンパイルはできましたが動かしても何も出てきませんでした。

また、距離の計算に関してですが点と原点の距離ではなく点同士の距離の計算を行いたいと考えております。
説明不足で申し訳ございませんでした。

かずま

Re: 数値の二次元配列の格納

#6

投稿記事 by かずま » 4年前

べけん さんが書きました:
4年前
上記のコードを打ち込んだところコンパイルはできましたが動かしても何も出てきませんでした。
「Results2.csv: file cannot open」と出てこないということは
fopen は成功しているということですね。
そのあと何も出ないということは fscanf が失敗して、line が
0 のままだったということになります。
for文の前に printf("line = %d\n", line); を入れて
確認してみてください。

Visual Studio を使っているのなら、2つ目の while のところに
ブレークポイントを置いて、シングルステップ実行しながら
line の値を確認できますよ。

べけん
記事: 21
登録日時: 5年前

Re: 数値の二次元配列の格納

#7

投稿記事 by べけん » 4年前

lineの値を確認するためにfor文の前にprintfを入れてみると0になっていました。
それだけではなくfor文内のlineを5に入れ替えたところ配列の全ての値が0になっていて格納もできていないことがわかりました。
どのようにすればよいでしょうか?

かずま

Re: 数値の二次元配列の格納

#8

投稿記事 by かずま » 4年前

べけん さんが書きました:
4年前
lineの値を確認するためにfor文の前にprintfを入れてみると0になっていました。
それだけではなくfor文内のlineを5に入れ替えたところ配列の全ての値が0になっていて格納もできていないことがわかりました。
どのようにすればよいでしょうか?
for文内のlineを 5に入れ替えたというソースを貼り付けてください。

また、なぜ 5なんでしょうか?
Results2.csv は 5行ですが、先頭に「番号 mean x y」がはいっているから
読み込むべきデータは 4行です。
べけん さんが書きました:
4年前
上記のコードを打ち込んだところコンパイルはできましたが動かしても何も出てきませんでした。
打ち込んだということは、コピペせずに、手で打ち込んだということ
ですか? それなら、間違いが入る可能性があります。例えば、
while (fgetc(fp) != '\n' && !feof(fp)) ; のところで
'\n' の代わりに、'n' と打ち込んでしまったとしましょう。
fgetc(fp) で 1文字ずつ読むと mean の 'n' を読み込んだところで
whileループを終了します。
次の fscanf の "%d" はスペースを読み飛ばして 'x' を読み込み、
それは数字ではないので、fscanf はその 'x' を入力バッファに戻し、
エラー終了します。4 つの数値が読み込めなかったので 0 を返し、
2つ目の whileループも終了しますから、line は 0 のままです。

とにかく、べけんさんが実際にコンパイルしている最新のソースを
見せてください。

あるいは、Results2.csv の先頭 1行を削除して 4行のデータだけにし、
ソースの while (fgetc(fp) != '\n' && !feof(fp)) ; の 1行を削除
してみるとどうなるか教えてください。

かずま

Re: 数値の二次元配列の格納

#9

投稿記事 by かずま » 4年前

もう一つ考えられるのは、
while (fgetc(fp) != '\n' && !feof(fp)) ; のところで
'\n' の代わりに、'/n' と打ち込んでしまったとしましょう。

'/n' は 2文字ですがこれは許されて、0x2f6e という値になります。
fgetc(fp) で 1文字ずつ読むとこれと一致する文字は現れないので
ファイルの最後まで読み切って、!feof(fp) が 0 になり
whileループを終了します。

次の fscanf はファイルの終わりに達しているので EOF(-1)を返し、
それは 4 ではないため、2つ目の whileループも終了し、
line は 0 のままです。

べけん
記事: 21
登録日時: 5年前

Re: 数値の二次元配列の格納

#10

投稿記事 by べけん » 4年前

まずfor文ないの値を5にした理由としてはResults.csvの中身が実際は175行ありその全てを書くことが困難なため最初の5行を上に書いたためです。
次の打ち込んだに関してですが表現の仕方が悪く申し訳ございません。
コードは全てコピペしました。

現在コンパイルしているソースは以下のような形です

コード:


#include <stdio.h>  // fopen, fclose, feof, fgetc, fscanf, printf
#include <math.h>   // sqrt

int main(void)
{
	char *fname = "Results.csv";
	int arr[1000][4];
	const int MAX_LINE = sizeof arr / sizeof arr[0];
	int line = 0;

	FILE *fp = fopen(fname, "r");
	if (fp == NULL) { printf("%s: file cannnot open\n", fname); return 1; }

	while (fgetc(fp) != '\n' && !feof(fp)) ;  // skip the first line
	while (line < MAX_LINE && fscanf(fp, "%d%d%d%d",
		arr[line], arr[line]+1, arr[line]+2, arr[line]+3) == 4) line++;
	fclose(fp);
	printf("%d\n",line);
	for (int i = 0; i < line; i++) {
		double x = arr[i][2], y = arr[i][3];
		printf("%4d %4d %4d %4d\n",
				arr[i][0], arr[i][1], arr[i][2], arr[i][3]);
	}
	return 0;
}

もう一つ質問なのですが
arr[line], arr[line]+1, arr[line]+2, arr[line]+3) == 4)
のコードの意味はなんでしょうか?
ご回答よろしくお願いいたします。

かずま

Re: 数値の二次元配列の格納

#11

投稿記事 by かずま » 4年前

べけん さんが書きました:
4年前
現在コンパイルしているソースは以下のような形です
Results.csv

コード:

番号 mean x y
1 100 5 10
2 93 7 7
3 120 13 4
4 30 8 6
#10のコードの実行結果

コード:

4
   1  100    5   10
   2   93    7    7
   3  120   13    4
   4   30    8    6
思った通りに動きます。

ひょっとして、べけんさんの Results.csv には先頭に空行があり、
2行目に「番号 mean x y」があるのではありませんか?

その場合、while (fgetc(fp) != '\n' && !feof(fp)) ; でその空行を
読み飛ばした後、fscanf の "%d" が「番」を読み込もうとして、
数字ではないから読み込みに失敗し、0 を返して、line が 0 のまま
なのではありませんか?
#10 のソースコードも先頭に空行がありますよね。
べけん さんが書きました:
4年前
arr[line], arr[line]+1, arr[line]+2, arr[line]+3) == 4)
のコードの意味はなんでしょうか?
&arr[line][0], &arr[line][1], &arr[line][2], &arr[line][3]) == 4)
と同じ意味です。
sizeof *arr と sizeof arr[0] が同じ意味であるように。

fgets と sscanf を使うことにより、数値が 4つ無い行を
無視するような読み方もできます。

コード:

#include <stdio.h>  // fopen, fclose, fgets, sscanf, printf
#include <math.h>   // sqrt

int main(void)
{
	char *fname = "Results.csv";
	int arr[1000][4];
	const int MAX_LINE = sizeof(arr) / sizeof(arr[0]);
	int line = 0;

	FILE *fp = fopen(fname, "r");
	if (fp == NULL) { printf("%s: file cannnot open\n", fname); return 1; }

	char buf[256];
	while (line < MAX_LINE && fgets(buf, sizeof(buf), fp) != NULL)
		if (sscanf(buf, "%d%d%d%d", &arr[line][0], &arr[line][1],
				&arr[line][2], &arr[line][3]) == 4) line++;
	fclose(fp);
	printf("%d\n",line);
	for (int i = 0; i < line; i++)
		printf("%4d %4d %4d %4d\n",
				arr[i][0], arr[i][1], arr[i][2], arr[i][3]);
	return 0;
}
これなら Results.csv が次のようになっていても読めます。

コード:


番号 mean x y

1 100 5 10
2 93 7 7

3 120 13 4
4 30 8 6

べけん
記事: 21
登録日時: 5年前

Re: 数値の二次元配列の格納

#12

投稿記事 by べけん » 4年前

すみません
csvの中身に関してですが、txtファイルではなくexcelファイルで読み取ったものをそのまま書いていました...
ですので、txtファイルの形で書くと数値と数値の間に,が入ることになります
おそらく,の処理ができていないため正確に表記されなかったのかと思われます...
説明不足で申し訳ございませんでした。

かずま

Re: 数値の二次元配列の格納

#13

投稿記事 by かずま » 4年前

べけん さんが書きました:
4年前
ですので、ファイルの形で書くと数値と数値の間に,が入ることになります
おそらく,の処理ができていないため正確に表記されなかったのかと思われます...
そこまで原因が分かっていて、まだコードが書けないのでしょうか?

コード:

#include <stdio.h>  // fopen, fclose, feof, fgetc, fscanf, printf

int main(void)
{
	char *fname = "Results.csv";
	int arr[1000][4];
	const int MAX_LINE = sizeof arr / sizeof arr[0];
	int line = 0;

	FILE *fp = fopen(fname, "r");
	if (fp == NULL) { printf("%s: file cannnot open\n", fname); return 1; }

	char buf[256];
	while (line < MAX_LINE && fgets(buf, sizeof buf, fp) != NULL)
		if (sscanf(buf, "%d,%d,%d,%d", &arr[line][0], &arr[line][1],
				&arr[line][2], &arr[line][3]) == 4) line++;
	fclose(fp);
	printf("%d\n",line);
	for (int i = 0; i < line; i++)
		printf("%4d %4d %4d %4d\n",
				arr[i][0], arr[i][1], arr[i][2], arr[i][3]);
	return 0;
}
Results.csv

コード:

番号,mean,x,y
1,100,5,10
2,93,7,7
3,120,13,4
4,30,8,6
実行結果

コード:

4
   1  100    5   10
   2   93    7    7
   3  120   13    4
   4   30    8    6
距離の計算はどうするんでしょうか?


Math

Re: 数値の二次元配列の格納

#15

投稿記事 by Math » 4年前

gcc 8.2.0 使用

コンマは文字列の一部として読み込んでしまうので コンマで区切られた文字列を読み込場合には注意すること。
なお行末はコンマでなく改行で区切られることにも注意。

Math

Re: 数値の二次元配列の格納

#16

投稿記事 by Math » 4年前

修正前のものを送ってしまった。

printf("%d\t %d\t %d\t %d\n", arr[L][0], arr[L][1], arr[L][2], arr[L][3]);

が正しいです。

べけん
記事: 21
登録日時: 5年前

Re: 数値の二次元配列の格納

#17

投稿記事 by べけん » 4年前

返信が遅くなってしまいました。
自分なりに色々調べて最終的には以下のようなコードを書いたのですがsegmentation fault 11というのが出てしまい結果が出力されません。
解決方法を教えていただきたいです。

csvの中身は
,area, mean,min,max,x,y
1,0,10,10,10,4,5
2,0,10,14,14,6,8
...
となっています
(19,20,21全てほぼ同じ内容)

osはlinuxを使っています

コード:


#include <stdio.h>  // fopen, fclose, feof, fgetc, fscanf, printf
#include <math.h>   // sqrt
#include <string.h>
#include <stdlib.h>
#define BUF_SIZE 256
//#include <iostream>

int main(void)
{
	char *fnamea = "Results16.csv";
	char *fnameb = "Results17.csv";
	char *fnamec = "Results18.csv";
	char arr[1000][4];
	char buf[2048]={0};
	int(*R1)[4000];
	int(*R2)[4000];
	int n,m;
	n = 100,m = 100;
	R1 = malloc(sizeof(int)*n*m);
	
	if(R1 == 0){
		fprintf(stderr,"error\n");
		exit(1);
	}

	R2 = malloc(sizeof(int)*n*m);
	if(R2 == 0){
		fprintf(stderr,"error\n");
		exit(1);
	}
	//int R[100000];
	int i,j;
	int data[1000][4];
	int line0 = 0;
	int line1 = 0;
	int line2 = 0;

	FILE *fp = fopen(fnamea, "r");
	if (fp == NULL) { printf("%s: file cannnot open\n", fnamea); return 1; }

	//while (fgetc(fp) != '\n' && !feof(fp)) ;  // skip the first line
	fgets(buf,2048,fp);   // skip the first line
	//printf("%s",buf);
	
	int x0[4000],y0[4000],ev0[4000],mean0[4000],min0[4000],max0[4000],area0[4000];
	
	while(1){
		//printf("hoge\n");
		if( fgets(buf,2048,fp) == NULL ) break;   // skip the first line
		//printf("hoghoge\n");
		//printf("%s",buf);
		sscanf(buf,"%d,%d,%d,%d,%d,%d,%d",&ev0[line0],&area0[line0],&mean0[line0],&min0[line0],&max0[line0],&x0[line0],&y0[line0]);
		//printf("%d %d %d %d\n",ev0[line0],mean0[line0],x0[line0],y0[line0]);
		line0++;
		
	}
	fclose(fp);

	
	
	FILE *fq = fopen(fnameb, "r");
	if (fq == NULL) { printf("%s: file cannnot open\n", fnameb); return 1; }

	//while (fgetc(fp) != '\n' && !feof(fp)) ;  // skip the first line
	fgets(buf,2048,fq);   // skip the first line
	//printf("%s",buf);
	
	int x1[4000],y1[4000],ev1[4000],mean1[4000],min1[4000],max1[4000],area1[4000];
	while(1){
		if( fgets(buf,2048,fq) == NULL ) break;   // skip the first line
		//printf("%s",buf);
		sscanf(buf,"%d,%d,%d,%d,%d,%d,%d",&ev1[line1],&area1[line1],&mean1[line1],&min1[line1],&max1[line1],&x1[line1],&y1[line1]);
		//printf("%d %d %d %d\n",ev1[line1],mean1[line1],x1[line1],y1[line1]);
		line1++;
		
	}

	fclose(fq);

	FILE *fr = fopen(fnamec, "r");
	if (fr == NULL) { printf("%s: file cannnot open\n", fnamec); return 1; }

	//while (fgetc(fp) != '\n' && !feof(fp)) ;  // skip the first line
	fgets(buf,2048,fr);   // skip the first line
	//printf("%s",buf);
	
	int x2[4000],y2[4000],ev2[4000],mean2[4000],min2[4000],max2[4000],area2[4000];
	while(1){
		//printf("hoge\n");
		if( fgets(buf,2048,fr) == NULL ) break;   // skip the first line
		//printf("hoghoge\n");
		//printf("%s",buf);
		sscanf(buf,"%d,%d,%d,%d,%d,%d,%d",&ev2[line2],&area2[line2],&mean2[line2],&min2[line2],&max2[line2],&x2[line2],&y2[line2]);
		//printf("%d %d %d %d\n",ev2[line2],mean2[line2],x2[line2],y2[line2]);
		line2++;
		
	}

	fclose(fr);

	printf("\n");

	FILE *outputfile;         // 出力ストリーム
  
  outputfile = fopen("d.txt", "w");  // ファイルを書き込み用にオープン(開く)
  if (outputfile == NULL) {          // オープンに失敗した場合
    printf("cannot open\n");         // エラーメッセージを出して
    exit(1);                         // 異常終了
  }
	
	//printf("%d\n",x0[1]-y0[1]);
	//for(int h=2;h<30;h++){
	for(i=0;i<line0;i++){
		for(j=0;j<line1;j++){
			R1[i][j] = (x0[i]-x1[j])*(x0[i]-x1[j])+(y0[i]-y1[j])*(y0[i]-y1[j]);
			//R[i*line1+j] = (x0[i]-x1[j])*(x0[i]-x1[j])+(y0[i]-y1[j])*(y0[i]-y1[j]);
			//printf("%d ",R[i][j]);
		for(int k=0;k<line2;k++){
			R2[j][k] = (x1[j]-x2[k])*(x1[j]-x2[k])+(y1[j]-y2[k])*(y1[j]-y2[k]);
		
			if ((R1[i][j] < 5) && (R2[j][k] < 5)){
		//printf("%d %d %d\n%d %d %d\n",ev0[i],ev1[j],ev2[k],mean0[i],mean1[j],mean2[k]);
		int s0 = mean0[i] - mean1[j],s2 = mean2[k] - mean1[j];
		if(s0 >= 0 && s2 >= 0){
			//printf("%d %d\n",s0,s2);
			//printf("%d %d %d %d\n",ev1[j],mean1[j],x1[j],y1[j]);
			//fprintf(outputfile, "%d %d %d %d\n",ev1[j],mean1[j],x1[j],y1[j]); // ファイルに書く
			fprintf(outputfile, "%d\n",mean1[j]);
  
		}
		
	}
}
}
			//printf("%d ",R[i*line1+j]);
		}
		free(R1);
		free(R2);
		//printf("\n");
	//}
	//int arr[1000][4];


  fclose(outputfile);
	
	FILE *fs;
	char buf2[BUF_SIZE];
	int LINE = 0;  
	if ((fs = fopen("d.txt", "r")) == NULL) {
    return -1;
  }
 
  while (fgets(buf2, BUF_SIZE, fs) != NULL) {
    LINE++;
  }
 
  printf("%d\n", LINE);

	exit(0);
}


かずま

Re: 数値の二次元配列の格納

#18

投稿記事 by かずま » 4年前

Results16.csv、Results17.csv、Results18.csv の行数はいくつですか?
すなわち、プログラム中の line0、line1、line2 はいくつですか?

コード:

	int(*R1)[4000];
	int(*R2)[4000];
	int n,m;
	n = 100,m = 100;
	R1 = malloc(sizeof(int)*n*m);
これは非常にまずい。
R1 は「10000個の int の領域」の先頭を指します。
1行が 4000個ですから、2行半です。
R1[ i][j] の i が 0 または 1 の場合、j は 3999まで OK。
R1[ i][j] の i が 2 の場合、j は 1999まで OK。
でも、i は 0~(line0-1)、j は 0~(line1-1) なんですよね。

R1 の計算結果は後で使うのでないようなので、
ただの int R1; で構わないのではありませんか?

ということで、次のように書き直してみました。

コード:

#include <stdio.h>   // fopen, fclose, fgets, sscanf, printf

#define MAX_DATA 4000

struct Data { int ev, area, mean, min, max, x, y; };
struct Data data[3][MAX_DATA];

int readData(struct Data *p, int size, const char *fname)
{
	FILE *fp = fopen(fname, "r");
	if (!fp) { printf("%s: file cannnot open\n", fname); return -1; }

	char buf[2048];
	fgets(buf, sizeof buf, fp);		// skip the first line
	int i;
	for (i = 0; i < size && fgets(buf, sizeof buf, fp); i++) {
		if (sscanf(buf, "%d,%d,%d,%d,%d,%d,%d", &p->ev, &p->area,
				&p->mean, &p->min, &p->max, &p->x, &p->y) != 7) {
			printf("%s: sscanf failed\n", fname); return -2;
		}
		printf("%d %d %d %d\n", p->ev, p->mean, p->x, p->y);
	}
	fclose(fp);
	return i;
}

int main(void)
{
	const char *fname[3] = {
		"Results16.csv", "Results17.csv", "Results18.csv"
	};
	int line[3];
	for (int i = 0; i < 3; i++) {
		line[i] = readData(data[i], MAX_DATA, fname[i]);
		if (line[i] < 0) return 1;
	}

	FILE *outputfile = fopen("d.txt", "w");
	if (!outputfile) { printf("cannot create d.txt\n"); return 1; }

	struct Data *p = data[0];
	for (int i = 0; i < line[0]; i++) {
		struct Data *q = data[1];
		for (int j = 0; j < line[1]; j++) {
			int x = p->x - q->x, y = p->y - q->y, R1 = x*x + y*y;
			struct Data *r = data[2];
			for (int k = 0; k < line[2]; k++) {
				int x = q->x - r->x, y = q->y - r->y, R2 = x*x + y*y;
				if (R1 < 5 && R2 < 5) {
					printf("%d %d %d\n%d %d %d\n",
							p->ev, q->ev, r->ev, p->mean, q->mean, r->mean);
					int s0 = p->mean - q->mean, s2 = r->mean - q->mean;
					if (s0 >= 0 && s2 >= 0) {
						printf("%d %d\n", s0, s2);
						printf("%d %d %d %d\n", q->ev, q->mean, q->x, q->y);
						fprintf(outputfile, "%d %d %d %d\n",
								q->ev, q->mean, q->x, q->y);
						fprintf(outputfile, "%d\n", q->mean);
					}
				}
			}
		}
	}
	printf("\n");
	fclose(outputfile);

	FILE *fs = fopen("d.txt", "r");
	if (!fs) { puts("d.txt: fopen failed"); return -1; }

	int LINE = 0;
	char buf[2048];
	while (fgets(buf, sizeof buf, fs)) LINE++;
	printf("%d\n", LINE);

	return 0;
}
私の勘違いかもしれません。
このプログラムでどうなるか、ご報告いただけると幸いです。

かずま

Re: 数値の二次元配列の格納

#19

投稿記事 by かずま » 4年前

かずま さんが書きました:
4年前
ということで、次のように書き直してみました。
すみません。
次のように、i++, j++, k++ のあとに p++, q++, r++ が必要です。

コード:

	struct Data *p = data[0];
	for (int i = 0; i < line[0]; i++, p++) {
		struct Data *q = data[1];
		for (int j = 0; j < line[1]; j++, q++) {
			int x = p->x - q->x, y = p->y - q->y, R1 = x*x + y*y;
			struct Data *r = data[2];
			for (int k = 0; k < line[2]; k++, r++) {

かずま

Re: 数値の二次元配列の格納

#20

投稿記事 by かずま » 4年前

またまた、申し訳ありません。
readData の中の for文にも同じ修正が必要した。

コード:

	for (i = 0; i < size && fgets(buf, sizeof buf, fp); i++, p++) {

べけん
記事: 21
登録日時: 5年前

Re: 数値の二次元配列の格納

#21

投稿記事 by べけん » 4年前

動かしてみたところ上手くいった感じの結果が出ました!
ありがとうございます!
line0,line1,line2はそれぞれ1200行程度です。

僕の書いたコードに関してですがmallocを使わないほうが良いということでしょうか?

かずま

Re: 数値の二次元配列の格納

#22

投稿記事 by かずま » 4年前

べけん さんが書きました:
4年前
僕の書いたコードに関してですがmallocを使わないほうが良いということでしょうか?
int (*R1)[4000];
R1 = malloc(sizeof(int) * 4000 * 4000);
あるいは、ファイルの読み込みが終わった後で、
R1 = malloc(sizeof(int) * line0 * 4000);
とすれば、元のプログラムでも動くでしょう。
R1 = malloc(sizeof(int[4000]) * line0); でも構いません。

でも、本当に mallocでそんなに大きな領域を確保する必要があるでしょうか?
R1[ i][j] に保存した値は、その直後に k を変えながら(line2)回参照され
ますが、j が 1 増えた後に元の R1[ i][j] が参照されることはありません。
それなら、malloc を使わず int R1; で十分でしょう。

例えば、2つの配列の内容を交換する場合、次のように書くことができます。

コード:

	int a[5] = { 1, 2, 3, 4, 5 }, b[5] = { 6, 7, 8, 9, 10 };
	int *c = malloc(sizeof(int) * 5);
	for (int i = 0; i < 5; i++)
		c[i] = a[i], a[i] = b[i], b[i] = c[i];
	free(c);
でも、次のように書けば、malloc も free も不要です。

コード:

	int a[5] = { 1, 2, 3, 4, 5 }, b[5] = { 6, 7, 8, 9, 10 };
	int c;
	for (int i = 0; i < 5; i++)
		c = a[i], a[i] = b[i], b[i] = c;

Math

Re: 数値の二次元配列の格納

#23

投稿記事 by Math » 4年前

OS がWindows10 からLinux に変わったようだけど #14 の方法でいいはずだぜ。
へんに苦労してるようだけど csv の例はいくらでもあるよ。

返信

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