C 从二进制文件更新记录(项目的一部分)(分段错误)
我试图更改二进制文件中的一些信息,但我遇到了分段错误。我已经试着处理了好几个小时了。假设有两支名字相同的球队。这些名字需要更改。但是,我有一个错误。 问题假设有两个名称相同的团队。这些名字需要更改。但是,我有一个错误。谢谢你的回答C 从二进制文件更新记录(项目的一部分)(分段错误),c,file-io,segmentation-fault,malloc,binaryfiles,C,File Io,Segmentation Fault,Malloc,Binaryfiles,我试图更改二进制文件中的一些信息,但我遇到了分段错误。我已经试着处理了好几个小时了。假设有两支名字相同的球队。这些名字需要更改。但是,我有一个错误。 问题假设有两个名称相同的团队。这些名字需要更改。但是,我有一个错误。谢谢你的回答 team_name, city , stadium ,fdate, colors the team is in binary file manunited,manchester,old_trafford,1878,black-rd chelsea,lon
team_name, city , stadium ,fdate, colors
the team is in binary file
manunited,manchester,old_trafford,1878,black-rd
chelsea,london,stamford_bridge,1905,blue-whte
manunited,manchester,old_trafford,1878,black-rd
----------------------------------------
example input
update
update team_name=newcastle,founding_date=2014 in teams where team_name=manunited
----------------------------------------
output
**segmentation fault**
----------------------------------------
new output teams.bin should be
newcastle,manchester,old_trafford,2014,black-rd
chelsea,london,stamford_bridge,1905,blue-whte
newcastle,manchester,old_trafford,2014,black-rd
代码:
在fread之前,还可以通过ftell等保存文件位置。
您需要查找在写入之前存储的位置
试试这个
fseek(fp, ii*sizeof(team), SEEK_SET);
fwrite(&t[ii], sizeof(teams), 1, fp);
命令分析示例代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct field_U {
char *name;
char *value;
} Field_U;
typedef struct command_U {
char *order; //"update"
char *rec_name;//record name. E.g "teams"
int n; //number of update field
Field_U *field;//field and value pair of char *
Field_U cond; //condition a field pair.(one pair)
} Command_U;
void *allocate(size_t size){
void *p = malloc(size);
if(!p){
fprintf(stderr, "malloc error!\n");
exit(-1);
}
return p;
}
char *str_dup(const char *str){
size_t len = strlen(str);
char *p = allocate(len+1);
memcpy(p, str, len+1);
return p;
}
Command_U *analyze_U(const char *cmd){
char temp1[128];//order field
char temp2[32]; //record name
char temp3[64]; //condition field
if(3!=sscanf(cmd, "update %127s in %31s where %63s", temp1, temp2, temp3)){
fprintf(stderr, "update syntax error!\n");
return NULL;
}
Command_U *cmdp = allocate(sizeof(*cmdp));
int n = 0;
char *p;
for(p = temp1; p = strchr(p, '='); ++p){
++n;//count order field
}
cmdp->n = n;
cmdp->field = allocate(n*sizeof(Field_U));
int i;
p = strtok(temp1, ",");
for(i=0; i<n; ++i){
cmdp->field[i].name = str_dup(p);
p = strchr(cmdp->field[i].name, '=');
*p++ = '\0';
cmdp->field[i].value = p;
p = strtok(NULL, ",");
}
cmdp->rec_name = str_dup(temp2);
cmdp->cond.name = str_dup(temp3);
p = strchr(cmdp->cond.name, '=');
*p++ = '\0';
cmdp->cond.value = p;
cmdp->order = "update";
return cmdp;
}
void drop_U(Command_U *cmd){
int i;
for(i=0; i<cmd->n; ++i)
free(cmd->field[i].name);
free(cmd->field);
free(cmd->rec_name);
free(cmd->cond.name);
free(cmd);
}
int main(){
char command[] = "update team_name=newcastle,founding_date=2014 in teams where team_name=manunited\n";
Command_U *cmd = analyze_U(command);
if(!cmd) return -1;
printf("order: %s\nrecord name: %s\n", cmd->order, cmd->rec_name);
int i;
for(i=0; i < cmd->n; ++i){
printf("update field%d: (%s, %s)\n", i+1, cmd->field[i].name, cmd->field[i].value);
}
printf("condition field : (%s, %s)\n", cmd->cond.name, cmd->cond.value);
drop_U(cmd);
return 0;
}
/* output
order: update
record name: teams
update field1: (team_name, newcastle)
update field2: (founding_date, 2014)
condition field : (team_name, manunited)
*/
不要强制转换malloc并检查返回的指针是否为NULL,也不要执行t=realloct,newsize,因为如果失败,将无法释放。另外,修复代码的缩进,这确实很难理解,也许你需要更多的函数。相同的输出,曼彻斯特,老特拉福德,1878年,布莱克路纽卡斯尔,曼彻斯特,老特拉福德,1878年,布莱克路纽卡斯尔,曼彻斯特,老特拉福德,2014年,布莱克路@BLUEPIXY@Soner因为这样应该写入相同的文件位置及其输出。您是否从正确的状态文件运行程序?您是否使用了,因为它已经是一个错误更新的文件?@Soner int x=freadt,sizeofteams,1000,fp;由于您已经读取了倒带FP;所需的所有数据;。首先,谢谢你的帮助。但是,我的跑步是正确的。添加rewindfp后,成功更改团队名称时出现问题。但是,成立的日期没有改变。另外,下一个团队的成立日期正在改变。i、 e.在二进制文件中有2支球队的信息,曼彻斯特,老特拉福德,1878年,布莱克路切尔西,伦敦,斯坦福德桥,1905年,蓝色whte,然后运行代码输出如下:纽卡斯尔,曼彻斯特,老特拉福德,1878年,布莱克路切尔西,伦敦,斯坦福德桥,2014年,蓝色whte除此之外,我将上面的代码更新为您的saying@Soner大小与二进制文件B的大小匹配。 它将移动文件位置的记录大小。这对我来说很难。我没有你经验丰富,但谢谢你。我仍然在努力解决我的问题@BLUEPIXY@Soner我已经添加了使用示例。我还没有经过测试,谢谢。我解决了我的问题@蓝精灵
fseek(fp, ii*sizeof(team), SEEK_SET);
fwrite(&t[ii], sizeof(teams), 1, fp);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct field_U {
char *name;
char *value;
} Field_U;
typedef struct command_U {
char *order; //"update"
char *rec_name;//record name. E.g "teams"
int n; //number of update field
Field_U *field;//field and value pair of char *
Field_U cond; //condition a field pair.(one pair)
} Command_U;
void *allocate(size_t size){
void *p = malloc(size);
if(!p){
fprintf(stderr, "malloc error!\n");
exit(-1);
}
return p;
}
char *str_dup(const char *str){
size_t len = strlen(str);
char *p = allocate(len+1);
memcpy(p, str, len+1);
return p;
}
Command_U *analyze_U(const char *cmd){
char temp1[128];//order field
char temp2[32]; //record name
char temp3[64]; //condition field
if(3!=sscanf(cmd, "update %127s in %31s where %63s", temp1, temp2, temp3)){
fprintf(stderr, "update syntax error!\n");
return NULL;
}
Command_U *cmdp = allocate(sizeof(*cmdp));
int n = 0;
char *p;
for(p = temp1; p = strchr(p, '='); ++p){
++n;//count order field
}
cmdp->n = n;
cmdp->field = allocate(n*sizeof(Field_U));
int i;
p = strtok(temp1, ",");
for(i=0; i<n; ++i){
cmdp->field[i].name = str_dup(p);
p = strchr(cmdp->field[i].name, '=');
*p++ = '\0';
cmdp->field[i].value = p;
p = strtok(NULL, ",");
}
cmdp->rec_name = str_dup(temp2);
cmdp->cond.name = str_dup(temp3);
p = strchr(cmdp->cond.name, '=');
*p++ = '\0';
cmdp->cond.value = p;
cmdp->order = "update";
return cmdp;
}
void drop_U(Command_U *cmd){
int i;
for(i=0; i<cmd->n; ++i)
free(cmd->field[i].name);
free(cmd->field);
free(cmd->rec_name);
free(cmd->cond.name);
free(cmd);
}
int main(){
char command[] = "update team_name=newcastle,founding_date=2014 in teams where team_name=manunited\n";
Command_U *cmd = analyze_U(command);
if(!cmd) return -1;
printf("order: %s\nrecord name: %s\n", cmd->order, cmd->rec_name);
int i;
for(i=0; i < cmd->n; ++i){
printf("update field%d: (%s, %s)\n", i+1, cmd->field[i].name, cmd->field[i].value);
}
printf("condition field : (%s, %s)\n", cmd->cond.name, cmd->cond.value);
drop_U(cmd);
return 0;
}
/* output
order: update
record name: teams
update field1: (team_name, newcastle)
update field2: (founding_date, 2014)
condition field : (team_name, manunited)
*/
int main(){
char read_command[12];
char command[256];
Command_U *cmd;
scanf("%s", read_command);
if(strcmp(read_command,"update") == 0){
fgets(command, sizeof(command),stdin);
if(cmd = analyze_U(command)){
updatefunc(cmd);
drop_U(cmd);
}
}
return 0;
}
void updatefunc(Command_U *cmd){
if(strcmp(cmd->rec_name, "teams") == 0){
FILE *fp = fopen("teams.bin", "rb+");
if (!fp){
printf("Unable to open file %s", "teams.bin");
exit(1);
}
teams t;
long savepos;
while(1){
savepos = ftell(fp);
if(0==fread(&t, sizeof(t), 1, fp))//read one record
break;
if(strcmp(cmd->cond.name, "team_name")==0 && strcmp(cmd->cond.value, t.team_name) == 0){
int i;
for(i = 0 ; i < cmd->n ; i++){
if(strcmp(cmd->field[i].name, "team_name") == 0)
strcpy(t.team_name, cmd->field[i].value);
else if(strcmp(cmd->field[i].name, "founding_date") == 0)
t.founding_date = atoi(cmd->field[i].value);
}
fseek(fp, savepos, SEEK_SET);
fwrite(&t, sizeof(t), 1, fp);
fflush(fp);
}
}
fclose(fp);
}
}