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



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

typedef struct contact{
char name[80];
char surname[80];
char cellnumber[20];
float length;
int contactid;
}contact;

我使用这个函数,我这样调用它,所以它读取它200次(const int MAXCONTACT = 200;)。

for(i2=0;i2<MAXCONTACT;i2++)
person[i2]=load(i2);

这是给定某个ID(可变i)的函数,返回具有相同I:的联系人

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;
}

这种代码的唯一问题是,当没有200个联系人时,该功能不会返回联系人,因为找不到联系人ID。

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

  1. 制作一个安装程序,像真正的安装程序一样创建文件,然后使用等于null的变量创建200个未声明的联系人。

  2. 检查程序是否是第一次运行,并且只在程序本身中执行与上面相同的操作。

  3. 如果没有找到联系人ID,则同样退出搜索循环,并返回一个未清除的联系人,其中所有变量都设置为null。

写完这篇文章后,脑海中浮现出三个问题:

其中哪一个是最好的还是最容易使用的?

退回未清除的联系人安全吗?(我必须记住,我必须使用联系人:模式化,打印,打印所有联系人)

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

尝试以下方法,线性复杂性,如果没有联系人,它将初始化为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"更改为无符号,因为没有办法正确处理负值):

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 );
}

这将允许调用者知道读取是否成功。

你必须更改代码才能传递你想要填写的联系人结构的地址,但你会知道读取是否有效。

最新更新