分段故障而阅读用C二进制文件 [英] Segmentation fault while reading binary file in C

查看:111
本文介绍了分段故障而阅读用C二进制文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

即时通讯在C.初学者
我想为写和读的二进制文件,然后我达到了这个至今:

我可以我的结构为二进制文件,并且可以读取。

问题一:我只能读整​​数,不知怎么的字符串打印为垃圾或随​​机字符

问题二:如果我运行我的程序,我有些条目添加到我的二进制文件,然后我打印所有它工作正常(除问题一)项,但在我结束我的计划并再次运行我得到分割故障而我试图读取该文件。

请帮助我,我就不能前进。

  / *我们的结构* /
结构REC
{
    INT最大,造价;
    字符*名称;
};
结构体REC addNewEntry()
{    //在里面
    字符名称[256];
    INT最大;
    INT费用;    //输入
    的printf(类型名称:\\ n);
    scanf函数(%S,&安培;名);    的printf(类型的客人限制:\\ n);
    scanf函数(%d个,&安培;最大);    的printf(类型的价格:\\ n);
    scanf函数(%d个,&安培;成本);    //创建记录
    结构体REC记录;    record.name =名称;
    record.max = MAX;
    record.cost =成本;    返回记录;}诠释的main()
{    FILE * ptr_myfile;
    //////////////////////////菜单/////////////////////// /////////    INT选项= -1;
    而(选择!= 3)
    {        的printf(\\ n === MENU === \\ n);
        的printf(\\ N1打印的所有项目);
        的printf(\\ N2添加新条目。);
        的printf(\\ N3退出);
        的printf(\\ n);        的printf(\\ n类型菜单选项:);        scanf函数(%d个,&安培;可选);
        如果(选项== 1)
        {
            的printf(\\ n ...打印所有条目的\\ n);            INT F =打开(stadionok.db,O_RDONLY);
            如果(F&小于0){PERROR(在打开文件\\ n错误);出口(1);}             结构体REC my_record;             而(读(F,放大器; my_record,sizeof的(my_record))){//使用写写作
                的printf(名称:%s \\ n,my_record.name);
                的printf(最大数:%d \\ n,my_record.max);
                的printf(成本数:%d \\ n,my_record.cost);
             }
            关闭(F);
        }
        否则,如果(选项== 2)
        {            的printf(\\ n ...键入一个新条目\\ n);
            //打开查看
            ptr_myfile =的fopen(stadionok.db,一个);
            如果(!ptr_myfile)
            {
                的printf(无法打开文件!);
                返回1;
            }            //键入一个新入榜
            结构REC new_stad = addNewEntry();            //写入文件
            FWRITE(安培; new_stad,的sizeof(结构REC),1,ptr_myfile);
            //关
            FCLOSE(ptr_myfile);            的printf(DONE \\ n);
        }
    }
    返回0;
}

E D I T:

我修改只是如你所说,现在我得到:
错误:不兼容的类型分配

 字符名称[256];
//输入
的printf(类型名称:\\ n);
scanf函数(%S,&安培;名);
结构体REC记录;record.name =名称; //这里


解决方案

你得到的垃圾字符串的原因是,你正在写一个字符的指针的到文件中。
最简单的方法去做你想做的就是用一个字符数组的结构内固定长度。像这样:

 结构REC
{
    INT最大,造价;
    字符名称[1024];
};

这也是崩溃的原因。当读取数据,并试图打印的printf()可能试图从一个内存块是无效的阅读,因为内存地址改变了字符串。搜索结果

如果你想要写动态尺寸字符串到它变得有点复杂文件。结果
那么你不应该写结构本身,而是它的值和字符串的大小。结果
伪code示例:

 写(最多);
写(成本);
写(strlen的(名)); // strlen的+ 1,如果你要包括\\ 0
写(名);最大=的readInt();
成本=的readInt();
nameLen =的readInt();
allocatememory(nameLen);
名称= read_n_bytes(namelen);

结果
您的编辑:
如果rec.name仍然是一个指针(字符*),你有一个指针分配给它,而不是一个数组。

  rec.name =放大器;名称;

如果您rec.name是现在有一个固定大小的数组:

 函数strncpy(rec.name,名称的sizeof(rec.name)); //拷贝字符串rec.name
rec.name [strlen的(名称)] ='\\ 0'; //二进制0添加到字符串的结尾

请注意:如果你正在阅读超过1结构(在一个循环中),则不应使用字符名称[256]; ,因为每rec.name会指着每次你读一个新的值被覆盖的名称。使用下面的结构对每个条目:

 字符*名称; //定义名字为指针
名称=的malloc(256); //分配一个新的内存块和一个指向分配给它的名字
scanf函数(%S,名); //否放;必要的,因为名字已经是一个指针
rec.name =名称; //否放;必要的,因为名字已经是一个指针

Im a beginner in C. I would like to write and read a binary file, and i reached this so far:

I can my struct to a binary file, and can read.

Problem one: I can only read integers, somehow strings are printed as garbage or random characters.

Problem two: If i run my program, i add some entries to my binary file, then i print all the entries it is working fine (except Problem one), but after i terminate my program and run AGAIN i got Segmentation Fault while i try to read the file.

Please help me, i just cannot move forward.

/* 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:

I modified just as you suggested and now i got: error: incompatible types in assignment

at:

char name[256];


//input
printf("Type name: \n");
scanf("%s" , &name) ;


struct rec record;

record.name = name; //HERE

解决方案

The reason you get garbage strings is that you are writing a char pointer into the file. The simple way to do what you want is to use a char array with a fixed length inside your struct. like so:

struct rec
{
    int max,cost;
    char name[1024];
};

It is also the reason for the crash. When you read the data and trying to print the string the printf() probably tries to read from a memory block that is not valid, because the memory addresses changed.

If you want to write strings with dynamic size into the file it gets a bit more complicated.
Then you should not write the struct itself, but the values of it and the size of the string.
PseudoCode Example:

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);


To your edit: if rec.name is still a pointer (char*) you have to assign a pointer to it, not an array.

rec.name = &name;

if your rec.name is an array with a fixed size now:

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

Note: if you are reading more than 1 struct (in a loop), you should not use char name[256];, because every rec.name would be pointing to name which is overwritten everytime you read a new value. Use the following construct for every entry:

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

这篇关于分段故障而阅读用C二进制文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆