鱼C论坛

 找回密码
 立即注册
查看: 1047|回复: 16

[已解决]结构体类型变量问题,求助,感谢感谢

[复制链接]
发表于 2022-2-7 13:56:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x

代码运行至printf("%s %d %d",ss.name,ss.id,ss.name_len);这里就报错。

Program received signal SIGSEGV, Segmentation fault。

#include<stdio.h>
#include<string.h>
#include <stdlib.h>
//        将以下结构体类型变量,以二进制的形式存放到文件中,并且可以实现读的接口,打印读出来信息。

typedef struct Student
{
        char *name;                //名字
        int id;
        int name_len;        //名字长度
}Stu;

int main()
{

        Stu s;        //定义结构体变量
        //结构体成员赋值
        s.id = 1;
        s.name_len = strlen("mike"); //名字长度
        s.name = (char *)malloc(s.name_len + 1);
        strcpy(s.name, "mike");
        
        FILE *ff=fopen("信息.txt","a+");
        if(!ff) return -1;
                printf("%s %d %d",s.name,s.id,s.name_len);
        int num=fwrite(&s,1,sizeof(Stu),ff);        
        printf("共存入%d个字节!",num);
        
        fclose(ff);
        ff=fopen("信息.txt","r");
        if(!ff) return -1;
        Stu ss;
        ss.name=(char *)malloc(64);
        int nuu=fread(&ss,1,sizeof(Stu),ff);
        printf("共%d个字节!",nuu);
        printf("%s %d %d",ss.name,ss.id,ss.name_len);
        
        
        free(s.name);
        free(ss.name);
        return 0; 
 } 


感谢帮助
感谢帮助
谢谢
最佳答案
2022-2-12 10:47:39
想入门的新人 发表于 2022-2-12 09:16
编译过得了,调试就出现
Program received signal SIGSEGV, Segmentation fault
就是第36行或者40行这 ...
free(s.name);
free(ss.name);//因为fread函数读取文件ss.name和s.name指针一样,你上面为ss.name申请内存得到的指针值已经被改变,这样重复释放内存当然报错,还有只把字符串指针写入文件有什么用
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-2-7 14:15:15 | 显示全部楼层
改成
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
//        将以下结构体类型变量,以二进制的形式存放到文件中,并且可以实现读的接口,打印读出来信息。

typedef struct Student
{
        char *name;                //名字
        int id;
        int name_len;        //名字长度
}Stu;

int main()
{

        Stu s;        //定义结构体变量
        //结构体成员赋值
        s.id = 1;
        s.name_len = strlen("mike"); //名字长度
        s.name = (char *)malloc(s.name_len + 1);
        strcpy(s.name, "mike");
       
        FILE *ff=fopen("信息.txt","ab+");  // 我改了这里
        if(!ff) return -1;
                printf("%s %d %d",s.name,s.id,s.name_len);
        int num=fwrite(&s,1,sizeof(Stu),ff);       
        printf("共存入%d个字节!",num);
       
        fclose(ff);
        ff=fopen("信息.txt","rb");  // 我改了这里
        if(!ff) return -1;
        Stu ss;
        ss.name=(char *)malloc(64);
        int nuu=fread(&ss,1,sizeof(Stu),ff);
        printf("共%d个字节!",nuu);
        printf("%s %d %d",ss.name,ss.id,ss.name_len);
       
       
        free(s.name);
        free(ss.name);
        return 0;
}
试试
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-8 16:25:59 | 显示全部楼层

小学五年级会挺多的,挺厉害的,谢谢了
这里还是不行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-10 17:39:27 | 显示全部楼层
请问具体报的是什么错呀?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-12 09:16:34 | 显示全部楼层
番杰 发表于 2022-2-10 17:39
请问具体报的是什么错呀?

编译过得了,调试就出现
Program received signal SIGSEGV, Segmentation fault
就是第36行或者40行这里编译不过去。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-12 10:47:39 | 显示全部楼层    本楼为最佳答案   
想入门的新人 发表于 2022-2-12 09:16
编译过得了,调试就出现
Program received signal SIGSEGV, Segmentation fault
就是第36行或者40行这 ...
free(s.name);
free(ss.name);//因为fread函数读取文件ss.name和s.name指针一样,你上面为ss.name申请内存得到的指针值已经被改变,这样重复释放内存当然报错,还有只把字符串指针写入文件有什么用
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-12 17:28:41 | 显示全部楼层

【还有只把字符串指针写入文件有什么用】
这里讲的是哪呀?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-12 17:31:29 | 显示全部楼层

感谢感谢,我把后面改成这样就可以了
//        ss.name=NULL;
//        ss.name=(char *)malloc(64);
        if(ss.name==NULL) return 1;
        int nuu=fread(&ss,1,sizeof(Stu),ff);
        printf("共%d个字节!",nuu);

        printf("%s %d %d",ss.name,ss.id,ss.name_len);
        
        free(s.name);
//        free(ss.name);
改成这样就可以了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-12 19:38:37 | 显示全部楼层
想入门的新人 发表于 2022-2-12 17:28
【还有只把字符串指针写入文件有什么用】
这里讲的是哪呀?


i
int num=fwrite(&s,1,sizeof(Stu),ff);//只把结构体里的char *name字符串指针变量写入文件,没有把字符串写入文件,应该在后面把name指向的字符串写入文件  
 num=fwrite(s.name,1,s.name_len + 1,ff);//读取时别忘了读完一个结构体在读入一个字符串
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2022-2-19 10:55:57 | 显示全部楼层
#include<stdio.h>
#include<string.h>
#include <stdlib.h>
//        将以下结构体类型变量,以二进制的形式存放到文件中,并且可以实现读的接口,打印读出来信息。

typedef struct Student
{
        char *name;                //名字
        int id;
        int name_len;        //名字长度
}Stu;

int main()
{

        Stu s;        //定义结构体变量
        //结构体成员赋值
        s.id = 1;
        s.name_len = strlen("mike"); //名字长度
        s.name = (char *)malloc(s.name_len + 1);
        strcpy(s.name, "mike");
        
        FILE *ff=fopen("信息.txt","w");
        if(!ff) 
        {
                perror("2");
                return -1;
        }
                printf("%s %d %d",s.name,s.id,s.name_len);
        int num=fwrite(&s,1,sizeof(Stu),ff);//只把结构体里的char *name字符串指针变量写入文件,没有把字符串写入文件,应该在后面把name指向的字符串写入文件  
                printf("共存入%d个字节!",num);
         num=fwrite(s.name,1,s.name_len + 1,ff);//读取时别忘了读完一个结构体在读入一个字符串        
        printf("共存入%d个字节!",num);
        
        fclose(ff);
        ff=fopen("信息.txt","r");
        if(!ff) 
        {
                perror("1");
                return -1;
        }
        Stu ss;
        free(s.name);
        ss.name=NULL;
        ss.name=(char *)malloc(64);
        if(ss.name==NULL) return 1;
        int nuu=fread(&ss,1,sizeof(Stu),ff);
        printf("共%d个字节!",nuu);
        nuu=fread(ss.name,1,ss.name_len+1,ff);
        printf("共%d个字节!",nuu);

        printf("%s %d %d",ss.name,ss.id,ss.name_len);
        
        
        
        free(ss.name);
        return 0; 
 } 
假如我改成这样先释放掉free(s.name),然后重新开辟ss.name ,这里运行调试至free(ss.name)还是会崩
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-19 11:40:06 | 显示全部楼层
本帖最后由 jhq999 于 2022-2-19 11:43 编辑
        Stu ss;
        free(s.name);
        ss.name=NULL;
        //ss.name=(char *)malloc(64);
        //if(ss.name==NULL) return 1;
        int nuu=fread(&ss,1,sizeof(Stu),ff);//如果在前面申请空间,经过fread函数后ss.name这个指针会被改变成文件储存的指针值
        printf("共%d个字节!",nuu);
        
        ss.name=(char *)malloc(64);////////////////////////
        if(ss.name==NULL) return 1;////////////////////////
        
        nuu=fread(ss.name,1,ss.name_len+1,ff);
        printf("共%d个字节!",nuu);

        printf("%s %d %d",ss.name,ss.id,ss.name_len);
        
        
        
        free(ss.name);
        return 0; 
 } 
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-19 11:47:12 | 显示全部楼层

这里在前面开辟空间不行吗,还是说提前开辟后,fread会将之前s.name所指向的地址拷贝过来,如果是这样,那么我在开辟ss.name后在用一个 char *p=ss.name ,在最后的时候free(p)行吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-19 11:49:24 | 显示全部楼层
想入门的新人 发表于 2022-2-19 11:47
这里在前面开辟空间不行吗,还是说提前开辟后,fread会将之前s.name所指向的地址拷贝过来,如果是这样, ...
Stu ss;
        free(s.name);
        ss.name=NULL;
        ss.name=(char *)malloc(64);
        char *p =ss.name; //-----------------------
        if(ss.name==NULL) return 1;
        int nuu=fread(&ss,1,sizeof(Stu),ff);
        printf("共%d个字节!",nuu);
        nuu=fread(ss.name,1,ss.name_len+1,ff);
        printf("共%d个字节!",nuu);

        printf("%s %d %d",ss.name,ss.id,ss.name_len);
        
        
        
//        free(ss.name); // 报错 
        free(p);//--------------------
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-19 11:52:20 | 显示全部楼层
本帖最后由 jhq999 于 2022-2-19 11:55 编辑
想入门的新人 发表于 2022-2-19 11:47
这里在前面开辟空间不行吗,还是说提前开辟后,fread会将之前s.name所指向的地址拷贝过来,如果是这样, ...


可以,但你后面的字符串读取到哪里,p?对于结构体有什么用,还得在读字符串之前让ss.name=p;多了好几行代码和一个变量
Stu ss;
        free(s.name);
        ss.name=NULL;
        ss.name=(char *)malloc(64);
        char *p =ss.name; //-----------------------
        if(ss.name==NULL) return 1;
        int nuu=fread(&ss,1,sizeof(Stu),ff);
        printf("共%d个字节!",nuu);
        nuu=fread(p,1,ss.name_len+1,ff);/////////
        ss.name=p;/////////////////////
        printf("共%d个字节!",nuu);

        printf("%s %d %d",ss.name,ss.id,ss.name_len);
        
        
        
         free(ss.name); 
    //   free(p);//--------------------
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-19 15:06:45 | 显示全部楼层
jhq999 发表于 2022-2-19 11:52
可以,但你后面的字符串读取到哪里,p?对于结构体有什么用,还得在读字符串之前让ss.name=p;多了好几行 ...

fwrite写进文件的时候是将 id的内容 ,name保存的地址 和len的内容拷贝进文件的吗?
那再一次fwrite(s.name,1,sizeof(s.len)+1,file)时会把之前保存的name地址覆盖吗?
感谢感谢感谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2022-2-19 15:18:04 | 显示全部楼层
想入门的新人 发表于 2022-2-19 15:06
fwrite写进文件的时候是将 id的内容 ,name保存的地址 和len的内容拷贝进文件的吗?
那再一次fwrite(s. ...

如果没重新打开文件,或者没有主动让位置指针移动,那么会写在后面,顺便问一下,读写文件你学了吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2022-2-19 15:41:03 | 显示全部楼层
jhq999 发表于 2022-2-19 15:18
如果没重新打开文件,或者没有主动让位置指针移动,那么会写在后面,顺便问一下,读写文件你学了吗?


                               
登录/注册后可看大图

我是这样想的,按我的思路的话,在fread(&ss,1,sizeof(Stu),fiile) ,后打印出ss.name应该是乱码,这里保存的是之前s.name molloc后的地址,fread(ss.name,1,5,file)后,将内容拷贝到之前被释放了的地址应该是非法操作
但是我打印出来却是内容mike,只有释放的时候显示报错


这里我学过文件的读写,我写入文件的结构体里面没遇见过有指针的,然后就有点不明白,感谢老哥费心思给我讲解,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-18 12:34

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表