2016-04-23 25 views
-1

ファイルから数値を取得しようとしています。私は別のアプローチを試みたが、私は次のコードを思い付いた:数値をファイルから配列に読み込む

int* readFileWithNumbers() 
{ 
    FILE *file = fopen("number_list.txt", "r"); 
    int*integers = malloc(sizeof(int) * 240);; 

    int i=0; 
    int num; 
    while(fscanf(file, "%d", &num) > 0) { 
     integers[i] = num; 
     i++; 
    } 
    fclose(file); 
    return integers; 
} 

私の入力ファイルの形式は次のとおりです。

106 
-18 
248 
-237 
148 
142 
38 
-189 
59 
-120 
-219 
-172 
237 
-257 
-154 
-267 
-34 
-292 
239 
-182 
-243 
-115 
-26 
-238 
298 

あなたは私がここで間違ってやって、私を導いてくださいことはできますか?

+1

いいですね。それは動作しますか? –

+1

あなたは何か間違っているという印象を与えますか?それは完全にうまくいくようです。 – Dolda2000

+0

ファイル内の整数の数をstatで得ることができます。そうすれば、より多くの/ mallocの部屋で240以上の整数を読み取ることができます。 'struct stat st;のようなものです。 stat(ファイル名:&st); int numOfIntegers = st.st_size; ' – Turtle

答えて

1

一般的に、あなたはあなたの関数にメモリmaxの現在の割り当てにFILE *ポインタ、arrayindexへのポインタ、ポインタを渡すことになるでしょう。あなたの関数がファイルから配列に値を読み取ることができるように、現在の割り振りサイズと比較するために現在のインデックスの数を保持します。値の数が現在の割り振りを超えた場合はreallocになります。最後に、あなたのindexとあなたmax割り当ての両方にポインタを使用しての仮想により、いずれかへの変更は、一般的にmain()これらの短い例のために(バックあなたの呼び出し元の関数ですぐに利用できます。

が一緒にすべてのそれらの作品を置く、あなたが行うことができます以下のようなもの:

/* read array of unknown size int 'a' from 'fp' */ 
int *readarr (FILE *fp, int *a, size_t *idx, size_t *max) 
{ 
    int tmp; 

    if (!a) /* if a not allocated -- allocate/validate */ 
     if (!(a = calloc (1, *max * sizeof *a))) { 
      fprintf (stderr, "readarr() virtual memory exhausted.\n"); 
      exit (EXIT_FAILURE); 
     } 

    while (fscanf (fp, " %d", &tmp) == 1) {  /* for each int in file */ 
     if (*idx == *max) {      /* check idx and max */ 
      void *ap = realloc (a, 2 * *max * sizeof *a); /* realloc */ 
      if (!ap) {  /* validate realloc success */ 
       fprintf (stderr, "realloc() error: memory exhausted.\n"); 
       break;  /* if failure, return with exising data */ 
      } 
      a = ap;  /* assign new mem block, zero new mem */ 
      memset (ap + *max * sizeof *a, 0, *max * sizeof *a); 
      *max *= 2; /* update allocation size */ 
     } 
     a[(*idx)++] = tmp; /* add int to array, update index */ 
    } 

    return a; /* return array */ 
} 

注:機能は、必要に応じて再割り当て/割り当てられた配列、またはNULLを受け入れ、割り当てられますしかし、あなたの配列aの値が原因に静的に宣言された配列にすることはできません。に電話するが発生します。さらに、arrayに関数からの戻り値をmain()に割り当てる必要があります。 'a'はそもそもNULLある、またはreallocが発生した場合、新しいポインタアドレスが返された場合。)

realloc後に新しいメモリをゼロに必須ではありませんが、それはあなた場合は初期化されていない値からの不用意な読み取りを防ぐことができます後で最後に格納された値のインデックスよりも大きいインデックスで配列を反復処理します。

また、現在の再割り当てスキームは、reallocを呼び出すたびにメモリ量を2倍にします。必要に応じて少しずつ追加するか、または必要なだけ追加するかを選択できます。それと

、短い例では、すべて一緒にそれを置くことが考えられます。

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

#define MAXI 64 

int *readarr (FILE *fp, int *a, size_t *idx, size_t *max); 

int main (int argc, char **argv) { 

    int *array = NULL;     /* pointer to array  */ 
    size_t i = 0, n = 0, maxi = MAXI; /* index, initial elements */ 
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; 

    if (!fp) { /* valildate file pointer */ 
     fprintf (stderr, "error: file open failed. '%s'\n", 
       argc > 1 ? argv[1] : "stdin"); 
     return 1; 
    } 

    array = readarr (fp, array, &n, &maxi); /* read values from file */ 

    if (fp != stdin) fclose (fp);   /* close file */ 


    for (i = 0; i < n; i++)     /* print array */ 
     printf (" array[%3zu] : %d\n", i, array[i]); 

    free (array); /* free memory */ 

    return 0; 
} 

/* read array of unknown size int 'a' from 'fp' */ 
int *readarr (FILE *fp, int *a, size_t *idx, size_t *max) 
{ 
    int tmp; 

    if (!a) /* if a not allocated -- allocate/validate */ 
     if (!(a = calloc (1, *max * sizeof *a))) { 
      fprintf (stderr, "readarr() virtual memory exhausted.\n"); 
      exit (EXIT_FAILURE); 
     } 

    while (fscanf (fp, " %d", &tmp) == 1) {  /* for each int in file */ 
     if (*idx == *max) {      /* check idx and max */ 
      void *ap = realloc (a, 2 * *max * sizeof *a); /* realloc */ 
      if (!ap) {  /* validate realloc success */ 
       fprintf (stderr, "realloc() error: memory exhausted.\n"); 
       break;  /* if failure, return with exising data */ 
      } 
      a = ap;  /* assign new mem block, zero new mem */ 
      memset (ap + *max * sizeof *a, 0, *max * sizeof *a); 
      *max *= 2; /* update allocation size */ 
     } 
     a[(*idx)++] = tmp; /* add int to array, update index */ 
    } 

    return a; /* return array */ 
} 

例入力100のInt

$ cat dat/100int.txt 
27086 
29317 
32736 
... 
16892 
8270 
6444 

使用例/出力

$ ./bin/fscanf_array_dyn dat/100int.txt 
array[ 0] : 27086 
array[ 1] : 29317 
array[ 2] : 32736 
array[ 3] : 3356 
... 
array[ 97] : 16892 
array[ 98] : 8270 
array[ 99] : 6444 

メモリエラーチェック

メモリに動的に割り当てられるコードでは、割り当てられたメモリブロックに関する2つの責任があります。(1)常にメモリブロックの開始アドレスへのポインタを保持するので、 )、不要になったときに解放することができます。

メモリエラーチェックプログラムを使用して、割り振られたメモリブロックの外側または外側に書き込まれていないことを確認し、初期化されていない値の読み込みまたはベースを試み、最後に解放したことを確認することが不可欠ですあなたが割り当てたすべてのメモリ。

Linuxの場合valgrindが通常の選択です。新しいメモリブロックを誤用する方法はたくさんあります。メモリエラーチェッカーを使用すると、問題を特定して、segfaultを介して問題を発見するのではなく、割り当てたメモリの適切な使用を検証できます。すべてのプラットフォームに同様のメモリチェッカーがあります。それらはすべて使いやすく、プログラムを実行するだけです。

$ valgrind ./bin/fscanf_array_dyn dat/100int.txt 
==7273== Memcheck, a memory error detector 
==7273== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. 
==7273== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info 
==7273== Command: ./bin/fscanf_array_dyn dat/100int.txt 
==7273== 
array[ 0] : 27086 
array[ 1] : 29317 
array[ 2] : 32736 
... 
array[ 97] : 16892 
array[ 98] : 8270 
array[ 99] : 6444 
==7273== 
==7273== HEAP SUMMARY: 
==7273==  in use at exit: 0 bytes in 0 blocks 
==7273== total heap usage: 3 allocs, 3 frees, 1,336 bytes allocated 
==7273== 
==7273== All heap blocks were freed -- no leaks are possible 
==7273== 
==7273== For counts of detected and suppressed errors, rerun with: -v 
==7273== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1) 

必ず確認すべてのヒープブロックが解放された - 何の漏れがERROR概要可能と同様に重要ではない:0エラーを0コンテキストから。

ご質問がありましたら教えてください。メモリの基本的な割り当てと解放は、Cの多くの基礎となります。コードを完全に理解するために時間をとってから、後であなたの机に頭を打つのが良いでしょう...あなたのコーディングで幸運を祈る。

+0

このような詳細な回答をいただきありがとうございます。あなたのコードを理解していて、あなたは非常にうまく説明しました。あなたのコードを使用しましたが、今は正しい値です。 – user3057437

+0

Cで学ぶことがたくさんあります。私が今まで読んだことのあるすべてのCリファレンスで、あなたが実際にそれを手に入れ始める唯一の方法は、微妙な点に遭遇して助けを呼ぶほどのコードを書いて、ついに電球が点灯します。コードの中のどの点についてもご質問がありましたら教えてください。私はさらに詳しく説明します。 –

関連する問題