0

私はこの割り当てに取り組んでいます。そこでは、「レコード」を読み込んでファイルに書き込み、後でそれらを読み取ったり見つけたりする必要があります。プログラムを実行するたびに、ユーザーは新しいレコードを書き込むか、古いレコードを読み取るか(名前または#のいずれかで)を決定できます。

ファイルはバイナリです。その定義は次のとおりです。

typedef struct{
        char * name;
        char * address;
        short addressLength, nameLength;
        int phoneNumber;
    }employeeRecord;
    employeeRecord record;

プログラムの動作方法では、構造、名前、アドレスの順に格納されます。名前とアドレスは動的に割り当てられるため、最初に構造を読み取って名前とアドレスのサイズを見つけ、それらにメモリを割り当ててから、そのメモリに読み込む必要があります。

デバッグの目的で、現在2つのプログラムがあります。私は自分のファイル書き込みプログラムとファイル読み取りを持っています。

私の実際の問題はこれです。私が書いたファイルを読むとき、私は構造を読み、電話番号を印刷してそれが機能することを確認し(これは正常に機能します)、次に名前を読みます(これでレコードを使用できるようになります)。適切な値も報告するnameLength)。ただし、Freadは使用可能な名前を返さず、空白を返します。

ファイルに名前を正しく書き込んでいないか、正しく読み取っていないという2つの問題があります。これが私がファイルに書き込む方法です:ここでfpはファイルポインタです。record.nameは適切な値であるため、record.nameLengthも適切な値です。また、ヌルターミネータを含む名前を書いています。(例:'Jack \ 0')

fwrite(&record,sizeof record,1,fp);
fwrite(record.name,sizeof(char),record.nameLength,fp);
fwrite(record.address,sizeof(char),record.addressLength,fp);

そして、ファイルを閉じます。これが私がファイルを読む方法です:

fp = fopen("employeeRecord","r");


fread(&record,sizeof record,1,fp);
printf("Number: %d\n",record.phoneNumber);


char *nameString = malloc(sizeof(char)*record.nameLength);

printf("\nName Length: %d",record.nameLength);
fread(nameString,sizeof(char),record.nameLength,fp);
printf("\nName: %s",nameString);

そこにいくつかのデバッグ機能があることに注意してください(名前の長さと数、どちらも正しい)。だから私はファイルが正しく開かれたことを知っています、そして私は名前の長さをうまく使うことができます。それでは、なぜ私の出力が空白、改行、またはそのようなものなのですか?(出力は名前だけです:その後は何もありません、そしてプログラムはうまく終了します)

助けてくれてありがとう。

4

3 に答える 3

1

私はあなたのコードを試しました、そしてそれはうまくいきました。順番に、ここに出力、ファイルの16進ダンプ、およびコンパイル用に作成されたソースがあります。

更新:stdinまたはコマンドライン引数から名前とアドレスを読み取るようにコードを更新しました。

prompt$ g++ -g -Wall -o test_records test_records.cpp
prompt$ echo -e "Test User\nSomeplace, Somewhere" | ./test_records
sizeof(employeeRecord) = 24
Number: 5551212

Name Length: 9
Name: Test User

prompt$ hexdump -C employeeRecord 
00000000  90 f7 bf 5f ff 7f 00 00  70 f7 bf 5f ff 7f 00 00  |..._....p.._....|
00000010  14 00 09 00 6c b4 54 00  54 65 73 74 20 55 73 65  |....l.T.Test Use|
00000020  72 53 6f 6d 65 70 6c 61  63 65 2c 20 53 6f 6d 65  |rSomeplace, Some|
00000030  77 68 65 72 65                                    |where|
00000035

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

typedef struct{
        char * name;
        char * address;
        short addressLength, nameLength;
        int phoneNumber;
    }employeeRecord;

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

#if 0
  // Commmand line arguments
  if (argc < 3)
    return 1;

  record.nameLength = strlen(argv[1]);
  record.name = (char *)malloc(sizeof(char)*(record.nameLength + 1));
  strncpy(record.name, argv[1], record.nameLength + 1);

  record.addressLength = strlen(argv[2]);
  record.address = (char *)malloc(sizeof(char)*(record.addressLength + 1));
  strncpy(record.address, argv[2], record.addressLength + 1);
#else
  // stdin
  char input[1024];

  fgets(input, sizeof(input), stdin);
  record.nameLength = strlen(input);
  record.name = (char *)malloc(sizeof(char)*(record.nameLength + 1));
  strncpy(record.name, input, record.nameLength + 1);

  fgets(input, sizeof(input), stdin);
  record.addressLength = strlen(input);
  record.address = (char *)malloc(sizeof(char)*(record.addressLength + 1));
  strncpy(record.address, input, record.addressLength + 1);
#endif

  record.phoneNumber = 5551212;

  FILE *fp = NULL;

  printf("sizeof(employeeRecord) = %lu\n", sizeof(employeeRecord));

  // Write
  fp = fopen("employeeRecord","w");
  fwrite(&record,sizeof(employeeRecord),1,fp);
  // Note: we're not including terminating NULLs.
  fwrite(record.name,sizeof(char),record.nameLength,fp);
  fwrite(record.address,sizeof(char),record.addressLength,fp);
  fclose(fp);

  // Read
  fp = fopen("employeeRecord","r");
  fread(&record,sizeof(employeeRecord),1,fp);
  printf("Number: %d\n",record.phoneNumber);

  char *nameString = (char *)malloc(sizeof(char)*(record.nameLength + 1));
  printf("\nName Length: %d",record.nameLength);
  fread(nameString,sizeof(char),record.nameLength,fp);
  nameString[record.nameLength] = '\0';
  printf("\nName: %s",nameString);
  printf("\n");

  fclose(fp);

  return 0;
}
于 2010-03-08T18:19:54.877 に答える
0

入力を追加したいのですが...メモリ構造をディスクにダンプしているので、データを保持するために使用されるポインタアドレスは、ダンプ前に確実に有効ですが、それらから読み取る場合、ポインタアドレスが無効になる可能性があります....文字ポインタに名前が表示されない理由を説明します...

于 2010-03-08T18:09:03.790 に答える
0

まず、ちょっとした問題です。sizeof(char)は必要ありません。定義上、常に1です。

空白の名前の出力について:出力をフラッシュするために、%sの後に改行が必要ですか?これを省略したときに奇妙な動作が見られましたが、使用しているプラ​​ットフォームを指定していません。プラットフォームのprintf()が奇妙に実装されている場合は、フォーマット文字列を印刷してフラッシュすることができますが、プログラムの終了時に名前自体がCライブラリのバッファに残ります。

また、ファイルとの間で構造体のようなバイナリデータのブロブを読み書きすることに満足することはありません。そうすることで、同じプラットフォームで書いたものだけを読み取ることをプログラムに約束していることを理解してください。たとえば、64ビットホストにファイルを書き込んだり、16ビット電子レンジコントローラーでファイルを読み戻したりすることはできませんでした。

于 2010-03-08T22:43:05.763 に答える