Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当文件未按预期100%填充时,无法使用C从二进制文件读取结构_C_File_Struct - Fatal编程技术网

当文件未按预期100%填充时,无法使用C从二进制文件读取结构

当文件未按预期100%填充时,无法使用C从二进制文件读取结构,c,file,struct,C,File,Struct,我有这个文件,我试图从中读取一个简单的通讯录使用的结构的联系人 typedef struct contact{ char name[80]; char surname[80]; char cellnumber[20]; float length; int contactid; }contact; 我使用这个函数,我这样调用它,所以它会读取它200次(const int MAXCONTACT=200;) 这种代码的唯一问题是,当没有200个联系人时,函数将

我有这个文件,我试图从中读取一个简单的通讯录使用的结构的联系人

typedef struct contact{
    char name[80];
    char surname[80];
    char cellnumber[20];
    float length;
    int contactid;
}contact;
我使用这个函数,我这样调用它,所以它会读取它200次(
const int MAXCONTACT=200;

这种代码的唯一问题是,当没有200个联系人时,函数将不会返回联系人,因为无法找到联系人ID

我想到了一些解决方案,但它们相当复杂,我想知道它们是否可以做得更好

  • 制作一个像真正的安装程序一样创建文件的安装程序,然后创建200个变量为null的未声明联系人

  • 检查程序是否第一次运行,并仅在程序本身中执行上述操作

  • 如果未找到联系人ID,则平等地退出搜索循环,并返回一个未清除的联系人,所有变量均设置为null

  • 写了这篇文章后,我想到了三个问题:

    以下哪一项是最好的或最容易使用的

    返回未清除的联系人是否安全?(我必须记住,我必须使用联系人:modefy、print、print all contacts)


    我应该有一个结构和文件来记录联系人结构/文件中未使用的变量的一些统计信息吗?

    尝试以下方法,线性复杂度,如果没有联系人,它将初始化为0

    /* initialize memory */
    memset(person, 0, MAXCONTACT * sizeof(contact0);
    
    /* open the file */
    data=fopen("data.bin","rb");
    
    /* get the file size */
    fseek(data, 0L, SEEK_END);
    
    /* don't read more than your allocated array can contain */
    int size = max(ftell(data), MAXCONTACT * sizeof(contact));
    
    /* seek to the beginning of the file */
    fseek(fp, 0L, SEEK_SET);
    
    /* populate the array */
    fread(&person,size,1,data);
    
    /* close the file */
    fclose(data);   
    

    试试这个。它返回数据读取工作或失败的指示,如果工作则返回0,如果不工作则返回1(请注意,我将“I”更改为unsigned,因为无法正确处理负值):

    int-load(未签名的int-i,结构联系人*person)
    {
    int数据;
    结构统计某人;
    数据=打开(“data.bin”,仅限ordu);
    如果(数据==-1)返回(-1);
    /*使用fstat()告诉文件有多大*/
    fstat(数据和sb);
    /*sb.st_size现在保存文件中的字节数
    它需要至少与(i+1)个联系人一样大*/
    如果(sb.st_尺寸<((1+i)*尺寸(*人)))
    {
    关闭(数据);
    返回(-1);
    }
    /*试图记录我*/
    lseek(数据,(i*sizeof(*人)),搜索集);
    ssize_t bytesRead=读取(数据、人员、大小(*人员));
    /*如果读取没有获得足够的字节,则返回-1*/
    如果(字节数!=sizeof(*人))
    {
    关闭(数据);
    返回(-1);
    }
    关闭(数据);
    返回(0);
    }
    
    这将允许调用方知道读取是否成功


    您必须更改代码以传递要填写的联系人结构的地址,但您将知道读取是否有效。

    无论选择何种方法,始终检查
    fread
    结果。至于“返回未清除的联系人是否安全?”,当然,如果你知道如何处理的话。一切都在你的控制之下。。打开文件并搜索id,然后关闭每个联系人id??有点。。“笨拙,说话温和。”尤金尼什。这是真的,我可以写一些if来检查variabiles@EugeneSh. 那我该怎么做呢?打开文件,逐个读取联系人,填充数组,关闭文件。
    SEEK\u SET
    做什么呢?我对max没有明确的引用!fseek()更改从输入流读取的下一个字符的位置。命令fseek(data,0L,SEEK\u END);将位置移动到流的末尾(以便使用ftell()获得流的大小)fseek(fp,0L,SEEK_SET);将位置倒回到流的开头,因为您希望将流读取到数组中。为了解决未定义的引用,include math.h:#include这是我的错误,max在math.h中没有定义。以下是如何定义此宏:#定义max(a,b)(((a)>(b))?(a):(b))
    contact load(int i){
        struct contact person;
        FILE *data;
        data=fopen("data.bin","rb");
        do{
            fread(&person,sizeof(contact),1,data);
        }while(person.contactid!=i);
        fclose(data);
        return person;
    }
    
    /* initialize memory */
    memset(person, 0, MAXCONTACT * sizeof(contact0);
    
    /* open the file */
    data=fopen("data.bin","rb");
    
    /* get the file size */
    fseek(data, 0L, SEEK_END);
    
    /* don't read more than your allocated array can contain */
    int size = max(ftell(data), MAXCONTACT * sizeof(contact));
    
    /* seek to the beginning of the file */
    fseek(fp, 0L, SEEK_SET);
    
    /* populate the array */
    fread(&person,size,1,data);
    
    /* close the file */
    fclose(data);   
    
    int load(unsigned int i, struct contact *person)
    {
        int data;
        struct stat sb;
        data=open("data.bin", O_RDONLY);
        if ( data == -1 ) return( -1 );
        /* use fstat() to tell how big a file is */
        fstat( data, &sb );
        /* sb.st_size now holds the number of bytes in the file
           it needs to be at least as big as ( i + 1 ) contacts */
        if ( sb.st_size < ( ( 1 + i ) * sizeof( *person ) ) )
        {
            close( data );
            return( -1 );
        }
        /* seek to record i */
        lseek( data, ( i * sizeof( *person ) ), SEEK_SET );
        ssize_t bytesRead = read( data, person, sizeof( *person ) );
        /* return -1 if the read didn't get enough bytes */
        if ( bytesRead != sizeof( *person ) )
        {
            close( data );
            return( -1 );
        }
        close(data);
        return( 0 );
    }