0

ここでバイナリ ファイルを処理する fwrite() と fread() に問題があるのは私のソース コードです。現在、実行すると「jake」が返されますが、他には何も返されません。バイナリ文字を処理するためにダンプ バッファ関数を作成するように言われました。さらに、ここにはテキスト ファイルもあり、info.bin という空のファイルに書き込んでいます。PSzipをintとして保存するのは悪い習慣であることは知っていますが、これは私の教授が求めているものです。

ファイル:

mike|203-376-5555|7 Melba Ave|Milford|CT|06461
jake|203-555-5555|8 Melba Ave|Hartford|CT|65484
snake|203-555-5555|9 Melba Ave|Stamford|CT|06465
liquid|203-777-5555|2 Melba Ave|Barftown|CT|32154

コード:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LINE 80
#define RECORDS 10


struct info{
  char name[100];
  char number[100];
  char address[100];
  char city[100];
  char state[100];
  int zip;
};

void dump_buffer(void *buffer, int buffer_size)
{
  int x;

  for(x = 0; x < buffer_size; x++)
  {
    printf("%c",((char *)buffer)[x]);
  }
}

int i, j, seeker;

int main(int argc, char* argv[])
{
  char *buffer;

  struct info input_records[RECORDS];
  int nrecs = 0;
  unsigned long fileLen;
  char line[LINE];
  FILE *fp = NULL;
  FILE *fpbin = NULL;
  FILE *fpread = NULL;



  if (argc != 2) 
  {
    printf ("ERROR: you must specify file name!\n");
    return 1;
  }
  /* Open file */
  fp = fopen(argv[1], "r");
  if (!fp) 
  {
    perror ("File open error!\n");
    return 1;
  }

  while (!feof (fp)) {
    fgets(line, sizeof(line),fp);
    char* tok =  strtok(line, "|");

    while(tok != NULL)
    {
      strcpy(input_records[nrecs].name, tok);
      tok = strtok(NULL, "|");
      strcpy(input_records[nrecs].number, tok);
      tok = strtok(NULL, "|");
      strcpy(input_records[nrecs].address, tok);
      tok = strtok(NULL, "|");
      strcpy(input_records[nrecs].city, tok);
      tok = strtok(NULL, "|");
      strcpy(input_records[nrecs].state, tok);
      tok = strtok(NULL, "|");
      input_records[nrecs].zip = atoi(tok);
      tok = strtok(NULL, "|");
    }
    nrecs++;
  }




  fpbin = fopen("info2.bin", "wb");
  if (!fp) 
  {
    perror ("File open error!\n");
    return 1;
  }

  for(i = 0; i < 4; i++)
  {

   fwrite(&input_records[i], sizeof(struct info), 200000, fpbin);

  }

  fclose(fpbin);



  fpread = fopen("info2.bin", "rb");



  fseek(fpread, 0, SEEK_END);
  fileLen = ftell(fpread);
  fseek(fpread, 0, SEEK_SET);

  buffer = (char *)malloc(sizeof(struct info));

  fread(buffer, fileLen, 1, fpread);


  dump_buffer(buffer, sizeof(buffer));

  fclose(fpread);

  fclose(fp);
  free(buffer);
return 0;
}
4

1 に答える 1

4
fwrite(&input_records[i], sizeof(struct info), 200000, fpbin);

のアドレスから始まるバイトをファイルfwriteに書き込むように指示しました。に割り当てられているメモリをはるかに超えたメモリにアクセスするため、動作は未定義ですが、セグメンテーション違反が発生する可能性は低くありません。どうやらそれがあなたのためにクラッシュしなかったことに、私は実際に驚いています。200000 * sizeof(struct info)input_records[i]input_records

buffer = (char *)malloc(sizeof(struct info));

fread(buffer, fileLen, 1, fpread);

fileLensize のバッファにバイトを読み込もうとしていますsizeof(struct info)。の場合fileLen > sizeof(struct info)、これも未定義の動作であり、fileLenが十分に大きい場合、クラッシュする可能性があります。

毎回size のオブジェクトをfwrite 1 つ許可する必要があり、読み取るバッファーにバイトを割り当てる (または size のチャンクで読み取る) 必要があります。そして、との戻り値をチェックして、目的のデータの書き込み/読み取りに成功したかどうかを確認し、失敗を適切に処理する必要があります。sizeof(struct info)fileLensizeof(struct info)fwritefread

fpbin = fopen("info2.bin", "wb");
if (!fp) 
{

FILE*あなたはここで間違ったものをチェックしますが、まったくチェックfpreadしません。

さらに、間違ったカウントを に渡しますdump_buffer

dump_buffer(buffer, sizeof(buffer));

bufferchar*であり、通常は 4 バイトまたは 8 バイトsizeof bufferの のサイズです。char*そこに割り当てられたバッファのサイズを渡す必要があります。

そして、元のファイルを読み込むと、

while (!feof (fp)) {
    fgets(line, sizeof(line),fp);

feof(fp)ファイルの終わりに達したときに読み取りが試行された後にのみ true になるため、ループ条件を次のように変更する必要があります。

while(fgets(line, sizeof line, fp) != NULL) {

最後に、入力ファイルに不正なデータや長すぎる行が含まれている場合、トークン化コードはひどく失敗します。またはに aNULLを渡さないように、そこにもチェックを追加する必要があります。strcpyatoi

于 2012-10-01T20:06:50.127 に答える