【问题标题】:using pointers in structures to read from file [duplicate]使用结构中的指针从文件中读取
【发布时间】:2013-12-30 17:46:22
【问题描述】:

我尝试使用结构中的指针写入和读取文件。但是当我从文件中读取时,我看到了一些垃圾值。我在 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;
}

【问题讨论】:

  • 第 1 个不写文件:不写指针...
  • @user101285 这将是您迁移到 Stack Overflow 的第二个问题。请阅读每个站点上的help center,以熟悉两者之间的区别——它将帮助您更快地获得更好的答案。
  • 你到底想在这里写什么?

标签: c pointers


【解决方案1】:

指针仅在它们源自的应用程序进程中才有意义。如果您将它们写入文件,就像您在此处所做的那样,您读回的值将毫无意义——它们很可能指向未初始化的内存,或完全用于其他用途的内存。

您需要想出另一种方法将此数据写入文件。

【讨论】:

    【解决方案2】:

    您遇到的问题是 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 具有从零开始的数组。

    【讨论】:

      【解决方案3】:
      printf("%s %s",phoneList[1].name,phoneList[1].phone);
      

      上述语句调用未定义的行为。

      由于结构对象phoneList[1] 的指针namephone 未初始化,因此取消引用它们会调用UB。在您的情况下,他们正在丢弃垃圾值,但这也可能导致崩溃。

      为了适合您读取文件内容并将其存储在结构对象中的情况,请使用getline 函数逐行读取它们(假设所有详细信息均按行存储),然后动态分配内存char 指针然后将它们分配给读取值。但是,这种方法会导致大量容易出错的内存管理。

      【讨论】:

      • 这个答案是正确的,因为从文件中读取的指针在读取过程的上下文中是无效的。更多细节会有所帮助。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-02
      • 2018-10-19
      • 2022-08-17
      • 2021-04-07
      • 2015-04-06
      相关资源
      最近更新 更多