此算法不起作用

时间:2012-08-01 01:19:54

标签: c data-structures binaryfiles

当我将数据写入文件然后我读取它们时,我创建了一个包含三个人(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')但第二个和第三个名字不是(pedro和leo)。

有什么问题?

4 个答案:

答案 0 :(得分: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循环中第二个参数,从原点偏移的字节数,传递给fseek()调用。它计算两个INT而不是两个CHAR(在到达第二个字符串之前)。您可以在sizeof(char[30])调用后看到fread(),它显示32个字节,但为字符串分配了30个字节。

为什么要再移动两个字节?因为任何字符串都在其末尾,保留字节(用于指示字符串的开头和结尾)。 e.g:

char a[10]="Example";

如果将其保存为二进制文件,则此文件的大小为12个字节。

答案 1 :(得分:1)

我会在每次循环中打印fread调用的结果。我在第一个对象上打赌你在文件上击中了EOF。我的预测是第一个fread调用返回1,其他调用返回0.

答案 2 :(得分: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;
}

cod大小取决于编译器OPTION !!!

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
}

答案 3 :(得分:-1)

printf中的{p> main()打印了FSearch()返回值,如果您想查看结果是否已找到,则至少应返回一个bool值在FSearch()