0

私は C で Linux に取り組んでおり、構造をファイルに書き込もうとしています。

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

struct stud{
    char name[20];
    char dept[20];  
    int id;
};

int main()
{
    FILE *fptr;
    int fwrt;
    struct stud s;

    printf("enter student name\n");
    scanf("%s",s.name);

    printf("enter student department\n");
    scanf("%s",s.dept);

    printf("enter student ID\n");
    scanf("%d",&s.id);

        fptr = fopen("tiger","wb");
        if(fptr == NULL){
            perror("error openning file :");
            exit(EXIT_FAILURE);
        }

        fwrt = fwrite(&s,sizeof(struct stud),1,fptr);
        if(fwrt == 0){
            perror("error writing file :");
            exit(EXIT_FAILURE);
        }

        // fprintf(fptr, "%d", s1->mark);

        if(fclose(fptr) == EOF){
            perror("error closing file :");
            exit(EXIT_FAILURE);
        }

}

出力: ファイルを開いて確認すると、次のようになります。

  • 名前ですが、追加の文字があります
  • 部門だが追加の文字がある
  • id ガベージ値を取得します。

この問題を解決する方法を教えてください。

4

3 に答える 3

1

出力: ファイルを開いて確認すると、次のようになります。

  • 名前は付けましたが、文字が追加されています
  • 部門を取得しましたが、追加の文字があります
  • id ガベージ値のようになりました。

fwriteファイルにバイトを書き込みますが、これらのsizeof(struct stud)バイトに何が含まれているかは気にしません。初期化していないためsnameおよびdept配列には未指定のデータが含まれ、入力によって上書きされなかったバイト (0 ターミネータを含む) はガベージ値を保持し、それらもファイルに書き込まれるため、 および の後に追加の文字が含まれますnamedept. はidバイナリ表現でファイルに書き込まれますが、それがエディターによってテキストとして解釈される (試みられる) と、ゴミのように見えます。

ただし、入力が配列の境界外に書き込まれるのを防ぐ必要があるため、0 ターミネータの場所を残して、最大 19 文字が 20 バイト配列にスキャンされるようにするのではなく、scanfフォーマット内の文字列の長さを制限する必要があります。 .%19s%s

于 2012-09-14T13:49:21.747 に答える
0

使用する

memset(&s, 0, sizeof(stud));

文字列に書き込む前に、最初にデータを無菌化して、印刷しようとしたときに表示されないようにします。

id が完全にガベージである理由は、scanf によってテキストとして保存されているにもかかわらず、バイナリとしてファイルに書き込むためです。また、文字列である必要があります。

また、バッファをこのように短くすると、誰かが 20 文字を超える名前や部門を入力すると、バッファ オーバーフローが発生する可能性があることにも注意してください。

于 2012-09-14T13:49:56.637 に答える
0

char[] の末尾に「\0」を追加して、データをシリアル化する必要があります。

しかし、バイナリモードでの fwrite は動的構造では便利ではありません.構造のフィールドを静的に宣言できる場合はより良いので、あなたの場合はそれが良いです.

scanf の代わりに、次のように fgets を使用することをお勧めします。

    #define MAX
    if (fgets(s.name, MAX, stdin) == NULL)
    {
         //do what you want here
    }
    if (fgets(s.dept, MAX, stdin) == NULL)
    {
         //do what you want here
    }
于 2012-09-14T13:48:59.207 に答える