我试着用带有结构指针的文件来编写和读取。但是当我从文件中读到时,我看到了一些垃圾值。我在Linux上使用GCC 4.7.2。需要一些帮助。
读:
//read from a file
#include<stdio.h>
typedef struct
{
char* name;
char* phone;
}LISTING;
int main(void)
{
LISTING phoneList[14];
FILE * fp = NULL;
fp = fopen("/media/Study/PhoneDirectory.dat","rb");
if(fp == NULL)
printf("Error opening file!!!");
fseek(fp,0,SEEK_SET);
if(fread(&phoneList[1],sizeof(LISTING),1,fp)==1)
printf("%s %s",phoneList[1].name,phoneList[1].phone);
fclose(fp);
return 0;
}
写下:
//Write to file
#include<stdio.h>
typedef struct
{
char* name;
char* phone;
}LISTING;
int main(void)
{
LISTING phoneList[2];
FILE * fp = NULL;
fp = fopen("/media/Study/PhoneDirectory.dat","wb");
phoneList[1].name = "Santosh";
phoneList[1].phone = "9657681798";
if(fwrite(&phoneList[1],sizeof(LISTING),1,fp)==1)
printf("inserted");
fclose(fp);
return 0;
}
答案 0 :(得分:1)
指针仅在它们源自的应用程序过程中有意义。如果你将它们写入文件,正如你在这里所做的那样,你读回的值将毫无意义 - 它们很可能指向未初始化的内存,或者指向完全用于其他内存的内存。
您需要提出另一种将此数据写入文件的方法。
答案 1 :(得分:0)
你遇到的问题是char *和char []之间的区别。您当然可以将字符串文字分配给char *,但是您需要了解LISTING结构的内容,以及您希望如何将数据序列化和反序列化为文件。
保存来自一个进程的指针并将它们读入另一个进程是没有意义的,因此您可能希望保存内容(指针指向的位置)。您希望将两个值(名称,电话)存储到文件中。由于您可能希望存储文字名称和文字电话,因此我们请考虑文件的外观:
roast duck|212-333-4444
peking duck|411-511-61111
duck soup|314-222-3333
free duck|800-111-2222
...
您需要使用函数来序列化和反序列化数据。由于您的LISTING类型是指针,因此您需要在读取这些值时为这些值分配适当的空间,并且需要函数(方法)从文件中读取序列化数据并将序列化数据写入文件。
阅读(你需要分配足够的空间),
int
listing_read(FILE*fp, LISTING* listing)
{
char name_buffer[100];
char phone_buffer[100];
if(!fp) return(-1);
if(!listing) return(-2);
int res = fscanf(fp,"%s|%s\n",name_buffer,phone_buffer);
if( !res ) {
//handle error here
}
//careful here, you cannot free if you didn't malloc/strdup
if(listing->name) free(listing->name);
if(listing->phone) free(listing->phone);
listing->name = strdup(name_buffer);
listing->phone = strdup(phone_buffer);
return(0);
}
写作(您需要提供正确的格式),
int
listing_write(FILE*fp, LISTING* listing)
{
if(!fp) return(-1);
if(!listing) return(-2);
fprintf(fp,"%s|%s\n",listing->name,listing->phone);
return(0);
}
以下是修改代码的方法,
//read from a file
#include<stdio.h>
typedef struct
{
char* name;
char* phone;
}LISTING;
int main(void)
{
LISTING phoneList[14];
FILE* fp = NULL;
if( !(fp = fopen("/media/Study/PhoneDirectory.dat","rb")) ) {
printf("Error opening file!!!");
exit(1);
}
fseek(fp,0,SEEK_SET);
if( listing_read(fp,&phoneList[0]) >= 0 ) {
printf("%s %s",phoneList[0].name,phoneList[0].phone);
}
fclose(fp);
return 0;
}
以下是编写文件的方式会发生变化,
//Write to file
#include<stdio.h>
typedef struct
{
char* name;
char* phone;
}LISTING;
int main(void)
{
LISTING phoneList[14];
FILE* fp = NULL;
if( !(fp = fopen("/media/Study/PhoneDirectory.dat","wb")) ) {
printf("error, cannot write file\n");
exit(1);
}
phoneList[0].name = "Santosh";
phoneList[0].phone = "9657681798";
if( listing_write(fp,&phoneList[0])>=0) {
printf("inserted");
}
fclose(fp);
return 0;
}
请注意,在编写程序时,您将字符串文字“Santosh”和“9657681798”分配给LISTING成员名称和电话。虽然合法,但您需要更好地了解C在这里所做的事情。 C获取这些C字符串常量的地址,并将这些地址分配给phonelist [1] .name和phonelist [1] .phone成员指针。
考虑一下,如果你做了这个任务,
phoneList[0].name = "Santosh";
phoneList[0].phone = "9657681798";
您已将指向常量字符串的指针分配给结构成员。
但是如果你要分配空间(例如,使用strdup()),
phoneList[0].name = strdup("Santosh");
phoneList[0].phone = strdup("9657681798");
您已为字符串分配空间,为这些成员元素指定独立位置。哪个更有可能是你想要做的。
请注意,我使用了phonelist [0],因为C具有从零开始的数组。
答案 2 :(得分:-1)
printf("%s %s",phoneList[1].name,phoneList[1].phone);
上述语句调用未定义的行为。
指针name
&amp;结构对象phone
的{{1}}未初始化,取消引用它们调用UB。在你的情况下,他们扔掉了垃圾值,但也可能导致崩溃。
为了适合您阅读文件内容并将其存储在struct对象中的情况,请使用phoneList[1]
函数逐行读取它们(假设所有细节都按行存储)然后动态分配getline
指针的内存然后将它们分配给读取值。但是,这种方法导致大量内存管理容易出错。