2017-10-16 4 views
0

私はスキャンしているテキストファイルを持っています。ファイルの最初の数字はマトリックスの行数、2番目の数字はマトリックスの列数です。Cの配列にスキャンする際の問題

"テキストファイル"

4  
10 
3.000000,1.000000,1180.000000,1955.000000,221900.000000 
3.000000,2.250000,2570.000000,1951.000000,538000.000000 
2.000000,1.000000,770.000000,1933.000000,180000.000000 
. 
. 
. 

N(4,10)マトリックス

Iは、2つのDで受信された値を読み取るためにアレイと二つのループを読み取る格納する関数fscanfを使用していアレイ。

double hold; 
fscanf(fpointer,"%d",&value);//gets me 4 
fscanf(fpointer,"%d",&lastvalue);/*gets me 10*/ 
for (i=0; i<value; i++) 
{ 
for (j=0; j<lastvalue; j++) //Supposed to input the other values 
{ 
    fscanf(fpointer,"%lf",&hold); array[i][j]=hold; 

私は配列の内容を2つのforループで印刷しています。

for(i=0;i<value;i++){ 
     for(j=0;j<lastvalue;j++){ 

    printf("%lf\t", array[i][j]); 
          } 
    printf("\n"); 

ただし、ループの最初のインデックスが出力として繰り返されます。

3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000  
3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000  

私はこれにかなりの時間を費やしてきたと私は私のロジックが正しくないか、私は関数fscanfについて理解していないよ何かあるかはわかりません。私は最初fscanfがカンマで問題を抱えていると思った。 fscanf(...,"%lf[^ ,]"...)。私は同じ出力を受けました。間違った点や修正方法を教えてください。

+0

「配列」はどのように定義されていますか? –

+4

_私は当初fscanfがcomma_:Yupに問題があると考えました。あなたが正しい。 'fscanf(fpointer、"%lf "、&hold);' –

+1

'fscanf'の戻りコードをチェックして返します0 =>データを読み取ることができませんでした –

答えて

1

カンマを処理する必要があります。 :

#include <stdio.h> 
#include <stdlib.h> 


void die(char *msg) { 
    fprintf(stderr, "Error: %s\n", msg); 
    exit(1); 
} 

double **read_matrix(FILE *f) { 
    int m, n; 
    if (fscanf(f, "%d%d", &m, &n) != 2) die("Couldn't scan matrix size"); 
    if (m <= 0 || n <= 0) die("Bad matrix size"); 
    double **matrix = malloc(m * sizeof(double*)); 
    if (!matrix) die("Couldn't allocate matrix spine"); 
    for (int i = 0; i < m; ++i) { 
    matrix[i] = malloc(n * sizeof(double)); 
    if (!matrix[i]) die("Couldn't allocate matrix row"); 
    // Read the first column. No comma. 
    if (fscanf(f, "%lf", &matrix[i][0]) != 1) die("Couldn't read matrix (1)"); 
    // Read the other columns. Skip preceding commas. 
    for (int j = 1; j < n; ++j) 
     if (fscanf(f, ",%lf", &matrix[i][j]) != 1) die("Couldn't read matrix (2)"); 
    } 
    return matrix; 
} 

int main(void) { 
    double **matrix = read_matrix(stdin); 
    for (int i = 0; i < m; ++i) { 
    for (int j = 0; j < n; ++j) printf(" %lf", matrix[i][j]); 
    printf("\n"); 
    } 
    return 0; 
} 
1

あり、あなたが取ることができる多数のアプローチここで重要なのは、あなたが(最初の二行のそれぞれにおける1)rowsの数とデータのcols価値へを表現する2つの整数を持っていることを知っているされています。その後、の数字がと表示されます。最初の決定は、「どのようにストレージを管理するのですか?」(動的に割り当てるか、 (VLA)を行列に使用するとStackOverflowされません)。

VLAを使用すると、メモリを動的に割り当て、追跡し、解放する必要がなくなりますが、スタックに収まるより多くの値をdouble格納してください。以下は、VLAを有効なオプションにする100,000またはそれ以下の値があると想定しています。

最初に、rowcolの値をファイルからどのようにピックオフ(読み取り)しますか? fgetsは、ライン指向入力の方がはるかに好ましい方法ですが、fprintfへの1回のコールでrowcolの両方を実際に取得して、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 "以下)rowcol値を持つ

、あなたは今まで、バッファのサイズをすることができますファイル内の残りの行のそれぞれを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行の数が読み込まれ、変換されるまで繰り返す。あなたはrowcol値の価値を読んだ後は必要に応じて、あなたの行列を使用することができ、

/* 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つの答えで説明したように、動的メモリ割り当てを使用することもできます。

関連する問題