【问题标题】:C getting a portion of string within a stringC在字符串中获取字符串的一部分
【发布时间】:2015-02-02 19:13:03
【问题描述】:

我正在尝试编写解析 HTTP GET 请求并检查“主机”是否为 www.bbc.co.uk 的代码。

这是我的工作代码:

char data[] = "GET /news/ HTTP/1.1\nHost: www.bbc.co.uk\nConnection: keep-alive";
    unsigned int size = strlen(data);

    if (size>3 && data[0] == 'G' && data[1] == 'E' && data[2] == 'T'){ //If GET Request
        int host_index = -1;

        for (int i=4; i<size-4; i++){
            if (data[i] == 'H' && data[i+1] == 'o' && data[i+2] == 's' && data[i+3] == 't'
                    && data[i+4] == ':' && data[i+5] == ' '){
                host_index = i+6;
            }
        }

        if ( host_index != -1 && size > host_index+11 &&
                data[host_index] == 'w' && data[host_index+1] == 'w' && data[host_index+2] == 'w' &&
                data[host_index+3] == '.' && data[host_index+4] == 'b' && data[host_index+5] == 'b' &&
                data[host_index+6] == 'c' && data[host_index+7] == '.' && data[host_index+8] == 'c' &&
                data[host_index+9] == 'o' && data[host_index+10] == '.' && data[host_index+11] == 'u' &&
                data[host_index+12] == 'k')
        {
            printf("BBC WEBSITE!\n");
        }

    }

我认为这是很多代码。我怎样才能使这段代码更紧凑?

[请将其保留为纯 C。没有 3rd 方库]

非常感谢!

【问题讨论】:

  • 这取决于你想成为多么迂腐,而这个细节在帖子中完全没有。有多少字符串需要采用预期的格式?如果你不关心,就做if strstr(data,"www.bbc.co.uk")) printf("BBC WEBSITE!\n");

标签: c string substring


【解决方案1】:

你的代码可以写得更简洁:

   if (!strncmp(data, "GET ", 4) && strstr(data, "\nHost: www.bbc.co.uk\n"))
       printf("BBC WEBSITE!\n");

但是,虽然这可能在 99.9% 的情况下有效,但它不能处理冒号后的任意空白。正则表达式会很有帮助,但这需要一个第三方库,而您没有。

一种解决方案是:

  if (!strncmp(data, "GET ", 4)) {
      const char *p = data;
      char buf[99 + 1];
      buf[0] = 0;
      while ((p = strchr(p, '\n')) && sscanf(++p, "Host: %99s", buf) != 1)
          ;
      if (!strcmp(buf, "www.bbc.co.uk"))
          printf("BBC WEBSITE!\n");
  }

编辑:上述解决方案允许"Host:" 之后的任意数量的 CR 和/或 LF。我不清楚 HTTP/1.1 LWS(线性空白)是否允许这样做。如果没有,并且要只允许零个或多个空格和制表符,请将sscanf 更改为:

   (sscanf(++p, "Host:%*[ \t]%99[^ \t]", buf) == 1 || 
    sscanf(p,   "Host:%99[^ \t]",        buf) == 1)

如您所见,它开始变得一团糟。

【讨论】:

    【解决方案2】:

    仅使用标准库函数,您可以:

    char data[] = 
        "GET /news/ HTTP/1.1\n"
        "Host: www.bbc.co.uk\n"
        "Connection: keep-alive";
    
    char *found_host = strstr(data, "Host: ");
    
    if (found_host != NULL) {
        found_host += sizeof("Host: ") - 1;
    
        char *end_of_host = strpbrk(found_host, "\r\n");
    
        if (end_of_host != NULL) {
            int equal = strncmp(found_host, "www.bbc.co.uk", end_of_host - found_host);
        }
    }
    

    请注意,这不考虑冒号和值之间的任意数量的空格。

    【讨论】:

      【解决方案3】:
      char data[] = "GET /news/ HTTP/1.1\nHost: www.bbc.co.uk\nConnection: keep-alive";
      unsigned int size = strlen(data);
      char buff[size];
      sscanf(data, "%*[^:]:%s", buff);
      if(strcmp(buff, "www.bbc.co.uk")==0)
          puts("BBC");
      

      【讨论】:

      • 也许if (sscanf(data, "%*[^\n] Host:%s", buff) == 1) ...`?
      • @chux 按需要吧。
      • 你能解释一下 sscanf 部分还是只评论那一行
      【解决方案4】:

      你为什么不使用 strstr() ?

      使用 strstr() 将大字符串拆分成块,然后通过单独的例程解析较小的块

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-06-13
        • 1970-01-01
        • 1970-01-01
        • 2017-06-19
        相关资源
        最近更新 更多