我正在尝试从二进制文件中更改一些信息,但是我遇到了分段错误。我一直试图处理它几个小时。假设有两个队名相同。名字想要改变。但是,我得到了分段错误。 (问题)假设有两个团队名称相同。名字想要改变。但是,我得到了分段错误。感谢所有赞赏的答案。
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
代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <math.h>
int main()
{
char read_command[12];
/* checking insert */
char str1[100],str2[5],str3[18],space,str4[100];
scanf("%s", read_command);
if(strcmp(read_command,"update") == 0)
{
scanf("%s",str3);//read update from input code
//printf("\nstr3=%s",str3);
scanf("%s",str4);
//printf("\nstr4=%s",str4);
scanf("%c",&space);
fgets(str1,100,stdin);
//printf("\nstr1=%s",str1);
updatefunc(str1,str4);
}
return 0;
}
void wherefunc(char *str,char *tag,char *id)
{
char *token;
int i=0;
token = strtok(str,"=");
strcpy(tag,token);
token = strtok(NULL,"=");
strcpy(id,token);
}
void updatefunc(char *str1, char *str2)
{
FILE *fp;
char tag[30]; // regard to the input it is team_name
char id[30]; // regard to the input it is manunited
/* regard to the input it will change first team_name then founding_date */
char variablenew[30];
/* regard to the input it will change first newcastle then 2014 */
char valuenew[30];
char *tokenstr1;
char *tokenstrnew;
char *buff;
buff = (char*) malloc(strlen(str1) + 1);
strcpy(buff,str1);
char *token;
const char space[2] = " ";
const char comma[2] = ",";
char tempstrs[10][100];
char tempstrsnew[10][30];
int i = 0, j = 0 ,c, ii;
tokenstrnew = strtok(str2,comma);
while (tokenstrnew != NULL)
{
//printf(" %s %d \n",tokenstr1,i);
strcpy(tempstrsnew[j],tokenstrnew);
j++;
tokenstrnew = strtok(NULL,comma);
}
//printf("%d %s %s",j,tempstrsnew[0],tempstrsnew[1]);
tokenstr1 = strtok(buff,space);
while (tokenstr1 != NULL)
{
/* get rid of \n character bcz of fgets() */
int len = strlen(tokenstr1);
if (len > 0 && tokenstr1[len-1] == '\n') tokenstr1[len-1] = '\0';
//printf(" %s %d \n",tokenstr1,i);
strcpy(tempstrs[i],tokenstr1);
i++;
tokenstr1 = strtok(NULL,space);
}
wherefunc(tempstrs[3],tag,id); //every wherefunc to seperate "=" symbols
//printf("\n\ntag = %s id = %s",tag,id);
//printf("\n\n%s",str2);
if(strcmp(tempstrs[1],"teams") == 0)
{
fp=fopen("teams.bin", "rb+");
if (!fp)
{
printf("Unable to open file %s", "teams.bin");
exit(1);
}
teams *t;
t=(teams*)malloc(sizeof(teams)*1000);
int x = fread(t, sizeof(teams), 1000, fp);
t = (teams*)realloc(t,x*sizeof(teams));
for( ii = 0 ; ii < x ; ii++)
{
if((strcmp(tag,"team_name") == 0) && (strcmp(id,t[ii].team_name) == 0))
{
fread(&t[ii], sizeof(teams), 1, fp);
for(c = 0 ; c < j ; c++)
{
wherefunc(tempstrsnew[c],variablenew,valuenew);
if(strcmp(variablenew,"team_name") == 0)
{
strcpy(t[ii].team_name,valuenew);
fseek(fp, ii*sizeof(team), SEEK_SET);
fwrite(&t[ii], sizeof(teams), 1, fp);
}
else if(strcmp(variablenew,"founding_date") == 0)
{
t[ii].founding_date = atoi(valuenew) ;
fseek(fp, ii*sizeof(team), SEEK_SET);
fwrite(&t[ii], sizeof(teams), 1, fp);
}
}
}
}
}
}
gdb结果:
(gdb) run
Starting program: /home/soner/Desktop/folder/a.out
update
update team_name=newcastle,founding_date=2014 in teams where team_name=manunited
Program received signal SIGSEGV, Segmentation fault.
__strcpy_sse2_unaligned ()
at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:296
296 ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S: No such file or directory.
(gdb) backtrace
#0 __strcpy_sse2_unaligned ()
at ../sysdeps/x86_64/multiarch/strcpy-sse2-unaligned.S:296
#1 0x000000000040fa91 in wherefunc (str=0x7fffffffd7a0 "team_name",
tag=0x7fffffffdbd0 "team_name", id=0x7fffffffdbf0 "2014") at seg.c:2321
#2 0x00000000004125b8 in updatefunc (
str1=0x7fffffffdc90 "in teams where team_name=manunited\n",
str2=0x7fffffffdd00 "team_name=newcastle") at seg.c:3357
#3 0x000000000040109a in main () at seg.c:70
(gdb) frame 1
#1 0x000000000040fa91 in wherefunc (str=0x7fffffffd7a0 "team_name",
tag=0x7fffffffdbd0 "team_name", id=0x7fffffffdbf0 "2014") at seg.c:2321
2321 strcpy(id,token);
(gdb) frame 2
#2 0x00000000004125b8 in updatefunc (
str1=0x7fffffffdc90 "in teams where team_name=manunited\n",
str2=0x7fffffffdd00 "team_name=newcastle") at seg.c:3357
3357 wherefunc(tempstrsnew[c],variablenew,valuenew);
(gdb) frame 3
#3 0x000000000040109a in main () at seg.c:70
70 updatefunc(str1,str4);
(gdb)
答案 0 :(得分:0)
在 fread
之前,还可以按ftell
(等)保存文件位置。
您需要fseek
定位fwrite
之前存储的内容。
试试这个
fseek(fp, ii*sizeof(team), SEEK_SET);
fwrite(&t[ii], sizeof(teams), 1, fp);
答案 1 :(得分:0)
命令分析示例代码。
#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)
*/
要使用Command_U
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);
}
}