3

現在、ディスクから構成ファイルを読み取り、構造を設定する関数を更新することを任されています。

static int LoadFromFile(FILE *Stream, ConfigStructure *cs)
{
  int tempInt;

   ...

  if ( fscanf( Stream, "Version: %d\n",&tempInt) != 1 )
  {
    printf("Unable to read version number\n");
    return 0;
  }
  cs->Version = tempInt;
   ...

}

構成をディスクに書き込むことをバイパスし、代わりにメモリに直接渡すことができるようにするもので、これとほぼ同等です。

static int LoadFromString(char *Stream, ConfigStructure *cs)

いくつかの注意事項:

  • 現在の LoadFromFile 関数は信じられないほど高密度で複雑で、下位互換性のある方法で構成ファイルの数十のバージョンを読み取るため、全体的なロジックの複製が非常に面倒です。
  • 構成ファイルを生成する関数とそれを読み取る関数は、古いシステムのまったく異なる部分に由来するため、データ構造を共有しないため、それらを直接渡すことはできません。ラッパーを作成することもできますが、ここでも、下位互換性のある方法で渡された構造を処理する必要があります。
  • ファイルを文字列として (上記のプロトタイプのように) そのまま渡し、すべての fscanf を sscanf に変換したいという誘惑にかられますが、ポインタのインクリメント (および潜在的にはバッファ オーバーラン エラーの処理) を手動で処理する必要があります。
  • これは C のままにしておく必要があるため、ストリームのような C++ 機能はここでは役に立ちません

より良いオプションがありませんか?ディスク上ではなくメモリ内の場所を実際に指す FILE * を作成する方法はありますか? ポインタ、提案、またはその他のヘルプは大歓迎です。

4

3 に答える 3

3

構造体を渡すことができず、データを文字列として渡す必要がある場合は、ファイルではなく文字列から読み取るように関数を微調整できるはずです。あなたが説明したように関数が複雑な場合は、変換fscanf->sscanfがおそらく最も簡単な方法です。

上記の関数プロトタイプを使用したアイデアを次に示します。データ文字列全体を (何も処理せずに) 読み込み、ローカル バッファーに格納します。こうすることで、ファイルの場合と同じようにコードがデータにランダムにアクセスできるようになり、バッファ オーバーランの予測と回避が容易になります。malloc適切なサイズのバッファーを作成することから始めて、データをそこにコピーし、realloc必要に応じてより多くのスペースを確保します。データ バッファー全体のローカル コピーを取得したら、それをスキャンして必要なデータを抽出します。

'\0'文字が有効な入力である場合、これは注意が必要です。その場合、これが入力文字列の最後であるか、単なるゼロ バイトであるかをテストするロジックを追加する必要があります (データ バッファーの特定の形式によっては困難です)。

于 2010-03-15T22:06:06.770 に答える
2

ファイルデータをメモリに保持しようとしているので、共有メモリを使用できるはずです。POSIX 共有メモリは、実際にはマップされたメモリのバリエーションです。共有メモリ オブジェクトは、必要に応じてmmap()を使用してプロセス アドレス空間にマップできます。共有メモリは通常、IPC メカニズムとして使用されますが、状況に応じて使用できるはずです。

次のコード例では、POSIX 共有メモリ ( shm_open() & shm_unlink() ) を a と共に使用しFILE *て、共有メモリ オブジェクトにテキストを書き込み、それを読み戻します。

#include <fcntl.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>

#define MAX_LEN 1024

int main(int argc, char ** argv)
{
    int    fd;
    FILE * fp;
    char * buf[MAX_LEN];

    fd = shm_open("/test", O_CREAT | O_RDWR, 0600);

    ftruncate(fd, MAX_LEN);

    fp = fdopen(fd, "r+");

    fprintf(fp, "Hello_World!\n");

    rewind(fp);

    fscanf(fp, "%s", buf);

    fprintf(stdout, "%s\n", buf);

    fclose(fp);

    shm_unlink("/test");

    return 0;
}

注: -lrtLinux で gcc を使用してこの例をコンパイルするときは、リンカーに渡す必要がありました。

于 2010-03-16T17:00:22.607 に答える
1
  • mkstemp()一時ファイルの作成に使用します。引数として取り、それをchar *ファイル名のテンプレートとして使用します。ただし、ファイル記述子が返されます。

  • を使用しtmpfile()ます。を返しますがFILE *セキュリティ上の問題があり、文字列を自分でコピーする必要があります。

  • 使用するmmap()( Beej's Guideヘルプ)

于 2010-03-15T21:53:14.440 に答える