不确定我的标题是否有意义,但是我想做的是从动态结构到文件的fwrite操作,但是使这种操作更困难的是我的结构是通过引用传递的,而且我不知道第一个参数的方式fwrite应该看起来像。这是代码的一部分:
void editData(FILE* fPtr, Car* carPtr[], int* size)
{
int number = 0;
printData(carPtr, size);
while(1)
{
if ((scanf("%d", &number) == 1) && (getchar() == '\n'))
{
if ((number > 0) && (number <= *size))
{
char make[15] = "", model[15] = "";
int year = 0;
double price = 0;
if (getUserInput(make, model, &year, &price) == 1)
{
strcpy((*carPtr+number-1)->make, make);
strcpy((*carPtr+number-1)->model, model);
(*carPtr+number-1)->year = year;
(*carPtr+number-1)->price = price;
fseek(fPtr, sizeof(Car) * number-1, SEEK_SET);
fwrite(**&carPtr[number-1]**, sizeof(Car), 1, fPtr);
}
这就是我从main调用此函数的方式:
FILE* db = NULL;
int choice = 0;
db = openDatabase(db);
Car* cr = NULL;
int size = 0;
loadData(db, &cr, &size);
while((choice = menuChoice()) != 5)
{
switch (choice)
{
case 1:
insertData(db, &cr, &size);
break;
case 2:
**editData(db, &cr, &size);**
break;
case 4:
printData(&cr, &size);
break;
}
}
free(cr);
fclose(db);
}
对结构的内存分配发生在不同的功能中。
如果结构是局部的,则在fwrite中我将写为第一个参数
&carPtr[number-1]
但是对于我来说,这是行不通的。
汽车申报单:
struct car
{
char make[15];
char model[15];
int year;
double price;
};
答案 0 :(得分:1)
fwrite
需要指向要写入的字节缓冲区的指针。
如果您有局部变量(包括结构),则需要使用&运算符获取其地址,如下所示:
Car myCar;
fwrite(&myCar, sizeof(Car), 1, fout);
但是,如果您已经有一个指针,则不需要&运算符:
Car *myCar;
fwrite(myCar, sizeof(Car), 1, fout);
如果您有一个指向结构的指针数组,也会发生同样的事情:
Car* cars[];
fwrite(cars[i], sizeof(Car), 1, fout);
由于cars[i]
已具有地址fwrite
的地址,因此不需要任何运算符。
要注意的一件事是C编译器填充结构-它们可以在字段之间插入未使用的字节,以确保每个字段都在边界上开始(取决于系统字的对齐方式,通常为4)。
因此,这15个char
数组可能附加一个额外的字节以舍入为16。
如果将整个结构写入文件,这些字节也将被写入。
这就是为什么通常建议单独编写每个字段的原因,但是如果这只是一个练习,可能没关系。
答案 1 :(得分:0)
Car *pnt
这是指向Car
的指针。
表达式*(...)
将...
取消引用到对象中。
表达式a[b]
等于*(a + b)
。
Car* carPtr[]
函数参数列表中的(即function(... Car *carPtr[] ....)
中的等于:
Car **carPtr
这是指向Car的指针。
&carPtr[x]
等于:
carPtr + x
这不是您想要的。您有一个指向汽车数组的指针,而不是指向汽车数组的指针。您要先取消引用carPtr,然后递增。您想要:
&(*carPtr)[x]
等于:
((*carPtr) + x)
所以尝试:
fwrite(&(*carPtr)[number-1], sizeof(Car), 1, fPtr);
我还要重写
(*carPtr+number-1)->
进入
(*carPtr)[number - 1].
表示您正在处理指向数组的指针。
但实际上,我将重写api以处理更好的抽象:
struct cars_s {
Car *cars;
size_t carslen;
};
int main() {
struct cars_s cars;
insertData(db, &cars);
...
editData(db, &cars);
}
当您执行editData(FILE *db, struct cars_s *cars)
和cars->cars[x].year = year
而不是Cars *cars[], int *size
和(*carPtr)[x].year = year
时,这将使您的代码更具可读性。
答案 2 :(得分:0)
问题不是fwrite,而是毕竟fseek。 这个:
fseek(fPtr, sizeof(Car) * number-1, SEEK_SET);
必须更改为此:
fseek(fPtr, sizeof(Car) * (number-1), SEEK_SET);
我设法省略了括号,由于这个原因,fwrite会写到错误的地方。然后,Fread读取的内容超出了分配的内存,这就是为什么我认为随机发生的事情。
关于写fwrite的正确方法:
fwrite(&(*carPtr)[number-1], sizeof(Car), 1, fPtr);
这很好用