如何在 C 中动态构建 Url

How to build Url dynamically in C

我需要使用查询参数和不同的 API 端点构建一个 url。我不喜欢使用固定大小的char数组,因为会浪费内存,我希望大小足够大。

#define BASE_URL  "https//mydomain.com/api/"
#define ID "ID1"

char* do_endpoint_request(const char* param)
{
   char url[500];
   snprintf(url, sizeof(url), BASE_URL "endpoint?id=%s&param1=%s", ID, param);
   // do request with url ...

}

我如何改进这段代码,内存是根据注入的字符串和参数的确切大小动态分配的?

在这种情况下,我们需要参数的大小。

char* do_endpoint_request(const char* param, int param_size)
{
   char* url = calloc(param_size + <size of base url>, sizeof(char));
   snprintf(url, sizeof(url), BASE_URL "endpoint?id=%s&param1=%s", ID, param);
   // do request with url ...

}

像这样的东西应该可以正常工作,但分配的大小可能需要更改。

您可以使用 snprintf() 可以用 NULL 而不是实际缓冲区调用这一事实,并且它 returns 如果有足够的 space。所以:

#define BASE_URL  "https//mydomain.com/api/"
#define ID "ID1"

char* do_endpoint_request(const char* param)
{
   int len;

   len = snprintf(NULL, 0, BASE_URL "endpoint?id=%s&param1=%s", ID, param);    
   char url[len+1]; // len excludes NULL; use malloc() if you can't use VLA
   // sprintf() is ok now, url is guaranteed to be large enough
   sprintf(url, BASE_URL "endpoint?id=%s&param1=%s", ID, param);
   // do request with url ...

}

也许你需要这样的东西:

char* do_endpoint_request(const char* param)
{
   int sizeneeded = snprintf(NULL, 0, BASE_URL "endpoint?id=%s&param1=%s", ID, param);

   char url[sizeneeded + 1];
   sprintf(url, BASE_URL "endpoint?id=%s&param1=%s", ID, param);

   // do request with url ...
}

但是如果字符串 param 的大小“合理”,那么像您的示例中那样的局部变量就足够了。

不过,您可能应该对 param 进行健全性检查,以确保其长度为 reaonable/plausible 大小。否则所有方法都可能以未定义的行为结束:

  • 在您的原始代码中:如果 param 太长,url 数组将太小,您将得到未定义的行为。
  • 在此答案中建议的代码中:如果 param 太长(可能长于几千,取决于您的平台和其他因素),char url[sizeneeded]; 可能不会很好地结束,您'会得到未定义的行为。