我编写了一个函数,该函数读取二进制文件中的struct中的double值,然后计算该值,然后将计算出的double值写入二进制文件中。
结构为:
struct logData{
long logId;
char logDate[11];
char logNote[20];
double charge;
double total;
};
读取和修改数据charge
的功能是:
long size = sizeof(struct logData);
void update(FILE* fp, int n){
fseek(fp,(n-1)*size, SEEK_SET);
struct logData thisLogData;
fread(&thisLogData,size,1,fp);
long offset = sizeof(thisLogData.logId)+sizeof(thisLogData.logNote)+ sizeof(thisLogData.logDate);
double oldCharge = thisLogData.charge;
scanf("%lf", &thisLogData.charge);
fseek(fp, -size+offset, SEEK_CUR);
fwrite(&thisLogData.charge, sizeof(thisLogData.charge), 1, fp);
fclose(fp);
}
很多结构:logData
存储在二进制文件中。参数:n
代表logData
的位置。
我成功读出了charge
(函数oldCharge
中的update()
)的先前值。费用的初始值为20,我在update
函数中输入40。成功写入后,我读取了charge
的值,发现它既不是20也不是40,而是一个奇怪的32.55(我保留了两位小数)。
我尝试修改logDate
,并且logNote
可以被成功修改(当然offset
是不同的)。只有双值charge
和total
会有奇怪的结果。
原因是什么?
答案 0 :(得分:4)
您阅读了完整的 logData ,可以修改read元素,然后将其全部写入,可能是您有填充问题,因此计算出的偏移量是错误的
chrome.runtime.onMessage.addListener(
(request, sender, sendResponse) => {
chrome.tabs.create({url: "example.com"}, tab => {
chrome.tabs.executeScript(tab.id, {code: var x = 10; x}, function (result) {
sendResponse(result);
});
});
});
否则使用 offsetof 仅写入 charge 的新值,而不读取元素:
bool update(FILE* fp, int n){
struct logData thisLogData;
if ((fseek(fp,(n-1)*size, SEEK_SET) == -1) ||
(fread(&thisLogData,size,1,fp) == 1)) {
??? indicate error ???
fclose(fp);
return false;
}
if (scanf("%lf", &thisLogData.charge) != 1) {
??? indicate error ???
fclose(fp);
return false;
}
fseek(fp,(n-1)*size, SEEK_SET);
return ((fwrite(&thisLogData,size,1,fp) != -1)
& (fclose(fp) != -1); /* not && because have to close in all cases */
}
注意:奇怪的是,该功能必须关闭文件但不要打开它,因此在此处不执行关闭操作更合逻辑
答案 1 :(得分:4)
long offset = sizeof(thisLogData.logId)+sizeof(thisLogData.logNote)+ sizeof(thisLogData.logDate);
这不是成员的偏移量。结构成员具有填充。使用offsetof
。
size_t offset = offsetof(struct logData, charge);
答案 2 :(得分:1)
您应该使用offsetof
来找出结构中某个字段的偏移量:
#include<stddef.h>
long offset = offsetof(struct logData, charge);
答案 3 :(得分:1)
我编写了一个函数,该函数读取二进制文件中struct中的double值,然后计算该值,然后将计算出的double值写入二进制文件中。
请注意,二进制文件本来就不可移植。如果要处理由同一C实现构建的另一个C程序在同一台计算机上创建的文件,那么您应该可以,但否则,编写者和阅读者都需要非常注意二进制兼容性问题
但是,即使在那种情况下,您的代码也做出了不安全的假设。结构构件(第一个构件除外)的偏移量不能保证与先前构件的大小之和相同。结构可能并且经常确实在成员之间以及最后一个成员之后包含填充,这将使您的计算陷入困境。
尽管可以计算结构成员的偏移量,包括在没有offsetof()
的旧C版本中,但在这种情况下,我建议通过将整个结构写回到文件中来完全避免此问题,而不只是一个成员:
fseek(fp, -size, SEEK_CUR);
fwrite(&thisLogData, size, 1, fp);