Since the number of spaces in the start and end locations is unknown, will be complex using a scanf() method. However, it can be parsed using a more 'old-school' method....
"some place 13:40 10000 some other place 14:45 10120"
First, think of each line as containing two 'way-points'; a 'start', and and 'end'. Then simplify the parsing individual way-points by using a single "way-point" parsing method.
"some place 13:40 10000", "some other place 14:45 10120"
So, there would be several ways to build the 'way-point' parser. As I looked at the problem, I didn't want to start out using a space character as a delimiter. I wanted to find some other starting point.
Each way-point contains a ':' character, so I started there. From the ':' character I went left, to find the space, and converted the space to a '\0' string termination character. That isolated the 'location' of the waypoint.
Then, from the ':', I went right, to find the space, and converted the space to a '\0' string termination character. That isolated the 'time' of the waypoint.
The odometer portion of the waypoint is easily isolated using strtoul().
My code follows here:
/***************************************************************************
** Compiler setup
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
typedef struct DRIVING_WAYPOINT_S
{
char *location;
char *time;
long odometer;
} DRIVING_WAYPOINT_T;
typedef struct DRIVING_DIARY_S
{
DRIVING_WAYPOINT_T start;
DRIVING_WAYPOINT_T end;
} DRIVING_DIARY_T;
/***************************************************************************
** Parse a waypoint.
*/
int ParseRecord(
char *I__string,
char **_O_string,
DRIVING_WAYPOINT_T *I__waypoint
)
{
int rCode=0;
char *cp, *space;
/* Parse location */
cp=strchr(I__string, ':'); /* Find the first ocurrance of ':' */
if(NULL == cp)
{
rCode=EINVAL;
fprintf(stderr, "Parse error. Time does not contain a ':'\n");
goto CLEANUP;
}
space = cp;
while(' ' != *space)
--space;
*space = '\0';
I__waypoint->location = strdup(I__string);
/* Parse time */
cp = space + 1;
space=strchr(cp, ' ');
if(NULL == space)
{
rCode=EINVAL;
fprintf(stderr, "Parse error. No space following time\n");
goto CLEANUP;
}
*space='\0';
I__waypoint->time = strdup(cp);
/* Parse odometer */
cp = space+1;
I__waypoint->odometer = strtol(cp, &cp, 10);
while(' ' == *cp)
++cp;
if(_O_string)
*_O_string = cp;
CLEANUP:
return(rCode);
}
/*******************************************************************************
** Parse the diary file.
*/
int ReadFileToDiary(
FILE *I__fp,
DRIVING_DIARY_T **IO_diary,
int *IO_diaryEntries
)
{
int rCode = 0;
char line[255+1];
for(;;)
{
DRIVING_DIARY_T *tmp;
char *cp;
/* Read the next line from the file. */
errno=0;
if(NULL == fgets(line, sizeof(line), I__fp))
{
if(feof(I__fp))
break;
rCode=errno;
fprintf(stderr, "fgets() reports: %d.\n", errno);
goto CLEANUP;
}
/* Expand the diary array for one more entry. */
tmp=realloc(*IO_diary, ((*IO_diaryEntries)+1) * sizeof(DRIVING_DIARY_T));
if(NULL == tmp)
{
rCode=ENOMEM;
fprintf(stderr, "realloc() failed.\n");
goto CLEANUP;
}
*IO_diary = tmp;
memset(&(*IO_diary)[*IO_diaryEntries], '\0', sizeof(DRIVING_DIARY_T));
/* Check for empty string. */
if('\0' == *line)
continue;
/* Parse the 'start' waypoint. */
rCode=ParseRecord(line, &cp, &(*IO_diary)[*IO_diaryEntries].start);
if(rCode)
{
fprintf(stderr, "ParseRecord(start) reports: %d\n", rCode);
goto CLEANUP;
}
/* Parse the 'end' waypoint. */
rCode=ParseRecord(cp, NULL, &(*IO_diary)[*IO_diaryEntries].end);
if(rCode)
{
fprintf(stderr, "ParseRecord(end) reports: %d\n", rCode);
goto CLEANUP;
}
/* Increment the 'diary entries' counter. */
(*IO_diaryEntries)++;
}
CLEANUP:
return(rCode);
}
/*******************************************************************************
** Free the diary array.
*/
int DiaryFree(
DRIVING_DIARY_T *diary,
int diaryEntries
)
{
int rCode=0;
int nCnt;
for(nCnt=0; nCnt<diaryEntries; ++nCnt)
{
free(diary[nCnt].start.location);
free(diary[nCnt].end.location);
free(diary[nCnt].start.time);
free(diary[nCnt].end.time);
}
free(diary);
return(rCode);
}
/*******************************************************************************
** Program start.
*/
int main()
{
int rCode = 0;
FILE *fp = NULL;
DRIVING_DIARY_T *diary = NULL;
int diaryEntries = 0;
int nCnt;
/* Open the data file. */
errno=0;
fp = fopen("test.txt", "r");
if(NULL == fp)
{
rCode=errno;
fprintf(stderr, "fopen() failed. errno:%d\n", errno);
goto CLEANUP;
}
/* Parse the file into the dynamic diary array. */
rCode=ReadFileToDiary(fp, &diary, &diaryEntries);
if(rCode)
{
fprintf(stderr, "ReadFileToDiary() reports: %d\n", rCode);
goto CLEANUP;
}
/* Print out the array. */
for(nCnt=0; nCnt < diaryEntries; ++nCnt)
{
printf("[%d] %s %s %ld %s %s %ld\n",
nCnt,
diary[nCnt].start.location,
diary[nCnt].start.time,
diary[nCnt].start.odometer,
diary[nCnt].end.location,
diary[nCnt].end.time,
diary[nCnt].end.odometer
);
}
CLEANUP:
if(diary)
DiaryFree(diary, diaryEntries);
if(fp)
fclose(fp);
return 0;
}