あり、あなたが取ることができる多数のアプローチここで重要なのは、あなたが(最初の二行のそれぞれにおける1)rows
の数とデータのcols
価値へを表現する2つの整数を持っていることを知っているされています。その後、の数字がと表示されます。最初の決定は、「どのようにストレージを管理するのですか?」(動的に割り当てるか、 (VLA)を行列に使用するとStackOverflowされません)。
VLAを使用すると、メモリを動的に割り当て、追跡し、解放する必要がなくなりますが、スタックに収まるより多くの値をdouble
格納してください。以下は、VLAを有効なオプションにする100,000
またはそれ以下の値があると想定しています。
最初に、row
とcol
の値をファイルからどのようにピックオフ(読み取り)しますか? fgets
は、ライン指向入力の方がはるかに好ましい方法ですが、fprintf
への1回のコールでrow
とcol
の両方を実際に取得して、col
値の残りのすべての空白をマトリックスの最初の値まで消費するという利点があります。たとえば、次のように動作します:
/* read row & col and consume all whitespace to first value */
if (fscanf (fp, "%d %d ", &row, &col) != 2) {
fprintf (stderr, "error: failed to read row and col.\n");
return 1;
}
(注:space
を最後変換指定"%d %d "
で以下)row
とcol
値を持つ
、あなたは今まで、バッファのサイズをすることができますファイル内の残りの行のそれぞれをfgets
で読み取ります。各行がバッファに読み込まれると、各列の値はstrtod
を使用してバッファから解析され、値の数はcol
の値に対して検証され、完全な行の行が満たされます。ラインバッファはVLAであり、値ごとに32-chars
(これ以上の値は50%
)である必要があります。バッファのサイズを決定し、次のようにVLAを使用して行列を行うことができる:
bufsz = col * 32; /* set read buffer size based on col */
char buf [bufsz]; /* VLA for read buffer */
double mtrx[row][col]; /* VLA for matrix */
memset (mtrx, 0, row * col * sizeof **mtrx); /* zero matrix */
次に、単に現在の文字が[+-0-9]
の一つであるかどうかをテストするためにポインタを使用して、次いでfgets
と各ラインを読み出し、そしてれます。そうであれば、double
への変換が実行され、有効化され、ポインタは変換の末尾の文字を越える次の文字に進む(strtod
自体によって提供される)。
現在の文字はあなたが興味を持っているものでない場合、単にそれを何もしないし、ライン内のすべての値が変換された後に次の文字(つまり','
Sをスキップする簡単な方法です)
を取得col
に対して成功した変換の数を比較して、エラーが発生していない場合は、行列の完全な行が満たされていることを確認します。次に、次の行を読み、row
行の数が読み込まれ、変換されるまで繰り返す。あなたはrow
行col
値の価値を読んだ後は必要に応じて、あなたの行列を使用することができ、
/* read each remaining line up to row lines */
while (ridx < row && fgets (buf, bufsz, fp)) {
int cidx = 0; /* column index */
char *p = buf, *ep = NULL; /* pointer & end pointer for strtod */
while (cidx < col && *p && *p != '\n') { /* for each character */
/* if '+-' or '0-9' convert number with strtod */
if (*p == '+' || *p == '-' || ('0' <= *p && *p <= '9')) {
errno = 0; /* set errno for strtod */
double tmp = strtod (p, &ep); /* convert string to value */
if (errno) { /* if errno set, conversion failed */
fprintf (stderr, "error: failed conversion mtrx[%d][%d].\n",
row, col);
return 1;
}
mtrx[ridx][cidx++] = tmp; /* set matrix value, inc. cidx */
p = ++ep; /* set new p to one past ep */
}
else /* if not '+-' or '0-9', just get next char */
p++;
}
if (cidx != col) { /* validate that col values contained in line */
fprintf (stderr, "error: row '%d' has only '%d' values.\n",
ridx, cidx);
return 1;
}
ridx++; /* row done and values validated, read next row */
}
:次のようなその意志何かを達成することができます。上
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main (int argc, char **argv) {
int bufsz, col, row, ridx = 0; /* buffer size, col, row, row index */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* read row & col and consume all whitespace to first value */
if (fscanf (fp, "%d %d ", &row, &col) != 2) {
fprintf (stderr, "error: failed to read row and col.\n");
return 1;
}
bufsz = col * 32; /* set read buffer size based on col */
char buf [bufsz]; /* VLA for read buffer */
double mtrx[row][col]; /* VLA for matrix */
memset (mtrx, 0, row * col * sizeof **mtrx); /* zero matrix */
/* read each remaining line up to row lines */
while (ridx < row && fgets (buf, bufsz, fp)) {
int cidx = 0; /* column index */
char *p = buf, *ep = NULL; /* pointer & end pointer for strtod */
while (cidx < col && *p && *p != '\n') { /* for each character */
/* if '+-' or '0-9' convert number with strtod */
if (*p == '+' || *p == '-' || ('0' <= *p && *p <= '9')) {
errno = 0; /* set errno for strtod */
double tmp = strtod (p, &ep); /* convert string to value */
if (errno) { /* if errno set, conversion failed */
fprintf (stderr, "error: failed conversion mtrx[%d][%d].\n",
row, col);
return 1;
}
mtrx[ridx][cidx++] = tmp; /* set matrix value, inc. cidx */
p = ++ep; /* set new p to one past ep */
}
else /* if not '+-' or '0-9', just get next char */
p++;
}
if (cidx != col) { /* validate that col values contained in line */
fprintf (stderr, "error: row '%d' has only '%d' values.\n",
ridx, cidx);
return 1;
}
ridx++; /* row done and values validated, read next row */
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
if (ridx != row) { /* validate that row rows read from file */
fprintf (stderr, "error: file has only row '%d' rows.\n", ridx);
return 1;
}
for (int i = 0; i < row; i++) { /* output the matrix */
for (int j = 0; j < col; j++)
printf (" %9.2f", mtrx[i][j]);
putchar ('\n');
}
return 0;
}
使用例/出力
$ ./bin/readmtrx dat/matrix.txt
3.00 1.00 1180.00 1955.00 221900.00
3.00 2.25 2570.00 1951.00 538000.00
2.00 1.00 770.00 1933.00 180000.00
ルック事を、あなたなら、私に知らせて次はちょうどあなたが提供した例のデータを読み出して出力する短い例で一緒に上記を置きますさらなる質問があります。コンパイラが提供するVLA拡張機能を使用していない場合は、もう1つの答えで説明したように、動的メモリ割り当てを使用することもできます。
「配列」はどのように定義されていますか? –
_私は当初fscanfがcomma_:Yupに問題があると考えました。あなたが正しい。 'fscanf(fpointer、"%lf "、&hold);' –
'fscanf'の戻りコードをチェックして返します0 =>データを読み取ることができませんでした –