我是C的初学者。 我想写和读取二进制文件,到目前为止我达到了这个目的:
我可以将我的结构转换为二进制文件,并且可以阅读。
问题一:我只能读取整数,不知何故字符串打印为垃圾或随机字符。
问题二:如果我运行我的程序,我将一些条目添加到我的二进制文件,然后我打印所有条目它正常工作(问题一除外),但在我终止我的程序后然后运行AGAIN我尝试读取文件时出现Segmentation Fault。
请帮助我,我无法前进。
/* Our structure */
struct rec
{
int max,cost;
char *name;
};
struct rec addNewEntry()
{
//init
char name[256];
int max;
int cost;
//input
printf("Type name: \n");
scanf("%s" , &name) ;
printf("Type guests limit: \n");
scanf("%d", &max);
printf("Type price: \n");
scanf("%d", &cost);
//create record
struct rec record;
record.name = name;
record.max = max;
record.cost = cost;
return record;
}
int main()
{
FILE *ptr_myfile;
//////////////////////////MENU////////////////////////////////
int option=-1;
while(option!=3)
{
printf("\n=== MENU === \n");
printf("\n1. Print all entries");
printf("\n2. Add new entry");
printf("\n3. Exit");
printf("\n");
printf("\nType menu option:");
scanf("%d", &option);
if(option == 1)
{
printf("\n...Printing all entries\n");
int f=open("stadionok.db",O_RDONLY);
if (f<0){ perror("Error at opening the file\n");exit(1);}
struct rec my_record;
while (read(f,&my_record,sizeof(my_record))){ //use write for writing
printf("name: %s \n",my_record.name);
printf("max: %d \n",my_record.max);
printf("cost: %d \n",my_record.cost);
}
close(f);
}
else if(option ==2)
{
printf("\n...Type a new entry\n");
//OPEN AND CHECK
ptr_myfile=fopen("stadionok.db","a");
if (!ptr_myfile)
{
printf("Unable to open file!");
return 1;
}
//TYPE A NEW ENTRY
struct rec new_stad = addNewEntry();
//WRITE TO FILE
fwrite(&new_stad, sizeof(struct rec), 1, ptr_myfile);
//CLOSE
fclose(ptr_myfile);
printf("Done.\n");
}
}
return 0;
}
E D I T:
我按照你的建议进行了修改,现在我得到了: 错误:分配中的不兼容类型
在:
char name[256];
//input
printf("Type name: \n");
scanf("%s" , &name) ;
struct rec record;
record.name = name; //HERE
答案 0 :(得分:2)
您获得垃圾字符串的原因是您正在将char 指针写入文件。 执行所需操作的简单方法是在结构中使用具有固定长度的char数组。像这样:
struct rec
{
int max,cost;
char name[1024];
};
这也是崩溃的原因。当您读取数据并尝试打印字符串时,printf()
可能会尝试从无效的内存块中读取,因为内存地址已更改。
如果要将具有动态大小的字符串写入文件,则会更复杂一些。
那么你不应该写结构本身,而是它的值和字符串的大小。
伪码示例:
write(max);
write(cost);
write(strlen(name)); // strlen + 1 if you want to include \0
write(name);
max = readInt();
cost = readInt();
nameLen = readInt();
allocatememory(nameLen);
name = read_n_bytes(namelen);
要编辑:
如果rec.name仍然是指针(char *),则必须为其指定一个指针,而不是数组。
rec.name = &name;
如果你的rec.name现在是一个固定大小的数组:
strncpy(rec.name, name, sizeof(rec.name)); // copy the string to rec.name
rec.name[strlen(name)] = '\0'; // add a binary 0 to the end of the string
注意:如果您正在读取多个结构(在循环中),则不应使用char name[256];
,因为每个rec.name都指向name,每次读取新值时都会覆盖该名称。对每个条目使用以下构造:
char* name; //define name as a pointer
name = malloc(256); // allocate a new memory block and assign a pointer to it to name
scanf("%s" , name); // No & needed because name is already a pointer
rec.name = name; // No & needed because name is already a pointer