Home>

From Google map URL https://www.google.com/maps/@35.6896342,139.6921007,15z
Latitude double latitude, longitude double longitude, zoom value int zoom
I want to extract, assign to each variable and output. But as a condition,

 Condition 1: URL is specified from the command line argument
 Condition 2: Do not use the URL structure of url.h
 Condition 3: Do not use character string manipulation functions other than strchr

The condition is imposed. For the time being, I tried to write it up to the point where I extracted it, but honestly I am not confident and I do not know how to write in the main function.
Would you please teach me?

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct{
char *service;
char *host;
double latitude;
 double longitude;
   int zoom;
} URL;
void parse_url(const char *url_str, URL *url){
  char *p = NULL;
  char *host_path = calloc(strlen(url_str)+1, sizeof(char));
  p = strchr(host_path,'@');
  if(p == NULL) url->latitude = NULL;
  else{
    url->latitude = calloc(strlen(p)+1, sizeof(char));
   url->latitude = atoi(p+1);
    *p ='\0';
  }
  p = strchr(host_path,',');
  if(p == NULL) url->longitude = NULL;
  else{
    url->longitude = calloc(strlen(p)+1, sizeof(char));
    url->longitude = atoi(p+1);
    *p ='\0';
  }
   p = strchr(host_path,',');
  if(p == NULL) url->zoom = NULL;
  else{
    url->zoom = calloc(strlen(p)+1, sizeof(char));
    url->zoom = atoi(p+1);
    *p ='\0';
  }
}

int main(int argc, char *argv[]){

printf("Latitude:%d Longitude:%d Zoom value:%d\n", latitude, longitude, zoom);
}
c
  • Answer # 1

    #include<stdio.h>// sscanf
    #include<stdlib.h>// strtod
    #include<string.h>// strchr
    typedef struct {
        char *service;
        char *host;
        double latitude;
        double longitude;
        int zoom;
    } URL;
    void parse_url(const char *url_str, URL *url)
    {
        url->service = url->host = NULL;
        url->latitude = url->longitude = url->zoom = 0;
        char *p = strchr(url_str,'@');
        if (p == NULL) return;
        char *q;
        url->latitude = strtod(++p,&q);
        if (q == p) return;
        url->longitude = strtod(++q,&p);
        if (p == q) return;
        url->zoom = strtol(++p,&q, 10);
    }
    int main(int argc, char *argv[])
    {
        if (argc != 2) return 1;
        // argv[1] = "https://www.google.com/maps/@35.6896342,139.6921007,15z";
        URL url;
        parse_url(argv[1],
    &url);
        printf("Latitude:%.7f Longitude:%.7f Zoom value:%d\n",
            url.latitude, url.longitude, url.zoom);
    }


    Another solution (I also added reading of service and host)

    #include<stdio.h>// sscanf
    #include<string.h>// strdup
    typedef struct {
        char *service;
        char *host;
        double latitude;
        double longitude;
        int zoom;
    } URL;
    void parse_url(const char *url_str, URL *url)
    {
        char service[32];
        char host[128];
        if (sscanf(url_str, "%31[^:]://%127[^/]/%*[^@]@%lf,%lf,%d", service,
                host,&url->latitude,&url->longitude,&url->zoom) == 5) (
            url->service = strdup(service);
            url->host = strdup(host);
        }
        else {
            url->service = url->host = NULL;
            url->latitude = url->longitude = url->zoom = 0;
        }
    }
    int main(int argc, char *argv[])
    {
        if (argc != 2) return 1;
        // argv[1] = "https://www.google.com/maps/@35.6896342,139.6921007,15z";
        URL url;
        parse_url(argv[1],
    &url);
        printf("Latitude:%.7f Longitude:%.7f Zoom value:%d\n",
            url.latitude, url.longitude, url.zoom);}


    Please comment.

  • Answer # 2

    Uh,atoiThat's why I don't think that number generation function is a string operation function.
    Apparently, the source that is presented has "a trace of trying to hold latitude etc. in a character string (such as calloc)".

    #include<stdio.h>#include<stdlib.h>#include<string.h>#include<math.h>typedef struct {
      char *service;
      char *host;
      double latitude;
      double longitude;
      int zoom;
    } URL;
    void parse_url(const char *url_str, URL *url) {
      char *p;
      url->latitude = url->longitude = NAN;
      url->zoom = 0;
      p = strchr(url_str,'@');
      if (p == NULL) {
        return;
      }
      url->latitude = strtod(p + 1, NULL);
      p = strchr(p + 1,',');
      if (p == NULL) {
        return;
      }
      url->longitude = strtod(p + 1, NULL);
      p = strchr(p + 1,',');
      if (p == NULL) {
        return;
      }
      url->zoom = strtol(p + 1, NULL, 10);
    }
    int main(int argc, char *argv[]) {
      URL url;
      if (argc<= 1) {
        puts("Specify Google MAP URL in argument");
        return 1;
      }
      parse_url(argv[1],
    &url);
      printf("Latitude:%.7lf Longitude:%.7lf Zoom value:%d\n", url.latitude, url.longitude,
             url.zoom);
      return 0;
    }

  • Answer # 3

    There are some problems.

    1. Error handling after calling strchr
    if(p == NULL) url->longitude = NULL;

    See some code like, but NULL should only be used for pointer types. Also, when an error occurs, you should immediately exit the function and notify the caller of the error instead of continuing.

    This time you don't need that much complicated error handling, so justboolUse molds.stdbool.hRequires include.

    Then

    if(p == NULL) return false;

    It looks like.

    2. Secure mysterious memory
    char *host_path = calloc(strlen(url_str)+1, sizeof(char));
    url->latitude = calloc(strlen(p)+1, sizeof(char));

    I have no idea what I wanted to do. Delete.

    3. Rewrite the url on error

    Rewriting the caller when there is an error during processing is not a very good design. Therefore

    bool parse_url(const char *url_str, URL *dest_url){
      URL url;
      //do something
      *dest_url = url;
      return true;
    }

    Like If this happens, it will not be rewritten. Structures can be copied with = assignment.

    4. Don't use atoi

    atoiCannot know if the string was converted correctly

    I can not know the position of the character string immediately after conversion

    There is a problem. In the first placeatoiIs a conversion to an integerdoubleIt can't be used for conversion to type.

    insteadstrtod/strtolTo use. How to use
    Safely get numbers from standard input in C
    Look at

    strtod/strtolThe second argument passed toendptrA pointer to the character immediately after the conversion is returned to. In other wordsstrchrYou don't have to call.

    result
    #include<stdio.h>#include<stdlib.h>#include<string.h>#include<errno.h>#include<stdbool.h>enum {
      // 21 seems to be the maximum
      ZOOM_MAX = 21,
    };
    typedef struct{
      char *service;
      char *host;
      double latitude;
      double longitude;
      int zoom;
    } URL;
    bool parse_url(const char *url_str, URL *dest_url){
      char *p = strchr(url_str,'@');
      if(p == NULL) return false;
      ++p;
      URL url;
      // Needed to know if strtod converted correctly and for subsequent processing
      char* endptr = p;
      // reset errno before calling strtod
      errno = 0;
      url.latitude = strtod(p,&endptr);
      if (0 != errno || (0 == url.latitude&&endptr == p)) return false;
      // endptr is a pointer to the character immediately following the number
      if (endptr[0] !=',') return false;
      p = endptr + 1;
      errno = 0;
      url.longitude = strtod(p,&endptr);
      if (0 != errno || (0 == url.longitude&&endptr == p)) return false;
      // endptr is a pointer to the character immediately following the number
      if (endptr[0] !=',') return false;
      p = endptr + 1;
      errno = 0;
      long z = strtol(p,&endptr, 10);
      if (0 != errno || (0 == z&&endptr == p) || z<0 || ZOOM_MAX<z) return false;
      url.zoom = (int)z;
      if (endptr[0] !='z') return false;
      *dest_url = url;
      return true;
    }
    int main(int argc, char *argv[]){
      if (argc != 2) return 1;
      URL url;
      if (!parse_url(argv[1],
    &url)) return 2;
      printf("Latitude:%f Longitude:%f Zoom value:%d\n", url.latitude, url.longitude, url.zoom);
      return 0;
    }

    How is it like this?

    https://wandbox.org/permlink/dd8yA6Gb4aHNILDg

Related articles