user14767: I am using the SIM908 module to get GPS position.
The SIM908 sends the latitude and longitude in the ddmm.mmmm format, but major online services for GPS location (for example, Google Earth) use the dd.dddd format.
So, how can I modify my code to convert coordinates from the SIM908 to dd.dddd format? 
This is the SIM908 GSM Library Code that I am using:
#include "gps.h"
char GPSGSM::getBattInf(char *str_perc, char *str_vol)
{
     char ret_val=0;
     char *p_char;
     char *p_char1;

     gsm.SimpleWriteln("AT+CBC");
     gsm.WaitResp(5000, 100, "OK");
     if(gsm.IsStringReceived("+CBC"))
          ret_val=1;

     //BCL
     p_char = strchr((char *)(gsm.comm_buf),',');
     p_char1 = p_char+1;  //we are on the first char of BCS
     p_char = strchr((char *)(p_char1), ',');
     if (p_char != NULL) {
          *p_char = 0;
     }
     strcpy(str_perc, (char *)(p_char1));

     //Voltage
     p_char++;
     p_char1 = strchr((char *)(p_char), '\r');
     if (p_char1 != NULL) {
          *p_char1 = 0;
     }
     strcpy(str_vol, (char *)(p_char));
     return ret_val;
}

char GPSGSM::getBattTVol(char *str_vol)
{
     char *p_char;
     char *p_char1;
     char ret_val=0;

     gsm.SimpleWriteln("AT+CBTE?");
     gsm.WaitResp(5000, 100, "OK");
     if(gsm.IsStringReceived("+CBTE"))
          ret_val=1;

     //BCL
     p_char = strchr((char *)(gsm.comm_buf),':');
     p_char1 = p_char+2;  //we are on the first char of BCS
     p_char = strchr((char *)(p_char1), '\r');
     if (p_char != NULL) {
          *p_char = 0;
     }
     strcpy(str_vol, (char *)(p_char1));
     return ret_val;
}

char GPSGSM::attachGPS()
{
     if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSPWR=1", 500, 100, "OK", 5))
          return 0;
     if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSRST=1", 500, 100, "OK", 5))
          return 0;
     return 1;
}

char GPSGSM::deattachGPS()
{
     if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSPWR=0", 500, 100, "OK", 5))
          return 0;
     return 1;
}

char GPSGSM::getStat()
{
     char ret_val=-1;
     gsm.SimpleWriteln("AT+CGPSSTATUS?");
     gsm.WaitResp(5000, 100, "OK");
     if(gsm.IsStringReceived("Unknown")||gsm.IsStringReceived("unknown"))
          ret_val=0;
     else if(gsm.IsStringReceived("Not"))
          ret_val=1;
     else if(gsm.IsStringReceived("2D")||gsm.IsStringReceived("2d"))
          ret_val=2;
     else if(gsm.IsStringReceived("3D")||gsm.IsStringReceived("3d"))
          ret_val=3;
     return ret_val;
}

char GPSGSM::getPar(char *str_long, char *str_lat, char *str_alt, char *str_time, char *str_speed )
{
     char ret_val=0;
     char *p_char;
     char *p_char1;
     gsm.SimpleWriteln("AT+CGPSINF=0");
     gsm.WaitResp(5000, 100, "OK");
     if(gsm.IsStringReceived("OK"))
          ret_val=1;

     //longitude
     p_char = strchr((char *)(gsm.comm_buf),',');
     p_char1 = p_char+1;  //we are on the first char of longitude
     p_char = strchr((char *)(p_char1), ',');
     if (p_char != NULL) {
          *p_char = 0;
     }
     strcpy(str_long, (char *)(p_char1));

     // latitude
     p_char++;
     p_char1 = strchr((char *)(p_char), ',');
     if (p_char1 != NULL) {
          *p_char1 = 0;
     }
     strcpy(str_lat, (char *)(p_char));

     // altitude
     p_char1++;
     p_char = strchr((char *)(p_char1), ',');
     if (p_char != NULL) {
          *p_char = 0;
     }
     strcpy(str_alt, (char *)(p_char1));

     // UTC time
     p_char++;
     p_char1 = strchr((char *)(p_char), ',');
     if (p_char1 != NULL) {
          *p_char1 = 0;
     }
     strcpy(str_time, (char *)(p_char));

     // TTFF
     p_char1++;
     p_char = strchr((char *)(p_char1), ',');
     if (p_char != NULL) {
          *p_char = 0;
     }

     // num
     p_char++;
     p_char1 = strchr((char *)(p_char), ',');
     if (p_char1 != NULL) {
          *p_char1 = 0;
     }

     // speed
     p_char1++;
     p_char = strchr((char *)(p_char1), ',');
     if (p_char != NULL) {
          *p_char = 0;
     }
     strcpy(str_speed, (char *)(p_char1));

     return ret_val;
}

void parseTime(char *field, int *time)
{
     ////////////////Time////////////
     char tmp[4];
     tmp[2]=0; // Init tmp and null terminate
     tmp[0] = field[8];
     tmp[1] = field[9];
     time[0] = atoi(tmp); // Hours
     tmp[0] = field[10];
     tmp[1] = field[11];
     time[1] = atoi(tmp); // Minutes
     tmp[0] = field[12];
     tmp[1] = field[13];
     time[2] = atoi(tmp); // Seconds
     /////////////Date///////////////
     tmp[0] = field[0];
     tmp[1] = field[1];
     tmp[2] = field[2];
     tmp[3] = field[3];
     tmp[4]=0; // Init tmp and null terminate
     time[3] = atoi(tmp); // year
     tmp[0] = field[4];
     tmp[1] = field[5];
     tmp[2]=0; // Init tmp and null terminate
     time[4] = atoi(tmp); // month
     tmp[0] = field[6];
     tmp[1] = field[7];
     tmp[2]=0; // Init tmp and null terminate
     time[5] = atoi(tmp); // day
}

// Read the latitude in decimal format from a GGA string
double convertLat(char* latString)
{
     double latitude = atof(latString);                                    // convert to a double (precise)
     int deg = (int) latitude / 100;                               // extract the number of degrees
     double min = latitude - (100 * deg);                  // work out the number of minutes
     latitude = deg + (double) min/60.0;                   // convert to decimal format
     return latitude;
}

// Read the longitude in decimal format from a GGA string
double convertLong(char* longString)
{
     double longitude = atof(longString);                                  // convert to a double
     int deg = (int) longitude / 100;                              // extract the number of degrees
     double min = longitude - (100 * deg);                 // work out the number of minutes
     longitude = deg + (double) min/60.00;                 // convert to decimal format
     return longitude;
}


user7508: This could be a general programming question. The only thing specific to
Arduino here is that you may want a solution that minimizes the use of
memory and avoids floating point operations.
Here is a memory-friendly solution that reformats the string in place,
i.e. it overwrites the original string. In many cases this is
appropriate, as it is unlikely that you need the original string later,
but you have to make sure it fits your application. It works by first
moving a few characters around in order to have the format "dd.mmmmm",
then parsing the minutes and converting to fractional degrees, then
writing that in ASCII.
It should be noted that the only reason for dropping the last digit in
the minutes field is to avoid 32-bit operations. I compiled for an Uno
and checked the generated assembly: it uses only four bytes of RAM, in
the stack.
// Convert the format of a latitude from "ddmm.mmmm" to "dd.dddd".
// The string is converted in place.
void convertLat(char* s)
{
    // Convert ddmm.mmmm to dd.mmmmm
    s[4] = s[3];  // move minutes
    s[3] = s[2];  // move tens of minutes
    s[2] = '.';   // put decimal point
    s[8] = '\0';  // drop last digit

    // Compute fractional degrees.
    uint16_t fraction = atoi(s + 3);  // unit = 1e-3 arcmin
    fraction /= 6;                    // unit = 1e-4 deg

    // Write in ASCII, right to left.
    s[7] = '\0';
    for (int i = 6; i > 2; i--) {
        s[i] = fraction % 10 + '0';
        fraction /= 10;
    }
}

You can use this same function to convert a longitude from "dddmm.mmmm"
to "ddd.dddd" by just skipping the first character:
static inline void convertLon(char* s)
{
    convertLat(s + 1);
}


Addendum: To answer Lipsyor comment, it is possible to have the
latitude in units of 1e-6 deg by using 32-bit arithmetic:
// Convert the format of a latitude from "ddmm.mmmm" to "dd.dddddd".
// The string is converted in place.
void convertLat(char* s)
{
    // Convert ddmm.mmmm to dd.mmmmmm
    s[4] = s[3];  // move minutes
    s[3] = s[2];  // move tens of minutes
    s[2] = '.';   // put decimal point

    // Compute fractional degrees.
    uint32_t fraction = atol(s + 3);     // unit = 1e-4 arcmin
    fraction = (fraction * 10 + 3) / 6;  // unit = 1e-6 deg

    // Write in ASCII, right to left.
    for (int i = 8; i > 2; i--) {
        s[i] = fraction % 10 + '0';
        fraction /= 10;
    }
}

The + 3 in the computation is only to round to nearest. Dropping this
term should not make any significant difference.

14767: <p>I am using the SIM908 module to get GPS position.</p>

<p>The SIM908 sends the latitude and longitude in the <code>ddmm.mmmm</code> format, but major online services for GPS location (for example, Google Earth) use the <code>dd.dddd</code> format.</p>

<p>So, how can I modify my code to convert coordinates from the SIM908 to <code>dd.dddd</code> format? </p>

<p>This is the SIM908 GSM Library Code that I am using:</p>

<pre><code>#include "gps.h"
char GPSGSM::getBattInf(char *str_perc, char *str_vol)
{
     char ret_val=0;
     char *p_char;
     char *p_char1;

     gsm.SimpleWriteln("AT+CBC");
     gsm.WaitResp(5000, 100, "OK");
     if(gsm.IsStringReceived("+CBC"))
          ret_val=1;

     //BCL
     p_char = strchr((char *)(gsm.comm_buf),',');
     p_char1 = p_char+1;  //we are on the first char of BCS
     p_char = strchr((char *)(p_char1), ',');
     if (p_char != NULL) {
          *p_char = 0;
     }
     strcpy(str_perc, (char *)(p_char1));

     //Voltage
     p_char++;
     p_char1 = strchr((char *)(p_char), '\r');
     if (p_char1 != NULL) {
          *p_char1 = 0;
     }
     strcpy(str_vol, (char *)(p_char));
     return ret_val;
}

char GPSGSM::getBattTVol(char *str_vol)
{
     char *p_char;
     char *p_char1;
     char ret_val=0;

     gsm.SimpleWriteln("AT+CBTE?");
     gsm.WaitResp(5000, 100, "OK");
     if(gsm.IsStringReceived("+CBTE"))
          ret_val=1;

     //BCL
     p_char = strchr((char *)(gsm.comm_buf),':');
     p_char1 = p_char+2;  //we are on the first char of BCS
     p_char = strchr((char *)(p_char1), '\r');
     if (p_char != NULL) {
          *p_char = 0;
     }
     strcpy(str_vol, (char *)(p_char1));
     return ret_val;
}

char GPSGSM::attachGPS()
{
     if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSPWR=1", 500, 100, "OK", 5))
          return 0;
     if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSRST=1", 500, 100, "OK", 5))
          return 0;
     return 1;
}

char GPSGSM::deattachGPS()
{
     if(AT_RESP_ERR_DIF_RESP == gsm.SendATCmdWaitResp("AT+CGPSPWR=0", 500, 100, "OK", 5))
          return 0;
     return 1;
}

char GPSGSM::getStat()
{
     char ret_val=-1;
     gsm.SimpleWriteln("AT+CGPSSTATUS?");
     gsm.WaitResp(5000, 100, "OK");
     if(gsm.IsStringReceived("Unknown")||gsm.IsStringReceived("unknown"))
          ret_val=0;
     else if(gsm.IsStringReceived("Not"))
          ret_val=1;
     else if(gsm.IsStringReceived("2D")||gsm.IsStringReceived("2d"))
          ret_val=2;
     else if(gsm.IsStringReceived("3D")||gsm.IsStringReceived("3d"))
          ret_val=3;
     return ret_val;
}

char GPSGSM::getPar(char *str_long, char *str_lat, char *str_alt, char *str_time, char *str_speed )
{
     char ret_val=0;
     char *p_char;
     char *p_char1;
     gsm.SimpleWriteln("AT+CGPSINF=0");
     gsm.WaitResp(5000, 100, "OK");
     if(gsm.IsStringReceived("OK"))
          ret_val=1;

     //longitude
     p_char = strchr((char *)(gsm.comm_buf),',');
     p_char1 = p_char+1;  //we are on the first char of longitude
     p_char = strchr((char *)(p_char1), ',');
     if (p_char != NULL) {
          *p_char = 0;
     }
     strcpy(str_long, (char *)(p_char1));

     // latitude
     p_char++;
     p_char1 = strchr((char *)(p_char), ',');
     if (p_char1 != NULL) {
          *p_char1 = 0;
     }
     strcpy(str_lat, (char *)(p_char));

     // altitude
     p_char1++;
     p_char = strchr((char *)(p_char1), ',');
     if (p_char != NULL) {
          *p_char = 0;
     }
     strcpy(str_alt, (char *)(p_char1));

     // UTC time
     p_char++;
     p_char1 = strchr((char *)(p_char), ',');
     if (p_char1 != NULL) {
          *p_char1 = 0;
     }
     strcpy(str_time, (char *)(p_char));

     // TTFF
     p_char1++;
     p_char = strchr((char *)(p_char1), ',');
     if (p_char != NULL) {
          *p_char = 0;
     }

     // num
     p_char++;
     p_char1 = strchr((char *)(p_char), ',');
     if (p_char1 != NULL) {
          *p_char1 = 0;
     }

     // speed
     p_char1++;
     p_char = strchr((char *)(p_char1), ',');
     if (p_char != NULL) {
          *p_char = 0;
     }
     strcpy(str_speed, (char *)(p_char1));

     return ret_val;
}

void parseTime(char *field, int *time)
{
     ////////////////Time////////////
     char tmp[4];
     tmp[2]=0; // Init tmp and null terminate
     tmp[0] = field[8];
     tmp[1] = field[9];
     time[0] = atoi(tmp); // Hours
     tmp[0] = field[10];
     tmp[1] = field[11];
     time[1] = atoi(tmp); // Minutes
     tmp[0] = field[12];
     tmp[1] = field[13];
     time[2] = atoi(tmp); // Seconds
     /////////////Date///////////////
     tmp[0] = field[0];
     tmp[1] = field[1];
     tmp[2] = field[2];
     tmp[3] = field[3];
     tmp[4]=0; // Init tmp and null terminate
     time[3] = atoi(tmp); // year
     tmp[0] = field[4];
     tmp[1] = field[5];
     tmp[2]=0; // Init tmp and null terminate
     time[4] = atoi(tmp); // month
     tmp[0] = field[6];
     tmp[1] = field[7];
     tmp[2]=0; // Init tmp and null terminate
     time[5] = atoi(tmp); // day
}

// Read the latitude in decimal format from a GGA string
double convertLat(char* latString)
{
     double latitude = atof(latString);                                    // convert to a double (precise)
     int deg = (int) latitude / 100;                               // extract the number of degrees
     double min = latitude - (100 * deg);                  // work out the number of minutes
     latitude = deg + (double) min/60.0;                   // convert to decimal format
     return latitude;
}

// Read the longitude in decimal format from a GGA string
double convertLong(char* longString)
{
     double longitude = atof(longString);                                  // convert to a double
     int deg = (int) longitude / 100;                              // extract the number of degrees
     double min = longitude - (100 * deg);                 // work out the number of minutes
     longitude = deg + (double) min/60.00;                 // convert to decimal format
     return longitude;
}
</code></pre>
 7508: <p>This could be a general programming question. The only thing specific to
Arduino here is that you may want a solution that minimizes the use of
memory and avoids floating point operations.</p>

<p>Here is a memory-friendly solution that reformats the string <em>in place</em>,
i.e. it overwrites the original string. In many cases this is
appropriate, as it is unlikely that you need the original string later,
but you have to make sure it fits your application. It works by first
moving a few characters around in order to have the format "dd.mmmmm",
then parsing the minutes and converting to fractional degrees, then
writing that in ASCII.</p>

<p>It should be noted that the only reason for dropping the last digit in
the minutes field is to avoid 32-bit operations. I compiled for an Uno
and checked the generated assembly: it uses only four bytes of RAM, in
the stack.</p>



<pre class="lang-cpp prettyprint-override"><code>// Convert the format of a latitude from "ddmm.mmmm" to "dd.dddd".
// The string is converted in place.
void convertLat(char* s)
{
    // Convert ddmm.mmmm to dd.mmmmm
    s[4] = s[3];  // move minutes
    s[3] = s[2];  // move tens of minutes
    s[2] = '.';   // put decimal point
    s[8] = '\0';  // drop last digit

    // Compute fractional degrees.
    uint16_t fraction = atoi(s + 3);  // unit = 1e-3 arcmin
    fraction /= 6;                    // unit = 1e-4 deg

    // Write in ASCII, right to left.
    s[7] = '\0';
    for (int i = 6; i &gt; 2; i--) {
        s[i] = fraction % 10 + '0';
        fraction /= 10;
    }
}
</code></pre>

<p>You can use this same function to convert a longitude from "dddmm.mmmm"
to "ddd.dddd" by just skipping the first character:</p>

<pre class="lang-cpp prettyprint-override"><code>static inline void convertLon(char* s)
{
    convertLat(s + 1);
}
</code></pre>

<hr>

<p><strong>Addendum</strong>: To answer Lipsyor comment, it is possible to have the
latitude in units of 1e-6 deg by using 32-bit arithmetic:</p>

<pre class="lang-cpp prettyprint-override"><code>// Convert the format of a latitude from "ddmm.mmmm" to "dd.dddddd".
// The string is converted in place.
void convertLat(char* s)
{
    // Convert ddmm.mmmm to dd.mmmmmm
    s[4] = s[3];  // move minutes
    s[3] = s[2];  // move tens of minutes
    s[2] = '.';   // put decimal point

    // Compute fractional degrees.
    uint32_t fraction = atol(s + 3);     // unit = 1e-4 arcmin
    fraction = (fraction * 10 + 3) / 6;  // unit = 1e-6 deg

    // Write in ASCII, right to left.
    for (int i = 8; i &gt; 2; i--) {
        s[i] = fraction % 10 + '0';
        fraction /= 10;
    }
}
</code></pre>

<p>The <code>+ 3</code> in the computation is only to round to nearest. Dropping this
term should not make any significant difference.</p>
