ページ 1 / 1
ファイルデータの読み込み
Posted: 2007年10月11日(木) 18:39
by ビスタ
学校の課題です。
・2つの、乱数正方行列データファイルを配列に読み込み、その配列を行列として和と積を求め、
ファイル出力するプログラムを作成せよ。なお、行列データファイルの作成はプログラムを用
いること。サイズは固定値を使わないこと。
C言語
OS:学校の演習室はLinuxですが家で確認するのでWindows vista
コンパイラ:Visual C++2005 Express Edition
以下のような2つのファイルに乱数正方行列データに見えるようなものを格納するプログラムを
作りました。行列計算の確認用に、乱数は0~10の範囲にしてあります。
/*乱数行列ファイルrep2-1.txt,rep2-2.txt作成プログラム*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>//初期化用
main(){
int rnd,i,j,n;
FILE *data;
FILE *data2;
data=fopen("rep2-1.txt","w");
data2=fopen("rep2-2.txt","w");
if(data==NULL){
printf("error!\n");
return;//異常終了
}
if(data2==NULL){
printf("error!\n");
return;
}
printf("Please one nutural number--->>");
scanf("%d\n",&n);
srand((unsigned)time(NULL));//rand初期化
for(j=0;j<n;j++){
for(i=0;i<n;i++){
rnd=rand()%10+1;
fprintf(data,"a[%d]=%d ",i,rnd);
}
fprintf(data,"\n");
}
for(j=0;j<n;j++){
for(i=0;i<n;i++){
rnd=rand()%10+1;
fprintf(data2,"a[%d]=%d ",i,rnd);
}
fprintf(data2,"\n");
}
fclose(data);
fclose(data2);
return 0;
}
で、もうひとつのプログラムでファイルのデータを読み込みたいのですが…
●fgetcとfgetsどちらを使うべきでしょうか?(他に使えるものがあればお願いします)
↑
fgetsだと最大値が必要なのでそこでもつまづいてます。ファイルのデータが可変なので最大値の
取り方が分かりません。
●読み込んだデータの配列への組み込み方がわかりません。またそのデータを「利用して」計算
するためにどうすればいいのかが分かりません。
ちょっとわからないことが多すぎますね……。どれかひとつでも解決すれば解けそうな気も
するのですが…。よろしくお願いします
Re:ファイルデータの読み込み
Posted: 2007年10月11日(木) 20:32
by box
> fprintf(data,"a[%d]=%d ",i,rnd);
データを作る際、"a[何とか]=" の部分は必要でしょうか?
また、データを読み込むときのことを意識して、正方行列本体のデータの前に
行・列の数を出力しておくのは要求仕様に反しているでしょうか?
例えば、3行3列の場合、
3
8 5 1
2 0 7
5 4 2
のようなファイルを作って、読み込むときは最初に行・列の数を読みます。
最初の行を読んだときに、行列本体は3行3列であることが
わかるようになっています。
Re:ファイルデータの読み込み
Posted: 2007年10月11日(木) 23:55
by ビスタ
boxさん、返答ありがとうございます。
> データを作る際、"a[何とか]=" の部分は必要でしょうか?
あ、それは前問のソースを書き換えただけなので残ってただけです;;
> また、データを読み込むときのことを意識して、正方行列本体のデータの前に
> 行・列の数を出力しておくのは要求仕様に反しているでしょうか?
それは大丈夫です。
> 最初の行を読んだときに、行列本体は3行3列であることが
> わかるようになっています。
そうですね。やってみます。
ここまででファイルのデータ読み込みの件は解決したと思います。
配列についてはまだ分からないことがあるので引き続きお願いします…。
ただ、自力で解けたら「解決」にマークしておきます。よろしくお願いします。
Re:ファイルデータの読み込み
Posted: 2007年10月12日(金) 11:27
by やそ
rnd=rand()%10+1;
だと1から10の乱数となりますね。
fgetcで変数cに読み込み、a
[j]に格納する処理を考える。
'1'のときは'10'の可能性も有るのでoneというフラグを利用する。
----------------
各変数、配列の定義
ファイルポインターの定義
ファイルオープン
whileループ
ループ継続条件は
fgetcにて1文字読み込んだ結果がファイル終端(EOF)でない時
'\n'の時
行末処理として
行カウンターに1を足す
列カウンターを0にリセット
' '(スペース)の時
oneフラグが1なら
a[j]に1を格納する。
oneフラグを0クリア。
列カウンターに1を足す。
'1'の時
oneフラグに1を立てる。
'0'の時
oneフラグが1の時
a[j]に10を格納する。
oneフラグを0にリセット。
oneフラグが0の時(else)
a[j]に0を格納する。
上記のどれでもない時
a[j]にcを格納する。
whileループ終端
と言うフローでどうでしょうか?
このフローは最大値が10限定です。
10以上の数値(99など)の場合は通用しません。
Re:ファイルデータの読み込み
Posted: 2007年10月13日(土) 11:11
by ビスタ
>>やそさん
レスありがとうございます。
>1から10の乱数となりますね。
あ、そうですね;;
要するにoneというフラグが1か0かで条件分岐させるんですよね?
適当に変数を指定して、そこに1か0を入れて分岐させるというこ
とですか?
あと2次元配列に値を代入するときに配列の宣言はどう記述したら
いいのでしょうか?やそさんのやり方だと配列のサイズの最大値が
必要ですよね?
それとも、「最大値が10以下」というのは配列のサイズのことですか?
Re:ファイルデータの読み込み
Posted: 2007年10月13日(土) 11:43
by box
> あと2次元配列に値を代入するときに配列の宣言はどう記述したら
そのプログラムでは、最大何行何列までの正方行列に対応する
必要がありますか?
例えば、10行10列までに対応するのであれば、
a[10][10]
のように定義します。
このとき、11行11列以上の正方行列には対応できませんので、
入力ファイルの内容が11行11列以上であれば、
「計算できない」と出力してプログラムを即時に終了させるなどの
手だてが必要です。
行・列の数に制限がない場合は、malloc関数を使って
実行時に領域を確保し、あたかも配列と同じであるかのように
扱うことができます。
今回そこまで必要かどうかはわからないですけれど。
Re:ファイルデータの読み込み
Posted: 2007年10月14日(日) 08:10
by フリオ
指定した大きさの行列を作成してファイルに書き出し、
それを読み込んで表示します。参考になれば。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LIMIT 100
typedef enum {ZERO, RAND} FLAG;
int Alloc(int ***matrix, int n)
{
int i, j;
if(!(*matrix = malloc(sizeof(int *) * n))) return 0;
for(i = 0; i < n; i ++){
if(!((*matrix) = malloc(sizeof(int) * n))){
while(!i) free((*matrix)[-- i]);
free(*matrix);
return 0;
}
}
return 1;
}
void Init(int **matrix, int n, FLAG flag)
{
int i, j;
if(flag){
for(i = 0; i < n; i ++){
for(j = 0; j < n; j ++) matrix[j] = rand() % LIMIT;
}
}
else{
for(i = 0; i < n; i ++){
for(j = 0; j < n; j ++) matrix[j] = 0;
}
}
}
int Write(int **matrix, int n, char *fname)
{
FILE *fp = fopen(fname, "w");
int i, j;
if(!fp) return 0;
fprintf(fp, "%d\n", n);
for(i = 0; i < n; i ++){
for(j = 0; j < n; j ++) fprintf(fp, "%d ", matrix[j]);
fputc('\n', fp);
}
fclose(fp);
return 1;
}
int Read(int ***matrix, int *n, char *fname)
{
FILE *fp = fopen(fname, "r");
int c, i, j;
if(!fp) return 0;
*n = 0;
while((c = fgetc(fp)) != '\n') *n = *n * 10 + (c - '0');
if(!Alloc(matrix, *n)){
fclose(fp);
return 0;
}
Init(*matrix, *n, ZERO);
for(i = 0; i < *n; i ++){
for(j = 0; j < *n; j ++){
while((c = fgetc(fp)) != ' ') (*matrix)[j] = (*matrix)[j] * 10 + (c - '0');
}
fgetc(fp);
}
fclose(fp);
return 1;
}
void Print(int **matrix, int n)
{
int i, j;
for(i = 0; i < n; i ++){
for(j = 0; j < n; j ++) printf("%2d ", matrix[j]);
putchar('\n');
}
}
void Delete(int **matrix, int n)
{
int i;
for(i = 0; i < n; i ++) free(matrix);
free(matrix);
}
int main(void)
{
int **matrix0, **matrix1;
int n0, n1;
printf("n : ");
scanf("%d", &n0);
if(!Alloc(&matrix0, n0)) return 1;
Init(matrix0, n0, RAND);
puts("matrix0");
Print(matrix0, n0);
if(!Write(matrix0, n0, "test000.txt")){
Delete(matrix0, n0);
return 1;
}
Delete(matrix0, n0);
if(!Read(&matrix1, &n1, "test000.txt")) return 1;
puts("matrix1");
Print(matrix1, n1);
Delete(matrix1, n1);
return 0;
}
Re:ファイルデータの読み込み
Posted: 2007年10月14日(日) 10:48
by フリオ
"Init"関数で、"srand((unsigned)time(NULL))"を忘れてました。
Re:ファイルデータの読み込み
Posted: 2007年10月14日(日) 14:36
by ビスタ
>boxさん
レスありがとうございます。今回、課題としては本来、行列のサイズは指定してもいいはず
なのですが評価が下がるので二次元配列にするときに配列を動的に確保したいんですよね…。
やはりmallocあたりを使わないといけないようです。
>フリオさん
詳細ソースありがとうございます。参考にさせていただきます!
calloc,mallocは知ってましたがAllocなんてのもあるんですね…メモリの動的確保って
C言語のサイトでも載ってるのが少なくて定義というか…稼動範囲?みたいなのが
よく分からないとか扱いが難しくて、どうも理解が追いつかないです;;
Re:ファイルデータの読み込み
Posted: 2007年10月15日(月) 11:19
by やそ
ビスタさんお疲れ様です。
boxさん、配列宣言の補足、ありがとうございます。
フリオさん、詳細なソース提示お疲れ様です&ありがとうございます。
が、正直、ビスタさんの質問されている内容から察するにフリオさんの提示したソースは
レベルが高いんじゃないかなあと思います。(私にもね・・・(笑))
また、「学校の課題」だそうですので、簡単に答えそのものを提示してしまうと課題の意味がないように思えたのであえて日本語でロジックを組んでみました。
ロジックは理解がしやすいようにあえて配列の要素数を10に抑えて作った訳です。(なんか言い訳っぽいですね)
まあ、mallocを知っているなら動的に配列確保も出来そうですね。
ビスタさん、フリオさんのソースのロジックが理解(解析)出来れば学校の課題レベルなんてお茶の子っすよ。
がんばってくださいね。