我尝试使用结构中的指针对文件进行写入和读取。但是当我从文件中读取时,我看到了一些无用的值。我在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;
}发布于 2013-12-31 03:02:21
指针只有在它们产生的应用程序进程中才有意义。如果你将它们写到一个文件中,就像你在这里做的那样,你读回的值将是没有意义的--它们很可能指向未初始化的内存,或者指向正在被完全用于其他事情的内存。
您需要想出另一种将此数据写入文件的方法。
发布于 2013-12-31 08:08:31
您遇到的问题是char*和char[]之间的模棱两可。当然,您可以为char*赋值字符串文字,但您需要了解清单结构的内容,以及如何将数据序列化和反序列化到文件中。
保存来自一个进程的指针并将其读入另一个进程是没有意义的,因此您可能希望保存内容(指针所指向的内容)。您希望将两个值(name、phone)存储到文件中。由于您可能希望存储文字名称和文字电话,让我们考虑一下该文件可能是什么样子:
roast duck|212-333-4444
peking duck|411-511-61111
duck soup|314-222-3333
free duck|800-111-2222
...您需要函数来序列化和反序列化数据。由于清单类型是指针,因此需要在读取这些值时为它们分配适当的空间,并且需要函数(方法)从文件读取序列化数据并将序列化数据写入文件。
读取(您将需要分配足够的空间),
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”分配给列表成员的姓名和电话。虽然这样做是合法的,但您需要更好地理解C语言在这里的作用。C获取这些C字符串常量的地址,并将这些地址分配给honelist1.name和honelist1.phone成员指针。
考虑一下,如果你完成了这项任务,
phoneList[0].name = "Santosh";
phoneList[0].phone = "9657681798";您已将指向常量字符串的指针分配给结构成员。
但如果要分配空间(例如,使用strdup()),
phoneList[0].name = strdup("Santosh");
phoneList[0].phone = strdup("9657681798");您已经为字符串分配了空间,为这些成员元素分配了独立的位置。这更有可能是你想要做的。
请注意,我使用了phonelist,因为C具有从零开始的数组。
发布于 2013-12-31 02:58:27
printf("%s %s",phoneList[1].name,phoneList[1].phone);上面的语句调用了未定义的行为。
由于结构对象phoneList[1]的指针name和phone没有初始化,因此取消对它们的引用将调用UB。在你的例子中,他们抛出了垃圾值,但这也可能导致崩溃。
为了适合读取文件内容并将其存储在结构对象中的情况,使用getline函数按行读取它们(假设所有细节都是按行存储的),然后为char指针动态分配内存,然后将它们赋给读取值。但是,这种方法导致了大量的内存管理,这很容易出错。
https://stackoverflow.com/questions/20845119
复制相似问题