Re: Problem Debugging C Program
- From: John Hanley <hanley@xxxxxxxxxxx>
- Date: Tue, 28 Aug 2007 13:52:06 -0600
Willem wrote:
John wrote:
) I replaced my printf with a simple printf("hello world"). And it still ) trips the SIGSEGV at that point.
)
) Any other suggestions?
You may have trashed the stack, or you made a mistake in some file I/O.
(Such as writing to a closed file handle)
Hard to tell without looking at the source.
Check all your memory allocations and deallocations, and also make sure to
add error checking at all your file operations, especially the open().
SaSW, Willem
Sounds good. In the meantime, here is the code if you have the time to take a peek at it.
Thanks so much for your help!
John
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ENGLISH 0
#define METRIC 1
char DELIMITER='\t';
struct gps_record
{
int month;
int day;
int year;
int hour;
int min;
int sec;
double elev;
double edist;
char etime[9];
double speed;
double latitude;
double longitude;
struct gps_record * next;
struct gps_record * prev;
};
struct list
{
struct gps_record * head;
struct gps_record * tail;
};
void init_list(struct list * l)
{
l->head=NULL;
l->tail=NULL;
}
/* create a new record with provided values */
struct gps_record * new_record(int mo,
int d,
int y,
int h,
int m,
int s,
double el,
double ed,
char * et,
double sp,
double lat,
double lng)
{
struct gps_record * g;
g = (struct gps_record *) malloc(sizeof(struct gps_record));
g->month=mo;
g->day=d;
g->year=y;
g->hour=h;
g->min=m;
g->sec=s;
g->elev=el;
g->edist=ed;
strcpy(g->etime,et);
g->speed=sp;
g->latitude=lat;
g->longitude=lng;
g->next=NULL;
g->prev=NULL;
return g;
}
/* add a record to the tail of the linked list */
void add_to_tail(struct list * l, struct gps_record * g)
{
struct gps_record * temp;
if(l->head==NULL) /* if list is empty, add to head */
{
l->head = g;
l->tail = l->head;
}
else /* otherwise, add to tail */
{
temp=g;
if(l->head==l->tail) /* if only one element in list, head is also the tail */
{
(l->head)->next = temp;
temp->prev=l->head;
l->tail = temp;
}
else /* otherwise, just add right to the tail */
{
temp->prev=l->tail;
(l->tail)->next = temp;
l->tail = (l->tail)->next;
}
}
}
/* remove gps_record from linked list */
int remove_record(struct list * ls, struct gps_record * rec)
{
struct gps_record * pr;
struct gps_record * nx;
if(rec==NULL)
return 1;
pr = rec->prev;
nx = rec->next;
/* if we're removing the head */
if(pr==NULL)
{
if(nx==NULL) /* if head is only node in list */
{
ls->head=NULL;
}
else
{
nx->prev=NULL;
ls->head=nx;
}
}
/* if we're removing the tail */
else if(nx==NULL)
{
pr->next=NULL;
ls->tail=pr;
}
/* if we're removing from in the middle */
else
{
pr->next = nx;
nx->prev = pr;
}
free(rec);
return 0;
}
/* This function will parse a date in the format mm/dd/yyyy and
* return the month, day, & year */
void parse_date(int * m, int * d, int * y, char * field)
{
char temp[11];
int i=0;
int j=0;
int len=0;
int field_cnt=0;
int month=0;
int day=0;
int year=0;
len=strlen(field); /* get length of date field string */
while(j<len) /* don't keep parsing past end of string */
{
i=0;
while( field[j] != '/' ) /* parse out field delimited by '/' */
{
temp[i]=field[j]; /* create a string from the field */
j++;
i++;
if(j==len)
break;
}
temp[i]='\0'; /* terminate string */
/* convert to month, day, or year, depending on which field we are at
in our parsing */
switch(field_cnt)
{
case 0: month=atoi(temp);
break;
case 1: day=atoi(temp);
break;
case 2: year=atoi(temp);
break;
}
field_cnt++;
j++;
}
/* return variables */
*m=month;
*d=day;
*y=year;
}
void parse_time(int * h, int * m, int * s, char * field, int add)
{
char temp[9];
int i=0;
int j=0;
int len=0;
int field_cnt=0;
int hour=0;
int min=0;
int sec=0;
len=strlen(field); /* get length of date field string */
while(j<len) /* don't keep parsing past end of string */
{
i=0;
while( field[j] != ':' ) /* parse out field delimited by '/' */
{
temp[i]=field[j]; /* create a string from the field */
j++;
i++;
if(j==len)
break;
}
temp[i]='\0'; /* terminate string */
/* convert to hour, minute, or second, depending on which field we are at
in our parsing */
switch(field_cnt)
{
case 0: hour=atoi(temp);
break;
case 1: min=atoi(temp);
break;
case 2: sec=atoi(temp);
break;
}
field_cnt++;
j++;
}
hour=hour+add; /* add will add 0 if am or 12 if pm to make 24 hr time. Add determined in parse_date_time() */
/* return variables */
*h=hour;
*m=min;
*s=sec;
}
void parse_date_time(int * mo, int * d, int * y, int * h, int * m, int * s, char * field)
{
char date_str[11];
char time_str[9];
char ampm[3];
int add=0;
int month, day, year, hour, min, sec;
int po=0; /* offset the pointer to point to middle of string */
sscanf(field,"%s",date_str);
po=po+strlen(date_str)+1;
sscanf(field+po, "%s",time_str);
po=po+strlen(time_str)+1;
sscanf(field+po, "%s",ampm);
if( (strcmp(ampm,"pm")==0) || (strcmp(ampm,"PM")==0) )
add=12;
parse_date(&month,&day,&year,date_str);
parse_time(&hour,&min,&sec,time_str,add);
*mo=month;
*d=day;
*y=year;
*h=hour;
*m=min;
*s=sec;
}
/* This function will read in a field of characters from 'line' up to the delimiter and return it in 'field' */
void get_field(char * field, char * line, int *ptr_offset)
{
char f[256]={0};
int i=0;
char c='\0';
int po;
po=*ptr_offset;
while(1)
{
sscanf(line+po,"%c",&c); /* read in a char from line */
if((c==DELIMITER) || (c=='\n') || (c==EOF))
break;
f[i]=c;
i++;
po++;
}
f[i]='\0'; /* null terminate string */
/* if the string is empty, it means we hit a \t character before any other data.
so we call get_field() recursively, incrementing ptr_offset to advance the
pointer to the next character in the line.
If the character we hit was a \n or EOF, we'll just return the empty string. */
if(strlen(f)==0)
{
if(c=='\t')
{
(*ptr_offset)++;
get_field(field,line,ptr_offset);
}
else
strcpy(field,f);
}
else
strcpy(field,f);
}
/* This function will parse the latitude and longitude from a string.
* Assumption: The format of the latitude and longitude provided
* begin with N,S,E, or W characters which are
* to be stripped out. */
void get_lat_long(char * field, double * lat, double * lng)
{
char lat_str[128]={0};
char long_str[128]={0};
double n1,n2;
int po=1; /* pointer offset */
sscanf(field+po,"%s",lat_str);
po=po+strlen(lat_str)+2;
sscanf(field+po,"%s",long_str);
n1=atof(lat_str);
n2=atof(long_str);
*lat=n1;
*lng=n2;
}
/* This function will parse from a given string a value and it's unit of measurement
* and return them */
void get_value_unit_pair(char * field, double * value, char * unit)
{
char value_str[128]={0};
char unit_str[128]={0};
double n;
int po=0; /* pointer offset */
sscanf(field,"%s",value_str);
po=po+strlen(value_str)+1;
sscanf(field+po,"%s",unit_str);
n=atof(value_str);
*value=n;
strcpy(unit,unit_str);
}
double get_elevation(char * field)
{
char unit[128]={0};
double n;
get_value_unit_pair(field,&n,unit);
if( (strcmp(unit,"ft")==0) || (strcmp(unit,"FT")==0) )
n=n*0.3048;
else if( (strcmp(unit,"m")!=0) && (strcmp(unit,"M")!=0) ) /* otherwise, if it wasn't 'm', it's wrong */
{
fprintf(stderr,"Invalid elevation measure. Aborting program\n");
exit(-1);
}
return n;
}
/* This function will get the string containing the elapsed distance and unit of measurement
* and will return the elapsed distance in metres */
double get_elapsed_distance(char * field)
{
char unit[128];
double n;
get_value_unit_pair(field,&n,unit);
if( (strcmp(unit,"ft")==0) || (strcmp(unit,"FT")==0) )
n=n*0.3048; /* if elapsed distance is in ft, change to metres */
else if( (strcmp(unit,"mi")==0) || (strcmp(unit,"MI")==0) )
n=n*1609.344; /* if in miles, convert to metres */
else if( (strcmp(unit,"km")==0) || (strcmp(unit,"KM")==0) )
n=n*1000; /* if in kilometres, convert to metres */
else if( (strcmp(unit,"m")!=0) && (strcmp(unit,"M")!=0) )
{
fprintf(stderr,"Invalid elapsed distance measure. Aborting program\n");
exit(-1);
}
return n;
}
/* This function will accept the string containing the speed & unit of measurement
* and return the speed in kph */
double get_speed(char * field)
{
char unit[128];
double n;
get_value_unit_pair(field,&n,unit);
if( (strcmp(unit,"mph")==0) || (strcmp(unit,"MPH")==0) )
n=n*1.609344;
else if( (strcmp(unit,"kph")!=0) && (strcmp(unit,"KPH")!=0) )
{
fprintf(stderr,"Invalid elapsed distance measure. Aborting program\n");
exit(-1);
}
return n;
}
void print_list(struct list * l)
{
struct gps_record * temp;
temp=l->head;
while(temp!=NULL)
{
fprintf(stdout,"hello world");
temp=temp->next;
}
}
/* This function will read all the lines of an input file and populate the
* linked list.
* Return: 0 - success - upon reaching end of file
* line_num - error - return the line number of where the error occured */
int extract_records(FILE * f)
{
struct gps_record * grec;
struct list * l;
char line[512];
char * rtn;
int line_num=0;
int field_counter; /* counter for loop */
int ptr_offset=0; /* used to offset the pointer pointing to a field of data in line */
int max_fields=11; /* the max number of fields in a line from the input (GPS) file.
Currently assuming no more than 11. */
char field[256]; /* hold the field of data read in from line */
int mo;
int d;
int y;
int h;
int m;
int s;
double el;
double ed;
char * et;
double sp;
double lat;
double lng;
l=(struct list *) malloc(sizeof(struct list));
init_list(l);
while(1)
{
line_num++;
ptr_offset=0;
rtn=fgets(line,511,f);
field[0]='\0';
/* for each of the 16 fields, we'll read in the field value and process it accordingly in the switch/case */
/* 'field' string will hold the value of each field */
/* note: in space delimited fashion, each column separated by a space is considered a field
example: 1:31:03 pm (UTC-6) is considered 3 different fields */
for (field_counter=0; field_counter<8; field_counter++)
{
get_field(field,line,&ptr_offset);
if(strlen(field)==0)
{
fprintf(stderr,"Formatting error: empty field after delimiter. \n");
return line_num;
}
/* once we read in the field, we process it based on which field it is */
switch(field_counter)
{
case 1: parse_date_time(&mo,&d,&y,&h,&m,&s,field); /* parse out the date */
break;
case 2: el=get_elevation(field); /* get the elevation */
break;
case 3: ed=get_elapsed_distance(field); /* get elapsed distance */
break;
case 4: strcpy(et,field); /* get elapsed time as string */
break;
case 5: sp=get_speed(field); /* get speed */
break;
case 7: get_lat_long(field,&lat,&lng); /* get latitude & longitude */
break;
default: break;
}
ptr_offset=ptr_offset+strlen(field)+1; /* offset the pointer to point to next field of data in line */
}
grec=new_record(mo,d,y,h,m,s,el,ed,et,sp,lat,lng);
add_to_tail(l,grec);
if(rtn==NULL)
break;
}
print_list(l);
if(feof(f)==0)
return line_num;
else
return 0;
}
/* This function will examine a line of data and determine if the format
* is ENGLISH or METRIC */
int get_format(char * line)
{
char field[256]; /* hold the field of data read in from line */
int field_counter; /* counter for loop */
int ptr_offset=0; /* used to offset the pointer pointing to a field of data in line */
field[0]=0;
for (field_counter=0; field_counter<7; field_counter++)
{
sscanf(line+ptr_offset,"%s",field); /* read in a field of data from line */
if(field_counter==4)
{
/* check to see if (UTC) field is present.
If it is not, add 1 to field_counter */
if( field[0]!='(' )
field_counter++;
}
ptr_offset=ptr_offset+strlen(field)+1; /* offset the pointer to point to next field of data in line */
}
if(strcmp(field,"ft")==0)
return ENGLISH;
else
return METRIC;
}
int main(int argv, char* argc[])
{
FILE * infile;
char input_line[512];
int s=0;
int rtn=0;
infile=fopen(argc[1],"r");
fgets(input_line,511,infile); /* read in first line */
s=get_format(input_line); /* check format from first line */
rewind(infile);
switch(s)
{
case ENGLISH: printf("Reading English format file....\n");
break;
case METRIC: printf("Reading Metric format file....\n");
break;
}
rtn=extract_records(infile);
if(rtn!=0)
{
fprintf(stderr,"error reading input file %s at line %d\n",infile,rtn);
exit(-1);
}
else
{
fprintf(stderr,"Success reading file\n");
}
fclose(infile);
return 0;
}
.
- Follow-Ups:
- Re: Problem Debugging C Program
- From: CBFalconer
- Re: Problem Debugging C Program
- From: Richard Heathfield
- Re: Problem Debugging C Program
- From: Ben Pfaff
- Re: Problem Debugging C Program
- References:
- Problem Debugging C Program
- From: John Hanley
- Re: Problem Debugging C Program
- From: Willem
- Re: Problem Debugging C Program
- From: John Hanley
- Re: Problem Debugging C Program
- From: Willem
- Problem Debugging C Program
- Prev by Date: Re: Problem Debugging C Program
- Next by Date: Re: Key-press detection
- Previous by thread: Re: Problem Debugging C Program
- Next by thread: Re: Problem Debugging C Program
- Index(es):
Relevant Pages
|
|