如何在 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¶m1=%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¶m1=%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¶m1=%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¶m1=%s", ID, param);
// do request with url ...
}
也许你需要这样的东西:
char* do_endpoint_request(const char* param)
{
int sizeneeded = snprintf(NULL, 0, BASE_URL "endpoint?id=%s¶m1=%s", ID, param);
char url[sizeneeded + 1];
sprintf(url, BASE_URL "endpoint?id=%s¶m1=%s", ID, param);
// do request with url ...
}
但是如果字符串 param
的大小“合理”,那么像您的示例中那样的局部变量就足够了。
不过,您可能应该对 param
进行健全性检查,以确保其长度为 reaonable/plausible 大小。否则所有方法都可能以未定义的行为结束:
- 在您的原始代码中:如果
param
太长,url
数组将太小,您将得到未定义的行为。
- 在此答案中建议的代码中:如果
param
太长(可能长于几千,取决于您的平台和其他因素),char url[sizeneeded];
可能不会很好地结束,您'会得到未定义的行为。
我需要使用查询参数和不同的 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¶m1=%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¶m1=%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¶m1=%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¶m1=%s", ID, param);
// do request with url ...
}
也许你需要这样的东西:
char* do_endpoint_request(const char* param)
{
int sizeneeded = snprintf(NULL, 0, BASE_URL "endpoint?id=%s¶m1=%s", ID, param);
char url[sizeneeded + 1];
sprintf(url, BASE_URL "endpoint?id=%s¶m1=%s", ID, param);
// do request with url ...
}
但是如果字符串 param
的大小“合理”,那么像您的示例中那样的局部变量就足够了。
不过,您可能应该对 param
进行健全性检查,以确保其长度为 reaonable/plausible 大小。否则所有方法都可能以未定义的行为结束:
- 在您的原始代码中:如果
param
太长,url
数组将太小,您将得到未定义的行为。 - 在此答案中建议的代码中:如果
param
太长(可能长于几千,取决于您的平台和其他因素),char url[sizeneeded];
可能不会很好地结束,您'会得到未定义的行为。