In the ``do-it-yourself'' part, the header line was only used for consistency checking, for example for the nodes file
{} // process header line: for ( int ii=1; ii<=NTOKENS; ++ii ) { inFile >> aString ; switch( ii ) { case 1: assert( aString=="ID" ) ; break ; case 2: assert( aString=="EASTING" ) ; break ; case 3: assert( aString=="NORTHING" ) ; break ; } }
A more robust alternative would be to use the header line as an indication of what each column contains. Processing of the header line would essentially become
{} // process header line: for ( int ii=1; ii<=NTOKENS; ++ii ) { inFile >> aString ; if ( aString=="ID" ) { column_id=ii ; } else if ( aString=="EASTING" ) { column_east=ii ; ... } }
These columns would later be used during the file reading, for example via
{} // main loop: while( !inFile.eof() ) { ... for ( int ii=1; ii<=NTOKENS ; ii++ ) { if ( ii==column_id ) { inFile >> nodeId ; } else ( ii==column_east ) { inFile >> xCoord ; ... } } }
This is in fact not much more work to program, and considerably more robust. The main reason why it was not introduced ealier is that it does not solve one of the main inconveniences, which is the parsing of the route-plans file. The problem with route-plans is that they are not column-oriented, and they cannot be, since the number of nodes in a route is changing from one route to the next. The next section discusses a robust way out of this dilemma.