C语言 结构体指针字符 二进制文件写入和读取

时间:2022-03-10 10:30:54

typedef struct s{
char *name;
}student;

/*将结构体读出并显示*/
int IsUsed(char str)
{
FILE *fp = fopen("test","rb");
student s;
s.name = (char) malloc(sizeof(char)*20);
fread(&s,sizeof(student),1,fp);
while(!feof(fp)){
printf("%s",s.name); //为什么这里出错??????????????????
if(strcmp(s.name,str)==0){
fclose(fp);
return 1; //存在该字符串,则返回1
}
fread(&s,sizeof(student),1,fp);
}
fclose(fp);
return 0; //不存在该字符串,则返回0
}
int main()
{
FILE fp = fopen("test","rb+");
/先将结构体P存入二进制文件中*/
student p;
p.name = (char*) malloc(sizeof(char)*20);
scanf("%s",p.name);
while(IsUsed(p.name)){ //检查员工号是否唯一
printf("该字符串已经存在,请更换一个:");
scanf("%s",p.name);
}
fwrite(&p,sizeof(student),1,fp);
}

在printf哪里显示程序停止工作!!!!!!!!!求解啊

12 个解决方案

#1


char*指针的值和char*指针指向的数据是两码事,一张纸上写了你房子的地址,不是说你把这张纸锁进保险箱里,你的房子就安全了
因为student结构体里放的是一个指针,所以sizeof(student)获得的是这张纸的大小,它上面写的地址可能早就不是你的房子了——毕竟,你只有70年产权而已

#2


引用 1 楼 baichi4141 的回复:
char*指针的值和char*指针指向的数据是两码事,一张纸上写了你房子的地址,不是说你把这张纸锁进保险箱里,你的房子就安全了
因为student结构体里放的是一个指针,所以sizeof(student)获得的是这张纸的大小,它上面写的地址可能早就不是你的房子了——毕竟,你只有70年产权而已

明白了、也就是说我fread取出来的不是我想要的完整结构体、、、那我想问问如果这样的话我岂不是不能fread了?  sizeof我没法得到结构体大小啊??谢谢啦~

#3


最简单的做法:
typedef struct s{
char name[20];
}student;

#4


引用 3 楼 vanxining 的回复:
最简单的做法:
typedef struct s{
char name[20];
}student;

嗯、我知道这么改可以、但是我还是想知道如果不改结构体的话如何实现呢、、、总不能实现不了吧?!

#5


引用 4 楼 zxasqwedc 的回复:
Quote: 引用 3 楼 vanxining 的回复:

最简单的做法:
typedef struct s{
char name[20];
}student;

嗯、我知道这么改可以、但是我还是想知道如果不改结构体的话如何实现呢、、、总不能实现不了吧?!

写文件的时候,写入指针指向的字符串,读文件的时候,读出字符串放到结构体中
不是不能用fread,而是不能用fread读出带有指针/容器的结构体,别总想着sizeof多省事,那是用户的想法,程序员的工作就是用自己的麻烦换用户的简单

#6


fread(&s,sizeof(student),1,fp);
即使你对s.name申请了空间. 但实际s本身还是只占一个指针, 通常也就是4字节空间.
你在这里从文件读取了一个数给这个指针, 即s.name的值就被修改了, 即name这个指针地址被修改了, 你前面的分配等于是白做了. 也产生了内存泄漏.

sizeof只能对student本身计算大小, 也就是指针本身所占的大小,4字节.

要保存这个串, 在保存的时候应该这么做.
fwrite(s.name,1,strlen(s.name),pFile);

读取的时候,先给s.name分配足够的空间,比如100,注意要为\0分配好空间.
fread(s.name,1, 100,pFile).

#7


引用 6 楼 xiaohuh421 的回复:
fread(&s,sizeof(student),1,fp);
即使你对s.name申请了空间. 但实际s本身还是只占一个指针, 通常也就是4字节空间.
你在这里从文件读取了一个数给这个指针, 即s.name的值就被修改了, 即name这个指针地址被修改了, 你前面的分配等于是白做了. 也产生了内存泄漏.

sizeof只能对student本身计算大小, 也就是指针本身所占的大小,4字节.

要保存这个串, 在保存的时候应该这么做.
fwrite(s.name,1,strlen(s.name),pFile);

读取的时候,先给s.name分配足够的空间,比如100,注意要为\0分配好空间.
fread(s.name,1, 100,pFile).


也就是说我fread出来后s.name的值不一定是我当初存入的那个指针、指针值改变了,所以我printf的时候可能读的是非法内存。。。就会出现“程序出现错误”那种windows提示? 
你说的fwrite(s.name....)和fread(s.name....)只是用于结构体中只有这一个name,我结构体中如果包含多项指针字符串呢?  
是不是  fread和fwrite在 对结构体中指针字符的操作真的不好用、??

#8


引用 7 楼 zxasqwedc 的回复:
Quote: 引用 6 楼 xiaohuh421 的回复:

fread(&s,sizeof(student),1,fp);
即使你对s.name申请了空间. 但实际s本身还是只占一个指针, 通常也就是4字节空间.
你在这里从文件读取了一个数给这个指针, 即s.name的值就被修改了, 即name这个指针地址被修改了, 你前面的分配等于是白做了. 也产生了内存泄漏.

sizeof只能对student本身计算大小, 也就是指针本身所占的大小,4字节.

要保存这个串, 在保存的时候应该这么做.
fwrite(s.name,1,strlen(s.name),pFile);

读取的时候,先给s.name分配足够的空间,比如100,注意要为\0分配好空间.
fread(s.name,1, 100,pFile).


也就是说我fread出来后s.name的值不一定是我当初存入的那个指针、指针值改变了,所以我printf的时候可能读的是非法内存。。。就会出现“程序出现错误”那种windows提示? 
你说的fwrite(s.name....)和fread(s.name....)只是用于结构体中只有这一个name,我结构体中如果包含多项指针字符串呢?  
是不是  fread和fwrite在 对结构体中指针字符的操作真的不好用、??


如果有多项指针, 那肯定要写多次了. 
如果直接保存结构体, 只会保存结构体当前的东西, 指针就仅保存指针的值, 但是指针指向的内容却没有保存

#9


崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。

#10


s.name =  (char*) malloc(sizeof(char)*20);

#11


该回复于2014-02-24 17:31:52被管理员删除

#12


我怎么感觉这个程序的逻辑有问题呢

#1


char*指针的值和char*指针指向的数据是两码事,一张纸上写了你房子的地址,不是说你把这张纸锁进保险箱里,你的房子就安全了
因为student结构体里放的是一个指针,所以sizeof(student)获得的是这张纸的大小,它上面写的地址可能早就不是你的房子了——毕竟,你只有70年产权而已

#2


引用 1 楼 baichi4141 的回复:
char*指针的值和char*指针指向的数据是两码事,一张纸上写了你房子的地址,不是说你把这张纸锁进保险箱里,你的房子就安全了
因为student结构体里放的是一个指针,所以sizeof(student)获得的是这张纸的大小,它上面写的地址可能早就不是你的房子了——毕竟,你只有70年产权而已

明白了、也就是说我fread取出来的不是我想要的完整结构体、、、那我想问问如果这样的话我岂不是不能fread了?  sizeof我没法得到结构体大小啊??谢谢啦~

#3


最简单的做法:
typedef struct s{
char name[20];
}student;

#4


引用 3 楼 vanxining 的回复:
最简单的做法:
typedef struct s{
char name[20];
}student;

嗯、我知道这么改可以、但是我还是想知道如果不改结构体的话如何实现呢、、、总不能实现不了吧?!

#5


引用 4 楼 zxasqwedc 的回复:
Quote: 引用 3 楼 vanxining 的回复:

最简单的做法:
typedef struct s{
char name[20];
}student;

嗯、我知道这么改可以、但是我还是想知道如果不改结构体的话如何实现呢、、、总不能实现不了吧?!

写文件的时候,写入指针指向的字符串,读文件的时候,读出字符串放到结构体中
不是不能用fread,而是不能用fread读出带有指针/容器的结构体,别总想着sizeof多省事,那是用户的想法,程序员的工作就是用自己的麻烦换用户的简单

#6


fread(&s,sizeof(student),1,fp);
即使你对s.name申请了空间. 但实际s本身还是只占一个指针, 通常也就是4字节空间.
你在这里从文件读取了一个数给这个指针, 即s.name的值就被修改了, 即name这个指针地址被修改了, 你前面的分配等于是白做了. 也产生了内存泄漏.

sizeof只能对student本身计算大小, 也就是指针本身所占的大小,4字节.

要保存这个串, 在保存的时候应该这么做.
fwrite(s.name,1,strlen(s.name),pFile);

读取的时候,先给s.name分配足够的空间,比如100,注意要为\0分配好空间.
fread(s.name,1, 100,pFile).

#7


引用 6 楼 xiaohuh421 的回复:
fread(&s,sizeof(student),1,fp);
即使你对s.name申请了空间. 但实际s本身还是只占一个指针, 通常也就是4字节空间.
你在这里从文件读取了一个数给这个指针, 即s.name的值就被修改了, 即name这个指针地址被修改了, 你前面的分配等于是白做了. 也产生了内存泄漏.

sizeof只能对student本身计算大小, 也就是指针本身所占的大小,4字节.

要保存这个串, 在保存的时候应该这么做.
fwrite(s.name,1,strlen(s.name),pFile);

读取的时候,先给s.name分配足够的空间,比如100,注意要为\0分配好空间.
fread(s.name,1, 100,pFile).


也就是说我fread出来后s.name的值不一定是我当初存入的那个指针、指针值改变了,所以我printf的时候可能读的是非法内存。。。就会出现“程序出现错误”那种windows提示? 
你说的fwrite(s.name....)和fread(s.name....)只是用于结构体中只有这一个name,我结构体中如果包含多项指针字符串呢?  
是不是  fread和fwrite在 对结构体中指针字符的操作真的不好用、??

#8


引用 7 楼 zxasqwedc 的回复:
Quote: 引用 6 楼 xiaohuh421 的回复:

fread(&s,sizeof(student),1,fp);
即使你对s.name申请了空间. 但实际s本身还是只占一个指针, 通常也就是4字节空间.
你在这里从文件读取了一个数给这个指针, 即s.name的值就被修改了, 即name这个指针地址被修改了, 你前面的分配等于是白做了. 也产生了内存泄漏.

sizeof只能对student本身计算大小, 也就是指针本身所占的大小,4字节.

要保存这个串, 在保存的时候应该这么做.
fwrite(s.name,1,strlen(s.name),pFile);

读取的时候,先给s.name分配足够的空间,比如100,注意要为\0分配好空间.
fread(s.name,1, 100,pFile).


也就是说我fread出来后s.name的值不一定是我当初存入的那个指针、指针值改变了,所以我printf的时候可能读的是非法内存。。。就会出现“程序出现错误”那种windows提示? 
你说的fwrite(s.name....)和fread(s.name....)只是用于结构体中只有这一个name,我结构体中如果包含多项指针字符串呢?  
是不是  fread和fwrite在 对结构体中指针字符的操作真的不好用、??


如果有多项指针, 那肯定要写多次了. 
如果直接保存结构体, 只会保存结构体当前的东西, 指针就仅保存指针的值, 但是指针指向的内容却没有保存

#9


崩溃的时候在弹出的对话框按相应按钮进入调试,按Alt+7键查看Call Stack里面从上到下列出的对应从里层到外层的函数调用历史。双击某一行可将光标定位到此次调用的源代码或汇编指令处。

#10


s.name =  (char*) malloc(sizeof(char)*20);

#11


该回复于2014-02-24 17:31:52被管理员删除

#12


我怎么感觉这个程序的逻辑有问题呢