![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?8acaa2e)
C言語を使って、ファイルの読み込みをして切り出して2次元配列に格納したいのです。
1,2行目に配列の行の数と列の数が書かれ、3行目から改行とカンマ、スペースで区切られて配列が書かれているテキストを読み込んで2次元配列に格納する。
テキストの例)
4
3
1.1 1.2 1.3 1.4 1.5
2.1 2.2 2.3 2.4 2.5
3.1 3.2 3.3 4.4 3.5
というプログラムを書いています。色々と参考書やサイトを参考してとりあえずの形にはなったと思ったのですが、実行してもエラーが出ます。
どこまで動いているか調べたところ、一行ごとに読み出してそれを切り出して行くところでおかしな事をしてしまっているようですが、どう変えたらいいものか分かりません。
なので、その点のアドバイスと
大きさの分からないファイルから1,2行目を読み出すのはこれで変な動きをする恐れはないか
の2点についてヒントでも構わないので、教えてください。
以下、書いたソースです(申し訳ないのですが、文字数の関係で一部省略しています。)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[] )
{
double ** mainhairetu;
int size_x, size_y; /* size_x 行 size_y 列 */
int i,j,count=0,count2;
int *cut,*temp2;
double temp;
char s2[] = " ,";
char gyou[10],*num;
FILE *fil;
while((fgets(gyou,10,fil)) !=NULL){
if(count == 0){
size_x=atoi(gyou);
count++;
}else if(count ==1){
size_y=atoi(gyou);
count=count+1;
}else{
break;
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ここでmallocを使ってcutとmainhairetuの2つの配列を作っています。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
count=0;
for (i = 0; i < size_y+2; i++) {
mainhairetu[i][0] = atof( strtok( fgets(cut,50,fil),s2 ) );
for (j = 1; j < size_x; j++){
if(count <=1){
count++;
break;
}else{
mainhairetu[i][j] = atof( strtok( NULL,s2 ) );
}
}
}
for(i=0;i<size_y;i++){
for(j=0;j<size_y;j++){
printf("%f",mainhairetu[i][j]);
}
printf("\n");
}
return(0);
}
A 回答 (4件)
- 最新から表示
- 回答順に表示
No.4
- 回答日時:
テキストの例)
5
3
1.1 1.2 1.3 1.4 1.5
2.1 2.2 2.3 2.4 2.5
3.1 3.2 3.3 4.4 3.5
を仮に dataファイルとすればもっと易しく考えて、それはスペース(空白文字)で区切られていることから fscanf() を使ったソースでも対応可能ですよ。
なお、動的二次元配列については↓を参照のこと。
http://www.aso.ecei.tohoku.ac.jp/~shun/multi_dim …
#include <stdio.h>
#include <stdlib.h>
#define MY_FILE "data"
int main(void)
{
FILE *fp;
int gyo,retu;
int i,j;
float **matrix;
fp = fopen(MY_FILE, "r");
fscanf(fp, "%d", &retu);
fscanf(fp, "%d", &gyo);
matrix = (float **)malloc(sizeof(float *) * retu);
if (matrix==NULL) exit(1);
for (i=0; i<retu; i++) {
matrix[i] = (float *)malloc(sizeof(float) * gyo);
if (matrix[i]==NULL) exit(1);
}
printf("%s[%d][%d]:\n", MY_FILE, retu, gyo);
for (i=0; i<gyo; i++) {
for (j=0; j<retu; j++) {
fscanf(fp, "%f", &matrix[i][j]);
printf("%.2f ", matrix[i][j]);
}
printf("\n");
}
fclose(fp);
for (i=0; i<retu; i++) free(matrix[i]);
free(matrix);
return 0;
}
----- 実行結果 -----
data[5][3]:
1.10 1.20 1.30 1.40 1.50
2.10 2.20 2.30 2.40 2.50
3.10 3.20 3.30 4.40 3.50
No.3
- 回答日時:
こっちにも問題ありますね。
> cut = malloc(sizeof(int)*size_y);
よくみたら cutはint *ですね。fgetsの対象としておかしくないですか?
Cの場合、ポインタの型が違っても警告が出るだけでコンパイルは通ったりしますが、そういう警告はできるだけ無視せず、目的の型と一致させるようにしましょう。
sizeof(int)が不明(環境依存のため)ですが、32bitCPU用だとすると4です。size_yは今回の場合3です。
4*3=12文字分しか確保していないのに、
> fgets(cut,50,fil)
と50文字まで読もうしています。
今回の例では、1行(改行まで含めて)20文字あります。確保した12文字を越えています。
この時点で何が起っても不思議ではありません。
1行読む(=X方向にデータを読む)ためのバッファなのですから、基準にするのはsize_xの方でしょう。
> mainhairetu = (double**)malloc(sizeof(double*)*size_x);
> for (i=0 ; i < size_x ; i++) {
> mainhairetu[i] = (double*)malloc(sizeof(double)*size_y);
これだと 2次元配列としては mainhairetu[size_x][size_y] という大きさになります。
しかし、実際に使用しているところを見ると mainhairetu[Y][X]として使用しています。
余る分には(Y側)ただ使わないだけですが、足りない分(X側)では領域をはみ出します。これも何が起っても不思議でない状態です。
どちらかに統一しましょう。一般的には[Y][X]を使います。
> size_yはテキストの行列の列分しかないので、テキストの最初にある行と列の2つ分のつもりです。
一応付け足すと、ファイルは基本的に一方通行です。あるところまで読んだら、次はその続きから読み込みはじめます。
今回は先で2行読み込んでいるので、このループは3行目から読み始めます。
fseek等で読み出し位置を変更できますが、読み込み先によっては変更できないものもあります(キーボードからの入力とか)
No.2
- 回答日時:
> テキストの例)
> 4
> 3
この数字の意味はなんでしょう?
4列x3行だと、その後のデータと合わないのですが。
>while((fgets(gyou,10,fil)) !=NULL){
>if(count == 0){
....
これだと、「3行目」を読みに行きます。
1回目:conut=0→fgets1行目→whileの判定→if(count==0)→count ++;
2回目:→fgets2行目→whileの判定→if(count==1)→count=count+1;
3回目:→fgets3行目→whileの判定→else→break;
2回目でbreakさせるとか、 whileを((count <= 1)&&(fgets... としてcountで先に判定させるとかの工夫が必要です。
もっとも、これくらい回数なら、ループ使わずに2つ並べて書いた方がわかりやすくはないですか?
間違いというわけではないですが。
・エラー対策(1行に10文字(9文字+改行)以上ある、数字ではない、など)が無い
・count++とcount=count+1が混在している
> ここでmallocを使ってcutとmainhairetuの2つの配列を作っています。
これでは、この箇所に間違いは無いかの判断はできかねます。
> for (i = 0; i < size_y+2; i++) {
この+2はなんでしょう?
> mainhairetu[i][0] = atof( strtok( fgets(cut,50,fil),s2 ) );
・これでは、fgetsやstrtokでエラーになっても対処できません。
・この50はどこから来た値ですか?cutの配列長だったら、固定長で50程度なら、ややこしいmallocを使わずとも、最初からcut[50]で宣言しても十分です。size_x等から計算しているのなら、ここでもその値を使うべきです。
・先の「while((fgets(gyou,10,fil)) !=NULL)..」の不具合のため、最初のデータ行(=ファイルの3行目)は9文字分読み込み済みで、ここのfgetsでは10文字目からの読み出しになります。
> if(count <=1){
> count++;
> break;
これの意図がわかりません。
これだと、 1番目と2番のデータ列では、それぞれmainhairetu[0][0],mainhairetu[1][0]にだけデータが入ってそれ以外は何も入りませんが。
> for(j=0;j<size_y;j++){
> printf("%f",mainhairetu[i][j]);
> }
size_yはsize_xの間違いだと思います。
書式に空白や幅の指定が無いため、全ての数値が連続して出力される(しかも値の大きさによって、長さがばらばらになる)ので、見栄えはよくないです。
> return(0);
これくらいの長さで、すぐ終了するものならよいのですが。
mallocしたものは、使い終わったらfreeする習慣を付けましょう。
この回答への補足
テキストの例は
5
3
で5行*3列の間違いです。申し訳ありません。
3行目を読みに行ってしまうのは気が付きませんでした。ご指摘の様に修正してみます。
エラー対策は曲がりなりにも動いてから書く予定でした。
書き方の混在は修正しておきます。
文字数オーバーだったので仕方なく削ってしまいました。
その部分は
cut = malloc(sizeof(int)*size_y);
mainhairetu = (double**)malloc(sizeof(double*)*size_x);
if (mainhairetu==NULL){
exit(1);
}
for (i=0 ; i < size_x ; i++) {
mainhairetu[i] = (double*)malloc(sizeof(double)*size_y);
if (mainhairetu[i]==NULL){
exit(1);
}
}
となっています。
>> for (i = 0; i < size_y+2; i++) {
>
>この+2はなんでしょう?
size_yはテキストの行列の列分しかないので、テキストの最初にある行と列の2つ分のつもりです。
・エラーに関しては上と同様に動いてからと考えていました。
・とりあえず大きめの数と思って50にしてしましましたが、一行で50ではマズイですね。
計算で出す方法を考えてみます。
・上のfgetsの不具合を訂正すれば、大丈夫ですね。
2度目のfgetsを動かした時の動きがあやふやで
テキストの最初の2行を飛ばして3行目から読み出すためのつもりでしたが、
でした。
不要だと分かったので、削除しておきます。
配列の出力は見やすい様に修正しておきます。
freeも一度ソースを貼りつけたときに溢れてしまって削ってしまいました。
多くのご指摘ありがとうございます。もう一度ご指摘の所を含めてソースを書き直してみます。
No.1
- 回答日時:
考え方として、
1区画に格納する最大文字数を調べます。
上詰めか、下詰めかを決めます。
配列の数 を決めます。
バイナリーエディターでCRコードを読み出します。
1文字づつ読んで、カンマ又はCRコードが見つかるたびにメモリーに書き込みます。
CRコードの場合は、配列の行を変えます。
END OF FILEを検出したら、Print文を実行し、結果を確認します。
メモリーに書き込む時は、下詰めなら下から書き込んで、次の文字が見つかれば1文字上にシフトして書き込む手もあります。
結果は、ファイル出力をお忘れなく。
CSVファイルにするのなら、1文字づつ読み込んで、EOFを検出したら最後にCRを追加してファイル出力すれば終わりです。メモリーはCRの数をお忘れなく。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- C言語・C++・C# c言語の問題です 課題1 (二分探索木とセット) 大きさ size の配列 array を考える。す 2 2023/01/10 21:08
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# C言語 3 2022/11/09 13:27
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
関数から配列を返すには?
-
c言語
-
構造体のextern方法
-
C言語 ファイルの指定された行...
-
MFCのCArrayを使った二次元配列
-
define で 配列
-
配列のアドレス部
-
ファイルのデータを構造体に代...
-
C言語の課題が出たのですが自力...
-
c言語 構造体
-
C言語についてです 5人のテスト...
-
AfxBeginThread の引数について
-
コンボボックスでデフォルト値...
-
配列の初期化に関する質問です
-
c言語プログラミング 等差数列...
-
C++で,配列に計算した値を入れ...
-
int i, int i[1];
-
C言語の配列のコピーについて
-
Winsockを用いてデータを交互に...
-
このプログラム見てもらえますか?
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
関数から配列を返すには?
-
C言語において、 配列要素をひ...
-
配列の要素数に変数を入れたい...
-
構造体のextern方法
-
define で 配列
-
c言語
-
C#で構造体の配列を持った構造...
-
C言語の2次元配列 容量が大き...
-
c言語 構造体
-
C言語 ファイルの指定された行...
-
C言語についてです 5人のテスト...
-
int i, int i[1];
-
fclose()でセグメンテーション違反
-
char型配列をint型に代入するには
-
C言語から質問です。
-
Cのエラー
-
コンボボックスでデフォルト値...
-
C言語の課題が出たのですが自力...
-
MFCのCArrayを使った二次元配列
-
[C++]const int と配列
おすすめ情報