2

当我将数据写入文件然后读取它们时,我创建了一个包含三个人(代号-名称-性别)的二进制文件,它工作得很好,所以..

我希望下一个函数读取 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')但第二个和第三个不是(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
}

问题是第二个参数,即从原点偏移的字节数fseek(),在 while 循环中传递给调用。它计算了两个 INT,但没有计算两个 CHAR(在到达第二个字符串之前)。你可以看到调用sizeof(char[30])之后fread(),它显示了 32 个字节,但是 30 个字节分配给了字符串。

为什么还要再移动两个字节?因为任何字符串的末尾都有保留字节(用于指示字符串的开头和结尾)。例如:

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 回答