2

データをファイルに書き込んでから読み取るときに、3人でバイナリファイル(Code-Name-Sex)を作成しましたが、完全に機能します。

次の関数で、X人が持っているすべての情報(存在する場合)を読み取ってほしい。

構文:

#include <stdio.h>    

struct alu{
    int cod;
    char name[30]; //alu[0]="juan" alu[1]="pedro" alu[2]="leo"
    int sex;
};

int FSearch(char path[],char X[]) {
    char Name[30];

    FILE *arc;
    arc=fopen(path,"rb");
    fseek(arc,sizeof(int),SEEK_SET);

    while (fread(Name,sizeof(char[30]),1,arc)) {
        /*Here is when the errors happen..
        The next sentence tell me that A.name don't have 
        the name from the second time*/
        printf("%s and %s.",X,Name);

        if (strcmp(Name,X)==0) return 1;
        fseek(arc,2*sizeof(int),SEEK_CUR);
    }
    fclose(arc);

    return 0
}

int main(int argc, char **argv)
{
    char path[]="file.bin";

    printf("\n%d",FSearch(path,"pedro"));

    return 0;
}

出力は次のとおりです。

pedroとjuan.pedroと.pedroと。

0

つまり、それは名('juan')が見つかりましたが、2番目と3番目はそうではありません(pedroとleo)。

なにが問題ですか?

4

4 に答える 4

4

方法は次のとおりです。

fseek(arc,sizeof(int),SEEK_SET);

while (fread(Name,sizeof(char[30]),1,arc)) {        
    if (strcmp(A.name,X)==0) return 1;
    fseek(arc,2*sizeof(int),SEEK_CUR); //--> ERROR
}

あるべき姿は次のとおりです。

fseek(arc,sizeof(int),SEEK_SET);

while (fread(Name,sizeof(char[30]),1,arc)) {        
    if (strcmp(A.name,X)==0) return 1;
    fseek(arc,2*sizeof(int)+sizeof(char[2]),SEEK_CUR); //--> SOLVED
}

問題は、whileループ内で、2番目の引数である起点からオフセットするバイト数がfseek()呼び出しに渡されることでした。2つのINTをカウントしていましたが、2つのCHARはカウントしていませんでした(2番目の文字列に到達する前)。sizeof(char[30])呼び出し後、 32バイトが表示fread()されていますが、文字列には30バイトが割り当てられています。

なぜさらに2バイト移動する必要があるのですか?文字列の最後には予約済みのバイトがあるため(文字列の開始と終了を示すため)。例えば:

char a[10]="Example";

これをバイナリファイルに保存すると、このファイルのサイズは12バイトになります。

于 2012-08-01T19:42:24.987 に答える
1

freadループを通過するたびに、呼び出しの結果を出力します。ファイルでEOFをヒットしている最初のオブジェクトの後に賭けます。私の予測では、最初のfread呼び出しは1を返し、他の呼び出しは0を返します。

于 2012-08-01T01:32:54.483 に答える
0

バイナリファイルの形式がわかりません。あなたのコードは、バイナリファイルの名前が30文字しかないことを示しています。

    struct alu{
        int cod;
        char name[30]; //juan - pedro - leo
        int sex;
    };

この構造体のサイズは38バイトではありません。

構造サイズを確認してください。

printf("%d", sizeof(struct alu));

構造体のサイズは、コンパイラのオプションによって異なります。

バイナリ形式が次の形式の場合。

{ // 1st record
  cod = 10
  names[30] = "juan"
  sex = 1
}
{ // 2nd record
  cod = 20
  names[30] = "pedro"
  sex = 1
}
{ // 3rd record
  cod = 12
  names[30] = "leo"
  sex = 2
}

コードを参照してください。

#include <stdio.h>    

#pragma pack(push, 1) or 4 or 8 depend on your binary format.
    struct alu{
        int cod;
        char name[30]; //juan - pedro - leo
        int sex;
    };
#pragma pack(pop)


int FSearch(char path[],char X[]) {
    char Name[30];
    struct alu A;

    FILE *arc;
    arc=fopen(path,"rb");
    //fseek(arc,sizeof(char[30]),SEEK_SET);
    fseek(arc,0,SEEK_SET); // first record.

    //while (fread(Name,sizeof(char[30]),1,arc)) {
    while (fread(A,sizeof(A),1,arc)) {
        /*Here is when the errors happen..
        The next sentence tell me that A.name don't have 
        the name from the second time*/
        printf("%s and %s.",X,A.name);

        if (strcmp(A.name,X)==0) {
            printf("Information of %s:\n",X);
            //fshow_str(A);
            fclose(arc);
            return 1; // found
        }
    }
    fclose(arc);
    return 0; // not found
}

int main(int argc, char **argv)
{
    char path[]="file.bin";

    printf("\n%d",FSearch(path,"pedro"));

    return 0;
}

タラのサイズはコンパイラのオプションによって異なります!!!

int FSearch(char path[],char X[]) {
    char Name[30];
    struct alu A;

    FILE *arc;
    arc=fopen(path,"rb");
    fseek(arc,0,SEEK_SET); // first record.

    //while (fread(Name,sizeof(char[30]),1,arc)) {
    while (1) {
        //if ( -1 == fseek(arc,4,SEEK_CUR)) // Important!!! case structure pack(4) for skip cod or
        //    break;
        if ( -1 == fseek(arc,8,SEEK_CUR)) // Important!!! case structure pack(8) for skip cod
            break;

        if (!fread(Name,sizeof(Name),1,arc))
            break;

        A.name = Name;

        /*Here is when the errors happen..
        The next sentence tell me that A.name don't have 
        the name from the second time*/
        printf("%s and %s.",X,A.name);

        if (strcmp(A.name,X)==0) {
            printf("Information of %s:\n",X);
            //fshow_str(A);
            fclose(arc);
            return 1; // found
        }
    }

        //if ( -1 == fseek(arc,4,SEEK_CUR)) // Important!!! case structure pack(4) for skip sex or
        //    break;
        if ( -1 == fseek(arc,8,SEEK_CUR)) // Important!!! case structure pack(8) for skip sex
            break;

    fclose(arc);
    return 0; // not found
}

バイナリファイルと構造体は4バイトで整列されます。

// Attention! pragma pack(push, 4) needs!!!
// Your now running machine is 32 bits system.
// This source code will invoke addressing fault 64 bits NON Intel processor.
#pragma pack(push, 4) // align 4 bytes.
    struct alu{
        int cod; // Integer type. 4 bytes on 32bits system. but 8 bytes on 64 bits system. 
                 // I recommend using "long" type. "long" type is 4 bytes on any system.
        char name[30]; //juan - pedro - leo
        int sex; // also, Integer type.
    };
#pragma pack(pop)

int FSearch(char path[],char X[]) {
    char Name[30];
    struct alu A;

    FILE *arc;
    arc=fopen(path,"rb");
    fseek(arc,0,SEEK_SET); // first record.

    //while (fread(Name,sizeof(char[30]),1,arc)) {
    while (1) {
        if ( -1 == fseek(arc,4,SEEK_CUR)) // Skip "cod" 4 bytes.
            break;
        if (!fread(Name,sizeof(Name),1,arc)) // Read "name" 30 bytes.
            break;
        if ( -1 == fseek(arc,2,SEEK_CUR)) // Skip "name"'s aligned 2 bytes.
            break;

        A.name = Name;

        /*Here is when the errors happen..
        The next sentence tell me that A.name don't have 
        the name from the second time*/
        printf("%s and %s.",X,A.name);

        if (strcmp(A.name,X)==0) {
            printf("Information of %s:\n",X);
            //fshow_str(A);
            fclose(arc);
            return 1; // found
        }
    }

    if ( -1 == fseek(arc,4,SEEK_CUR)) // Skip "sex" 4 bytes.
       break;

    fclose(arc);
    return 0; // not found
}
于 2012-08-01T02:08:30.220 に答える
-1

printfmain()印刷されたの戻りFSearch()、結果が見つかったかどうかを確認したい場合は、少なくともブール値を返す必要があります。FSearch()

于 2012-08-01T01:23:37.263 に答える