当文件未按预期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
我想到了一些解决方案,但它们相当复杂,我想知道它们是否可以做得更好
我应该有一个结构和文件来记录联系人结构/文件中未使用的变量的一些统计信息吗?尝试以下方法,线性复杂度,如果没有联系人,它将初始化为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 );
}