DMS to Decimal By Request

This is a function from my library that can be used to decode a degrees-minutes-seconds (DMS) string to a decimal degrees.
Enjoy.

/* ------------------------------
   Function: geo_dms_to_deg
     Parse a degrees-minutes-seconds (DMS) value string into a double floating
     point in degrees.
 
   Parameters:
     str     - [in]  string containing an angle in DMS
     end_ptr - [out] a pointer to the character following the last in the DMS
     packed  - [in]  boolean whether to expect the DMS to lack delimiters
     value   - [out] value in degrees
 
   Returns:
     true on success, false on failure
   ------------------------------ */
int geo_dms_to_deg( const char *str, const char **endptr, int packed, double *value ) {
  int d = -1, m = -1, s = -1, pos = 0;
  char ps[20] = "", *ps_ptr;
  float p = 0.0, fraction;
 
  if( packed ) {
    char format[64] = "";
 
    pos = strspn( str, "0123456789" );
    if( pos < 5 || pos > 7 )
      return( 0 );
 
    snprintf( format, 64, "%%%dd%%2d%%2d%%n", pos - 4 );
    if( sscanf( str, format, &d, &m, &s, &pos ) != 3 )
      return( 0 );
  } else if( sscanf( str, "%d:%d:%d.%[0123456789]%n", &d, &m, &s, ps, &pos ) == 4 ) {
    p = 0.0;
    fraction = 0.1;
    for( ps_ptr = ps; *ps_ptr != '\0'; ps_ptr++ ) {
      p += (*ps_ptr - '0')*fraction;
      fraction *= 0.1;
    }
  } else if( sscanf( str, "%d:%d:%d%n", &d, &m, &s, &pos ) == 3 ) {
    /* empty */
  } else if( sscanf( str, "%d:%d%n", &d, &m, &pos ) == 2 ) {
    s = 0;
  } else if( sscanf( str, "%d%n", &d, &pos ) == 1 ) {
    s = 0;
    m = 0;
  } else {
    return( 0 );
  }
  if (d < 0) return 0;
  if (m < 0 || m >= 60) return 0;
  if (s < 0 || s >= 60) return 0;
 
  *endptr = &str[pos];
 
  if( value )
    *value = d + m/60.0 + (p + (float)s)/3600.0;
 
  return( 1 );
}
    . You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

    Leave a Reply


    Bad Behavior has blocked 149 access attempts in the last 7 days.